/*
Copyright (C) 2013 Tom Bachmann
This file is part of FLINT.
FLINT is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See .
*/
#ifndef ARITHXX_H
#define ARITHXX_H
#include "arith.h"
#include "fmpq_polyxx.h"
#include "fmpqxx.h"
#include "fmpz_matxx.h"
#include "fmpz_vecxx.h"
#include "fmpzxx.h"
#include "nmod_vecxx.h"
// TODO namespace arith?
// TODO arith_hrr_expsum_factored
// TODO codegen / vector improvements
namespace flint {
namespace detail {
template
inline typename T::wrapped_traits::data_srcref_t extract_data(const T& t,
typename mp::enable_if >::type* = 0)
{
return t._data().inner;
}
template
inline typename T::wrapped_traits::data_ref_t extract_data(T& t,
typename mp::enable_if >::type* = 0)
{
return t._data().inner;
}
template
const T& extract_data(const T& t,
typename mp::disable_if >::type* = 0)
{
return t;
}
template
typename T::arrayref_t extract_data(T& t,
typename mp::disable_if >::type* = 0,
typename mp::enable_if,
rules::FMPQ_VECXX_COND_S > >::type* = 0)
{
return t._array();
}
}
#define ARITHXX_DEFINE_UNOP(name, Return, Cond) \
FLINT_DEFINE_UNOP(name) \
namespace rules { \
FLINT_DEFINE_UNARY_EXPR_COND(name##_op, Return, Cond, \
arith_##name(detail::extract_data(to), detail::extract_data(from))) \
}
#define ARITHXX_DEFINE_BINOP(name, Return, Cond1, Cond2) \
FLINT_DEFINE_BINOP(name) \
namespace rules { \
FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, Return, Cond1, Cond2, \
arith_##name(detail::extract_data(to), detail::extract_data(e1), \
detail::extract_data(e2))) \
}
namespace at {
template struct slong : traits::fits_into_slong { };
template struct ulong : traits::is_unsigned_integer { };
} // at
ARITHXX_DEFINE_UNOP(primorial, fmpzxx, at::slong)
ARITHXX_DEFINE_UNOP(harmonic_number, fmpqxx, at::slong)
ARITHXX_DEFINE_BINOP(stirling_number_1u, fmpzxx, at::slong, at::slong)
ARITHXX_DEFINE_BINOP(stirling_number_1, fmpzxx, at::slong, at::slong)
ARITHXX_DEFINE_BINOP(stirling_number_2, fmpzxx, at::slong, at::slong)
ARITHXX_DEFINE_BINOP(stirling_number_1u_vec, fmpz_vecxx, at::slong, at::slong)
ARITHXX_DEFINE_BINOP(stirling_number_1_vec, fmpz_vecxx, at::slong, at::slong)
ARITHXX_DEFINE_BINOP(stirling_number_2_vec, fmpz_vecxx, at::slong, at::slong)
FLINT_DEFINE_BINOP(stirling_number_1u_vec_next)
FLINT_DEFINE_BINOP(stirling_number_1_vec_next)
FLINT_DEFINE_BINOP(stirling_number_2_vec_next)
FLINT_DEFINE_BINOP(stirling_matrix_1u)
FLINT_DEFINE_BINOP(stirling_matrix_1)
FLINT_DEFINE_BINOP(stirling_matrix_2)
namespace vectors {
template<>
struct outsize
{
template
static unsigned get(const Expr& e) {return e._data().second();}
};
template<> struct outsize
: outsize { };
template<> struct outsize
: outsize { };
template<>
struct outsize
{
template
static unsigned get(const Expr& e)
{
slong r = e._data().first().size();
if(r == e._data().second())
return r + 1;
return r;
}
};
template<> struct outsize
: outsize { };
template<> struct outsize
: outsize { };
} // vectors
namespace matrices {
template<>
struct outsize
{
template
static slong rows(const Expr& e) {return e._data().first();}
template
static slong cols(const Expr& e) {return e._data().second();}
};
template<> struct outsize
: outsize { };
template<> struct outsize
: outsize { };
} // matrices
namespace rules {
FLINT_DEFINE_BINARY_EXPR_COND2(stirling_number_1u_vec_next_op, fmpz_vecxx,
FMPZ_VECXX_COND_S, at::slong,
arith_stirling_number_1u_vec_next(to._array(), e1._array(), e2,
e1.size() + (e1.size() == e2)))
FLINT_DEFINE_BINARY_EXPR_COND2(stirling_number_1_vec_next_op, fmpz_vecxx,
FMPZ_VECXX_COND_S, at::slong,
arith_stirling_number_1_vec_next(to._array(), e1._array(), e2,
e1.size() + (e1.size() == e2)))
FLINT_DEFINE_BINARY_EXPR_COND2(stirling_number_2_vec_next_op, fmpz_vecxx,
FMPZ_VECXX_COND_S, at::slong,
arith_stirling_number_2_vec_next(to._array(), e1._array(), e2,
e1.size() + (e1.size() == e2)))
FLINT_DEFINE_BINARY_EXPR_COND2(stirling_matrix_1u_op, fmpz_matxx,
at::slong, at::slong, arith_stirling_matrix_1u(to._mat()))
FLINT_DEFINE_BINARY_EXPR_COND2(stirling_matrix_1_op, fmpz_matxx,
at::slong, at::slong, arith_stirling_matrix_1(to._mat()))
FLINT_DEFINE_BINARY_EXPR_COND2(stirling_matrix_2_op, fmpz_matxx,
at::slong, at::slong, arith_stirling_matrix_2(to._mat()))
} // rules
ARITHXX_DEFINE_UNOP(bell_number, fmpzxx, at::ulong)
ARITHXX_DEFINE_UNOP(bell_number_bsplit, fmpzxx, at::ulong)
ARITHXX_DEFINE_UNOP(bell_number_multi_mod, fmpzxx, at::ulong)
ARITHXX_DEFINE_UNOP(bell_number_vec, fmpz_vecxx, at::slong)
ARITHXX_DEFINE_UNOP(bell_number_vec_recursive, fmpz_vecxx, at::slong)
ARITHXX_DEFINE_UNOP(bell_number_vec_multi_mod, fmpz_vecxx, at::slong)
FLINT_DEFINE_BINOP(bell_number_nmod)
FLINT_DEFINE_BINOP(bell_number_nmod_vec)
FLINT_DEFINE_BINOP(bell_number_nmod_vec_recursive)
FLINT_DEFINE_BINOP(bell_number_nmod_vec_series)
namespace vectors {
template<>
struct outsize
{
template static unsigned get(const Expr& e)
{return e._data().first();}
};
template<> struct outsize
: outsize { };
template<> struct outsize
: outsize { };
template<> struct outsize
: outsize { };
template<> struct outsize
: outsize { };
template<> struct outsize
: outsize { };
} // vectors
namespace at {
template struct nmod : mp::or_,
mp::equal_types > { };
} // at
#define NMODXX_DEFINE_FIND_CTX_BY_OP(exprname, eval) \
namespace traits { \
template \
struct has_nmodxx_ctx< exprname, Data> > : mp::true_ { }; \
} \
namespace detail { \
template \
struct get_nmodxx_ctx > \
{ \
template \
static nmodxx_ctx_srcref get(const T& e) {return eval;} \
}; \
}
#define FLINTXX_COMMA() ,
NMODXX_DEFINE_FIND_CTX_BY_OP(nmodxx_expression
struct outsize
{
template static unsigned get(const Expr& e)
{return e._data().first();}
};
} // vectors
ARITHXX_DEFINE_UNOP(euler_number, fmpzxx, at::ulong)
ARITHXX_DEFINE_UNOP(euler_number_vec, fmpz_vecxx, at::ulong)
ARITHXX_DEFINE_UNOP(euler_polynomial, fmpq_polyxx, at::ulong)
namespace vectors {
template<> struct outsize
: outsize { };
}
ARITHXX_DEFINE_UNOP(legendre_polynomial, fmpq_polyxx, at::ulong)
ARITHXX_DEFINE_UNOP(chebyshev_t_polynomial, fmpz_polyxx, at::ulong)
ARITHXX_DEFINE_UNOP(chebyshev_u_polynomial, fmpz_polyxx, at::ulong)
ARITHXX_DEFINE_UNOP(euler_phi, fmpzxx, FMPZXX_COND_S)
ARITHXX_DEFINE_BINOP(divisor_sigma, fmpzxx, FMPZXX_COND_S, at::ulong)
ARITHXX_DEFINE_UNOP(divisors, fmpz_polyxx, FMPZXX_COND_S)
ARITHXX_DEFINE_UNOP(ramanujan_tau, fmpzxx, FMPZXX_COND_S)
ARITHXX_DEFINE_UNOP(ramanujan_tau_series, fmpz_polyxx, at::slong)
ARITHXX_DEFINE_UNOP(cyclotomic_polynomial, fmpz_polyxx, at::ulong)
ARITHXX_DEFINE_UNOP(cos_minpoly, fmpz_polyxx, at::ulong)
ARITHXX_DEFINE_UNOP(swinnerton_dyer_polynomial, fmpz_polyxx, at::ulong)
ARITHXX_DEFINE_UNOP(landau_function_vec, fmpz_vecxx, at::slong)
namespace vectors {
template<> struct outsize
: outsize { };
}
ARITHXX_DEFINE_BINOP(dedekind_sum_naive, fmpqxx,
FMPZXX_COND_S, FMPZXX_COND_S)
ARITHXX_DEFINE_BINOP(dedekind_sum, fmpqxx,
FMPZXX_COND_S, FMPZXX_COND_S)
ARITHXX_DEFINE_UNOP(number_of_partitions_vec, fmpz_vecxx, at::slong)
ARITHXX_DEFINE_UNOP(number_of_partitions, fmpzxx, at::ulong)
FLINT_DEFINE_BINOP(number_of_partitions_nmod_vec)
namespace vectors {
template<> struct outsize
: outsize { };
template<> struct outsize
: outsize { };
}
NMODXX_DEFINE_FIND_CTX_BY_OP(vector_expression struct outsize
: outsize { };
}
inline double bell_number_size(ulong n) {return arith_bell_number_size(n);}
inline double bernoulli_number_size(ulong n)
{return arith_bernoulli_number_size(n);}
inline double euler_number_size(ulong n) {return arith_euler_number_size(n);}
template
inline typename mp::enable_if, int>::type moebius_mu(
const Fmpz& n)
{
return arith_moebius_mu(n.evaluate()._fmpz());
}
} // flint
#endif