/*
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 NMOD_POLYXX_H
#define NMOD_POLYXX_H
#include
#include
#include "nmod_poly.h"
#include "fmpzxx.h"
#include "nmod_vecxx.h"
#include "fmpz_polyxx.h"
#include "fmpq_polyxx.h"
#include "flintxx/expression.h"
#include "flintxx/ltuple.h"
#include "flintxx/flint_classes.h"
#include "flintxx/flint_exception.h"
#include "flintxx/frandxx.h"
#include "flintxx/stdmath.h"
#include "flintxx/traits.h"
// TODO exhibit this as a specialisation of a generic poly
// TODO input
// TODO automatic mulmod, powmod etc?
// TODO use underscore function versions?
// TODO nmod_series class?
// TODO subproduct trees?
namespace flint {
FLINT_DEFINE_BINOP(div_newton)
FLINT_DEFINE_BINOP(divrem_newton)
FLINT_DEFINE_BINOP(evaluate_fast)
FLINT_DEFINE_BINOP(evaluate_iter)
FLINT_DEFINE_BINOP(exp_series_basecase)
FLINT_DEFINE_BINOP(gcd_euclidean)
FLINT_DEFINE_BINOP(gcd_hgcd)
FLINT_DEFINE_BINOP(inv_series_basecase)
FLINT_DEFINE_BINOP(nmod_polyxx_get_coeff)
FLINT_DEFINE_BINOP(deflate)
FLINT_DEFINE_BINOP(inflate)
FLINT_DEFINE_BINOP(resultant_euclidean)
FLINT_DEFINE_BINOP(taylor_shift_convolution)
FLINT_DEFINE_BINOP(xgcd_euclidean)
FLINT_DEFINE_BINOP(xgcd_hgcd)
FLINT_DEFINE_THREEARY(compose_mod)
FLINT_DEFINE_THREEARY(compose_mod_brent_kung)
FLINT_DEFINE_THREEARY(compose_mod_horner)
FLINT_DEFINE_THREEARY(div_newton_n_preinv)
FLINT_DEFINE_THREEARY(divrem_newton_n_preinv)
FLINT_DEFINE_THREEARY(exp_series_monomial)
FLINT_DEFINE_THREEARY(log_series_monomial)
FLINT_DEFINE_THREEARY(mulmod)
FLINT_DEFINE_THREEARY(powmod_binexp)
FLINT_DEFINE_BINOP(nmod_polyxx_interpolate)
FLINT_DEFINE_BINOP(nmod_polyxx_interpolate_barycentric)
FLINT_DEFINE_BINOP(nmod_polyxx_interpolate_fast)
FLINT_DEFINE_BINOP(nmod_polyxx_interpolate_newton)
FLINT_DEFINE_UNOP(nmod_polyxx_product_roots)
FLINT_DEFINE_FOURARY(compose_mod_brent_kung_preinv)
FLINT_DEFINE_FOURARY(mulmod_preinv)
FLINT_DEFINE_FOURARY(powmod_binexp_preinv)
template
class nmod_polyxx_expression
: public expression,
Operation, Data>
{
public:
typedef expression,
Operation, Data> base_t;
FLINTXX_DEFINE_BASICS(nmod_polyxx_expression)
FLINTXX_DEFINE_CTORS(nmod_polyxx_expression)
FLINTXX_DEFINE_C_REF(nmod_polyxx_expression, nmod_poly_struct, _poly)
// static functions for nmod_polyxx
template
static FLINT_BINOP_ENABLE_RETTYPE(nmod_polyxx_interpolate,
Nmod_vec1, Nmod_vec2)
interpolate(const Nmod_vec1& xs, const Nmod_vec2& ys)
{
return nmod_polyxx_interpolate(xs, ys);
}
template
static FLINT_BINOP_ENABLE_RETTYPE(nmod_polyxx_interpolate_fast,
Nmod_vec1, Nmod_vec2)
interpolate_fast(const Nmod_vec1& xs, const Nmod_vec2& ys)
{
return nmod_polyxx_interpolate_fast(xs, ys);
}
template
static FLINT_BINOP_ENABLE_RETTYPE(nmod_polyxx_interpolate_newton,
Nmod_vec1, Nmod_vec2)
interpolate_newton(const Nmod_vec1& xs, const Nmod_vec2& ys)
{
return nmod_polyxx_interpolate_newton(xs, ys);
}
template
static FLINT_BINOP_ENABLE_RETTYPE(nmod_polyxx_interpolate_barycentric,
Nmod_vec1, Nmod_vec2)
interpolate_barycentric(const Nmod_vec1& xs, const Nmod_vec2& ys)
{
return nmod_polyxx_interpolate_barycentric(xs, ys);
}
template
static FLINT_UNOP_ENABLE_RETTYPE(nmod_polyxx_product_roots, Nmod_vec)
product_roots(const Nmod_vec& xs)
{
return nmod_polyxx_product_roots(xs);
}
// XXX this is difficult to make lazy
template
static typename mp::enable_if,
nmod_polyxx_expression>::type
bit_unpack(const Fmpz& a, flint_bitcnt_t bits, nmodxx_ctx_srcref modulus)
{
nmod_polyxx_expression res(modulus);
nmod_poly_bit_unpack(res._poly(), a.evaluate()._fmpz(), bits);
return res;
}
FLINTXX_DEFINE_FORWARD_STATIC(from_ground)
FLINTXX_DEFINE_FORWARD_STATIC(reduce)
static nmod_polyxx_expression zero(mp_limb_t n)
{return nmod_polyxx_expression(n);}
static nmod_polyxx_expression one(mp_limb_t n)
{
nmod_polyxx_expression res(n);
res.set_one();
return res;
}
static nmod_polyxx_expression randtest(mp_limb_t n,
frandxx& state, slong len)
{
nmod_polyxx_expression res(n);
res.set_randtest(state, len);
return res;
}
static nmod_polyxx_expression randtest_irreducible(mp_limb_t n,
frandxx& state, slong len)
{
nmod_polyxx_expression res(n);
res.set_randtest_irreducible(state, len);
return res;
}
// these only make sense with immediates
void realloc(slong alloc) {nmod_poly_realloc(_poly(), alloc);}
void fit_length(slong len) {nmod_poly_fit_length(_poly(), len);}
void _normalise() {_nmod_poly_normalise(_poly());}
nmodxx_ctx_srcref _ctx() const
{return nmodxx_ctx_srcref::make(_poly()->mod);}
void set_zero() {nmod_poly_zero(_poly());}
void set_one() {nmod_poly_one(_poly());}
// These only make sense with target immediates
void set_coeff(slong n, ulong c) {nmod_poly_set_coeff_ui(_poly(), n, c);}
template
typename mp::enable_if >::type
set_coeff(slong j, const Nmod& c)
{
// TODO this does not need reduction
nmod_poly_set_coeff_ui(_poly(), j, c.template to());
}
void truncate(slong n) {nmod_poly_truncate(_poly(), n);}
void set_randtest(frandxx& state, slong len)
{nmod_poly_randtest(_poly(), state._data(), len);}
void set_randtest_irreducible(frandxx& state, slong len)
{nmod_poly_randtest_irreducible(_poly(), state._data(), len);}
template
slong remove(const Poly& p)
{
return nmod_poly_remove(_poly(), p.evaluate()._poly());
}
// These work on any expression without evaluation
nmodxx_ctx_srcref estimate_ctx() const;
mp_limb_t modulus() const {return estimate_ctx().n();}
evaluated_t create_temporary() const
{
return evaluated_t(estimate_ctx());
}
// These cause evaluation
slong length() const {return nmod_poly_length(this->evaluate()._poly());}
slong degree() const {return nmod_poly_degree(this->evaluate()._poly());}
bool is_one() const {return nmod_poly_is_one(this->evaluate()._poly());}
bool is_zero() const {return nmod_poly_is_zero(this->evaluate()._poly());}
bool is_squarefree() const
{return nmod_poly_is_squarefree(this->evaluate()._poly());}
bool is_irreducible() const
{return nmod_poly_is_irreducible(this->evaluate()._poly());}
slong max_bits() const {return nmod_poly_max_bits(this->evaluate()._poly());}
ulong deflation() const
{return nmod_poly_deflation(this->evaluate()._poly());}
// Lazy members
FLINTXX_DEFINE_MEMBER_BINOP_(get_coeff, nmod_polyxx_get_coeff)
FLINTXX_DEFINE_MEMBER_BINOP_(operator(), compeval)
FLINTXX_DEFINE_MEMBER_BINOP(inflate)
FLINTXX_DEFINE_MEMBER_BINOP(deflate)
FLINTXX_DEFINE_MEMBER_BINOP(compose_divconquer)
FLINTXX_DEFINE_MEMBER_BINOP(compose_horner)
FLINTXX_DEFINE_MEMBER_BINOP(div_basecase)
FLINTXX_DEFINE_MEMBER_BINOP(div_divconquer)
FLINTXX_DEFINE_MEMBER_BINOP(div_newton)
FLINTXX_DEFINE_MEMBER_BINOP(divrem)
FLINTXX_DEFINE_MEMBER_BINOP(divrem_basecase)
FLINTXX_DEFINE_MEMBER_BINOP(divrem_divconquer)
FLINTXX_DEFINE_MEMBER_BINOP(divrem_newton)
FLINTXX_DEFINE_MEMBER_BINOP(div_root)
FLINTXX_DEFINE_MEMBER_BINOP(evaluate_fast)
FLINTXX_DEFINE_MEMBER_BINOP(evaluate_iter)
FLINTXX_DEFINE_MEMBER_BINOP(gcd)
FLINTXX_DEFINE_MEMBER_BINOP(gcd_euclidean)
FLINTXX_DEFINE_MEMBER_BINOP(gcd_hgcd)
FLINTXX_DEFINE_MEMBER_BINOP(inv_series)
FLINTXX_DEFINE_MEMBER_BINOP(inv_series_basecase)
FLINTXX_DEFINE_MEMBER_BINOP(inv_series_newton)
FLINTXX_DEFINE_MEMBER_BINOP(invsqrt_series)
FLINTXX_DEFINE_MEMBER_BINOP(mul_classical)
FLINTXX_DEFINE_MEMBER_BINOP(mul_KS)
FLINTXX_DEFINE_MEMBER_BINOP(shift_left)
FLINTXX_DEFINE_MEMBER_BINOP(shift_right)
FLINTXX_DEFINE_MEMBER_BINOP(pow)
FLINTXX_DEFINE_MEMBER_BINOP(pow_binexp)
FLINTXX_DEFINE_MEMBER_BINOP(rem_basecase)
FLINTXX_DEFINE_MEMBER_BINOP(resultant)
FLINTXX_DEFINE_MEMBER_BINOP(resultant_euclidean)
FLINTXX_DEFINE_MEMBER_BINOP(reverse)
FLINTXX_DEFINE_MEMBER_BINOP(revert_series)
FLINTXX_DEFINE_MEMBER_BINOP(revert_series_lagrange)
FLINTXX_DEFINE_MEMBER_BINOP(revert_series_lagrange_fast)
FLINTXX_DEFINE_MEMBER_BINOP(revert_series_newton)
FLINTXX_DEFINE_MEMBER_BINOP(sqrt_series)
FLINTXX_DEFINE_MEMBER_BINOP(taylor_shift)
FLINTXX_DEFINE_MEMBER_BINOP(taylor_shift_convolution)
FLINTXX_DEFINE_MEMBER_BINOP(taylor_shift_horner)
FLINTXX_DEFINE_MEMBER_BINOP(xgcd)
FLINTXX_DEFINE_MEMBER_BINOP(xgcd_euclidean)
FLINTXX_DEFINE_MEMBER_BINOP(xgcd_hgcd)
FLINTXX_DEFINE_MEMBER_BINOP(log_series)
FLINTXX_DEFINE_MEMBER_BINOP(exp_series)
FLINTXX_DEFINE_MEMBER_BINOP(exp_series_basecase)
FLINTXX_DEFINE_MEMBER_BINOP(atan_series)
FLINTXX_DEFINE_MEMBER_BINOP(atanh_series)
FLINTXX_DEFINE_MEMBER_BINOP(asin_series)
FLINTXX_DEFINE_MEMBER_BINOP(asinh_series)
FLINTXX_DEFINE_MEMBER_BINOP(sin_series)
FLINTXX_DEFINE_MEMBER_BINOP(cos_series)
FLINTXX_DEFINE_MEMBER_BINOP(tan_series)
FLINTXX_DEFINE_MEMBER_BINOP(sinh_series)
FLINTXX_DEFINE_MEMBER_BINOP(cosh_series)
FLINTXX_DEFINE_MEMBER_BINOP(tanh_series)
FLINTXX_DEFINE_MEMBER_BINOP(bit_pack)
FLINTXX_DEFINE_MEMBER_UNOP(derivative)
FLINTXX_DEFINE_MEMBER_UNOP(integral)
FLINTXX_DEFINE_MEMBER_UNOP(make_monic)
FLINTXX_DEFINE_MEMBER_UNOP(sqrt)
FLINTXX_DEFINE_MEMBER_3OP(compose_mod)
FLINTXX_DEFINE_MEMBER_3OP(compose_mod_horner)
FLINTXX_DEFINE_MEMBER_3OP(compose_mod_brent_kung)
FLINTXX_DEFINE_MEMBER_3OP(compose_series)
FLINTXX_DEFINE_MEMBER_3OP(compose_series_brent_kung)
FLINTXX_DEFINE_MEMBER_3OP(compose_series_divconquer)
FLINTXX_DEFINE_MEMBER_3OP(compose_series_horner)
FLINTXX_DEFINE_MEMBER_3OP(div_newton_n_preinv)
FLINTXX_DEFINE_MEMBER_3OP(divrem_newton_n_preinv)
FLINTXX_DEFINE_MEMBER_3OP(div_series)
FLINTXX_DEFINE_MEMBER_3OP(mulhigh)
FLINTXX_DEFINE_MEMBER_3OP(mulhigh_classical)
FLINTXX_DEFINE_MEMBER_3OP(mullow)
FLINTXX_DEFINE_MEMBER_3OP(mullow_classical)
FLINTXX_DEFINE_MEMBER_3OP(mullow_KS)
FLINTXX_DEFINE_MEMBER_3OP(mulmod)
FLINTXX_DEFINE_MEMBER_3OP(powmod_binexp)
FLINTXX_DEFINE_MEMBER_3OP(pow_trunc)
FLINTXX_DEFINE_MEMBER_3OP(pow_trunc_binexp)
FLINTXX_DEFINE_MEMBER_4OP(compose_mod_brent_kung_preinv)
FLINTXX_DEFINE_MEMBER_4OP(mulmod_preinv)
FLINTXX_DEFINE_MEMBER_4OP(powmod_binexp_preinv)
};
namespace detail {
struct nmod_poly_data;
}
typedef nmod_polyxx_expression
nmod_polyxx;
typedef nmod_polyxx_expression >
nmod_polyxx_ref;
typedef nmod_polyxx_expression >
nmod_polyxx_srcref;
namespace detail {
struct nmod_poly_data
{
nmod_poly_t inner;
typedef nmod_poly_t& data_ref_t;
typedef const nmod_poly_t& data_srcref_t;
nmod_poly_data(mp_limb_t n) {nmod_poly_init(inner, n);}
nmod_poly_data(nmodxx_ctx_srcref c)
{
nmod_poly_init_preinv(inner, c.n(), c._nmod().ninv);
}
nmod_poly_data(mp_limb_t n, slong alloc) {nmod_poly_init2(inner, n, alloc);}
nmod_poly_data(nmodxx_ctx_srcref c, slong alloc)
{
nmod_poly_init2_preinv(inner, c.n(), c._nmod().ninv, alloc);
}
~nmod_poly_data() {nmod_poly_clear(inner);}
nmod_poly_data(const nmod_poly_data& o)
{
nmod_poly_init2_preinv(inner, o.inner->mod.n,
o.inner->mod.ninv, o.inner->length);
nmod_poly_set(inner, o.inner);
}
nmod_poly_data(nmod_polyxx_srcref r)
{
nmod_poly_init2_preinv(inner, r.modulus(),
r._poly()->mod.ninv, r.length());
nmod_poly_set(inner, r._poly());
}
nmod_poly_data(const char* str)
{
mp_limb_t n;slong length;
execution_check(flint_sscanf(str, "%wd %wu", &length, &n) == 2
&& (nmod_poly_init2(inner, n, length), nmod_poly_set_str(inner, str)),
"construct from string", "nmod_polyxx");
}
template
static nmod_poly_data from_ground(const Nmod& x,
typename mp::enable_if >::type* = 0)
{
nmod_poly_data res(x.estimate_ctx());
nmod_poly_set_coeff_ui(res.inner, 0, x.template to());
return res;
}
static nmod_poly_data from_ground(mp_limb_t x, nmodxx_ctx_srcref c)
{
nmod_poly_data res(c);
nmod_poly_set_coeff_ui(res.inner, 0, x);
return res;
}
// TODO maybe make these lazy
template
static nmod_poly_data reduce(const Fmpz_poly& p, nmodxx_ctx_srcref c,
typename mp::enable_if >::type* = 0)
{
nmod_poly_data res(c);
fmpz_poly_get_nmod_poly(res.inner, p.evaluate()._poly());
return res;
}
template
static nmod_poly_data reduce(const Fmpz_poly& p, mp_limb_t m,
typename mp::enable_if >::type* = 0)
{
nmod_poly_data res(m);
fmpz_poly_get_nmod_poly(res.inner, p.evaluate()._poly());
return res;
}
template
static nmod_poly_data reduce_(const Fmpq_poly& p, nmodxx_ctx_srcref c,
typename mp::enable_if >::type* = 0)
{
nmod_poly_data res(c, p.length());
for(slong i = 0;i < p.length();++i)
nmod_poly_set_coeff_ui(res. inner, i,
nmodxx::red(p.get_coeff(i), c).template to());
return res;
}
template
static nmod_poly_data reduce(const Fmpq_poly& p, nmodxx_ctx_srcref c,
typename mp::enable_if >::type* = 0)
{
return reduce_(p.evaluate(), c);
}
template
static nmod_poly_data reduce(const Fmpq_poly& p, mp_limb_t m,
typename mp::enable_if >::type* = 0)
{
return reduce_(p.evaluate(), nmodxx_ctx(m));
}
};
} // detail
namespace traits {
template<> struct has_nmodxx_ctx : mp::true_ { };
template<> struct has_nmodxx_ctx : mp::true_ { };
template<> struct has_nmodxx_ctx : mp::true_ { };
template struct is_nmod_polyxx : mp::or_<
traits::is_T_expr,
flint_classes::is_source > { };
} // traits
template
inline nmodxx_ctx_srcref
nmod_polyxx_expression::estimate_ctx() const
{
return tools::find_nmodxx_ctx(*this);
}
namespace rules {
#define NMOD_POLYXX_COND_S FLINTXX_COND_S(nmod_polyxx)
#define NMOD_POLYXX_COND_T FLINTXX_COND_T(nmod_polyxx)
NMODXX_DEFINE_INSTANTIATE_TEMPORARIES(nmod_polyxx)
FLINT_DEFINE_DOIT_COND2(assignment, NMOD_POLYXX_COND_T, NMOD_POLYXX_COND_S,
nmod_poly_set(to._poly(), from._poly()))
FLINTXX_DEFINE_ASSIGN_STR(nmod_polyxx, execution_check(
nmod_poly_set_str(to._poly(), from), "assign string", "nmod_polyxx"))
FLINT_DEFINE_PRINT_COND(NMOD_POLYXX_COND_S, nmod_poly_fprint(to, from._poly()))
FLINT_DEFINE_READ_COND(NMOD_POLYXX_COND_T, nmod_poly_fread(from, to._poly()))
FLINTXX_DEFINE_EQUALS(nmod_polyxx, nmod_poly_equal(e1._poly(), e2._poly()))
FLINTXX_DEFINE_TO_STR(nmod_polyxx, nmod_poly_get_str(from._poly()))
FLINTXX_DEFINE_SWAP(nmod_polyxx, nmod_poly_swap(e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(nmod_polyxx_get_coeff_op, nmodxx,
NMOD_POLYXX_COND_S, traits::fits_into_slong,
to.set_nored(nmod_poly_get_coeff_ui(e1._poly(), e2)))
FLINT_DEFINE_BINARY_EXPR_COND2(plus, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_add(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(minus, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_sub(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_UNARY_EXPR_COND(negate, nmod_polyxx, NMOD_POLYXX_COND_S,
nmod_poly_neg(to._poly(), from._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(reverse_op, nmod_polyxx,
NMOD_POLYXX_COND_S, traits::fits_into_slong,
nmod_poly_reverse(to._poly(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(shift_left_op, nmod_polyxx,
NMOD_POLYXX_COND_S, traits::fits_into_slong,
nmod_poly_shift_left(to._poly(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(shift_right_op, nmod_polyxx,
NMOD_POLYXX_COND_S, traits::fits_into_slong,
nmod_poly_shift_right(to._poly(), e1._poly(), e2))
FLINT_DEFINE_CBINARY_EXPR_COND2(times, nmod_polyxx,
NMOD_POLYXX_COND_S, NMODXX_COND_S,
nmod_poly_scalar_mul_nmod(to._poly(), e1._poly(), e2._limb()))
FLINT_DEFINE_UNARY_EXPR_COND(make_monic_op, nmod_polyxx, NMOD_POLYXX_COND_S,
nmod_poly_make_monic(to._poly(), from._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(bit_pack_op, fmpzxx,
NMOD_POLYXX_COND_S, traits::fits_into_flint_bitcnt_t,
nmod_poly_bit_pack(to._fmpz(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(times, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_mul(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(mul_classical_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_mul_classical(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(mul_KS_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_mul_KS(to._poly(), e1._poly(), e2._poly(), 0 /* TODO */))
#define NMOD_POLYXX_DEFINE_MULFUNC(name) \
FLINT_DEFINE_THREEARY_EXPR_COND3(name##_op, nmod_polyxx, \
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, traits::fits_into_slong, \
nmod_poly_##name(to._poly(), e1._poly(), e2._poly(), e3))
NMOD_POLYXX_DEFINE_MULFUNC(mullow_classical)
NMOD_POLYXX_DEFINE_MULFUNC(mullow)
NMOD_POLYXX_DEFINE_MULFUNC(mulhigh_classical)
NMOD_POLYXX_DEFINE_MULFUNC(mulhigh)
FLINT_DEFINE_THREEARY_EXPR_COND3(mullow_KS_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, traits::fits_into_slong,
nmod_poly_mullow_KS(to._poly(), e1._poly(), e2._poly(), 0 /* TODO */, e3))
FLINT_DEFINE_THREEARY_EXPR_COND3(mulmod_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_mulmod(to._poly(), e1._poly(), e2._poly(), e3._poly()))
FLINT_DEFINE_FOURARY_EXPR_COND4(mulmod_preinv_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_mulmod_preinv(to._poly(), e1._poly(), e2._poly(),
e3._poly(), e4._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(pow_binexp_op, nmod_polyxx,
NMOD_POLYXX_COND_S, traits::is_unsigned_integer,
nmod_poly_pow_binexp(to._poly(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, nmod_polyxx,
NMOD_POLYXX_COND_S, traits::is_unsigned_integer,
nmod_poly_pow(to._poly(), e1._poly(), e2))
FLINT_DEFINE_THREEARY_EXPR_COND3(powmod_binexp_op, nmod_polyxx,
NMOD_POLYXX_COND_S, traits::is_unsigned_integer, NMOD_POLYXX_COND_S,
nmod_poly_powmod_ui_binexp(to._poly(), e1._poly(), e2, e3._poly()))
FLINT_DEFINE_FOURARY_EXPR_COND4(powmod_binexp_preinv_op, nmod_polyxx,
NMOD_POLYXX_COND_S, traits::is_unsigned_integer,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_powmod_ui_binexp_preinv(to._poly(), e1._poly(), e2,
e3._poly(), e4._poly()))
FLINT_DEFINE_THREEARY_EXPR_COND3(pow_trunc_op, nmod_polyxx,
NMOD_POLYXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong,
nmod_poly_pow_trunc(to._poly(), e1._poly(), e2, e3))
FLINT_DEFINE_THREEARY_EXPR_COND3(pow_trunc_binexp_op, nmod_polyxx,
NMOD_POLYXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong,
nmod_poly_pow_trunc_binexp(to._poly(), e1._poly(), e2, e3))
FLINT_DEFINE_UNARY_EXPR_COND(derivative_op, nmod_polyxx, NMOD_POLYXX_COND_S,
nmod_poly_derivative(to._poly(), from._poly()))
FLINT_DEFINE_UNARY_EXPR_COND(integral_op, nmod_polyxx, NMOD_POLYXX_COND_S,
nmod_poly_integral(to._poly(), from._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, nmodxx,
NMOD_POLYXX_COND_S, NMODXX_COND_S,
to.set_nored(nmod_poly_evaluate_nmod(e1._poly(), e2._limb())))
FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, nmod_vecxx,
NMOD_POLYXX_COND_S, NMOD_VECXX_COND_S,
nmod_poly_evaluate_nmod_vec(to._array(), e1._poly(), e2._array(),
to.size()))
FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_fast_op, nmod_vecxx,
NMOD_POLYXX_COND_S, NMOD_VECXX_COND_S,
nmod_poly_evaluate_nmod_vec_fast(to._array(), e1._poly(), e2._array(),
to.size()))
FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_iter_op, nmod_vecxx,
NMOD_POLYXX_COND_S, NMOD_VECXX_COND_S,
nmod_poly_evaluate_nmod_vec_iter(to._array(), e1._poly(), e2._array(),
to.size()))
namespace rdetail {
typedef make_ltuple::type>::type
nmod_polyxx_pair;
} // rdetail
#define NMOD_POLYXX_DEFINE_DIVREM(name) \
FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, rdetail::nmod_polyxx_pair, \
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, \
nmod_poly_##name(to.template get<0>()._poly(), to.template get<1>()._poly(), \
e1._poly(), e2._poly()))
NMOD_POLYXX_DEFINE_DIVREM(divrem_basecase)
NMOD_POLYXX_DEFINE_DIVREM(divrem_divconquer)
NMOD_POLYXX_DEFINE_DIVREM(divrem_newton)
NMOD_POLYXX_DEFINE_DIVREM(divrem)
FLINT_DEFINE_BINARY_EXPR_COND2(div_basecase_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_div_basecase(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(div_divconquer_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_div_divconquer(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(div_newton_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_div_newton(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_div_divconquer(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_THREEARY_EXPR_COND3(div_newton_n_preinv_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_div_newton_n_preinv(to._poly(),
e1._poly(), e2._poly(), e3._poly()))
FLINT_DEFINE_THREEARY_EXPR_COND3(divrem_newton_n_preinv_op,
rdetail::nmod_polyxx_pair,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_divrem_newton_n_preinv(to.template get<0>()._poly(),
to.template get<1>()._poly(), e1._poly(), e2._poly(), e3._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(rem_basecase_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_rem_basecase(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(modulo, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_rem(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_newton_op, nmod_polyxx,
NMOD_POLYXX_COND_S, traits::fits_into_slong,
nmod_poly_inv_series_newton(to._poly(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_op, nmod_polyxx,
NMOD_POLYXX_COND_S, traits::fits_into_slong,
nmod_poly_inv_series(to._poly(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_basecase_op, nmod_polyxx,
NMOD_POLYXX_COND_S, traits::fits_into_slong,
nmod_poly_inv_series_basecase(to._poly(), e1._poly(), e2))
#define NMOD_POLYXX_DEFINE_SERIES(name) \
FLINT_DEFINE_THREEARY_EXPR_COND3(name##_op, nmod_polyxx, \
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, traits::fits_into_slong, \
nmod_poly_##name(to._poly(), e1._poly(), e2._poly(), e3))
NMOD_POLYXX_DEFINE_SERIES(div_series)
FLINT_DEFINE_BINARY_EXPR_COND2(compose_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_compose(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(compose_divconquer_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_compose_divconquer(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(compose_horner_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_compose_horner(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(div_root_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMODXX_COND_S,
nmod_poly_div_root(to._poly(), e1._poly(), e2._limb()))
FLINT_DEFINE_BINARY_EXPR_COND2(nmod_polyxx_interpolate_op, nmod_polyxx,
NMOD_VECXX_COND_S, NMOD_VECXX_COND_S,
nmod_poly_interpolate_nmod_vec(to._poly(), e1._data().array,
e2._data().array, e2.size()))
FLINT_DEFINE_BINARY_EXPR_COND2(nmod_polyxx_interpolate_fast_op, nmod_polyxx,
NMOD_VECXX_COND_S, NMOD_VECXX_COND_S,
nmod_poly_interpolate_nmod_vec_fast(to._poly(), e1._data().array,
e2._data().array, e2.size()))
FLINT_DEFINE_BINARY_EXPR_COND2(nmod_polyxx_interpolate_newton_op, nmod_polyxx,
NMOD_VECXX_COND_S, NMOD_VECXX_COND_S,
nmod_poly_interpolate_nmod_vec_newton(to._poly(), e1._data().array,
e2._data().array, e2.size()))
FLINT_DEFINE_BINARY_EXPR_COND2(nmod_polyxx_interpolate_barycentric_op, nmod_polyxx,
NMOD_VECXX_COND_S, NMOD_VECXX_COND_S,
nmod_poly_interpolate_nmod_vec_barycentric(to._poly(), e1._data().array,
e2._data().array, e2.size()))
FLINT_DEFINE_BINARY_EXPR_COND2(taylor_shift_horner_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMODXX_COND_S,
nmod_poly_taylor_shift_horner(to._poly(), e1._poly(), e2._limb()))
FLINT_DEFINE_BINARY_EXPR_COND2(taylor_shift_convolution_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMODXX_COND_S,
nmod_poly_taylor_shift_convolution(to._poly(), e1._poly(), e2._limb()))
FLINT_DEFINE_BINARY_EXPR_COND2(taylor_shift_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMODXX_COND_S,
nmod_poly_taylor_shift(to._poly(), e1._poly(), e2._limb()))
FLINT_DEFINE_THREEARY_EXPR_COND3(compose_mod_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_compose_mod(to._poly(), e1._poly(), e2._poly(), e3._poly()))
FLINT_DEFINE_THREEARY_EXPR_COND3(compose_mod_horner_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_compose_mod_horner(
to._poly(), e1._poly(), e2._poly(), e3._poly()))
FLINT_DEFINE_THREEARY_EXPR_COND3(compose_mod_brent_kung_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_compose_mod_brent_kung(
to._poly(), e1._poly(), e2._poly(), e3._poly()))
FLINT_DEFINE_FOURARY_EXPR_COND4(compose_mod_brent_kung_preinv_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_compose_mod_brent_kung_preinv(
to._poly(), e1._poly(), e2._poly(), e3._poly(), e4._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(gcd_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_gcd(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(gcd_hgcd_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_gcd_hgcd(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(gcd_euclidean_op, nmod_polyxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_gcd_euclidean(to._poly(), e1._poly(), e2._poly()))
namespace rdetail {
typedef make_ltuple::type>::type
nmod_polyxx_triple;
} // rdetail
FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_op, rdetail::nmod_polyxx_triple,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_xgcd(to.template get<0>()._poly(), to.template get<1>()._poly(),
to.template get<2>()._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_hgcd_op, rdetail::nmod_polyxx_triple,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_xgcd_hgcd(to.template get<0>()._poly(),
to.template get<1>()._poly(),
to.template get<2>()._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_euclidean_op, rdetail::nmod_polyxx_triple,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
nmod_poly_xgcd_euclidean(to.template get<0>()._poly(),
to.template get<1>()._poly(),
to.template get<2>()._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(resultant_op, nmodxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
to.set_nored(nmod_poly_resultant(e1._poly(), e2._poly())))
FLINT_DEFINE_BINARY_EXPR_COND2(resultant_euclidean_op, nmodxx,
NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
to.set_nored(nmod_poly_resultant_euclidean(e1._poly(), e2._poly())))
NMOD_POLYXX_DEFINE_SERIES(compose_series)
NMOD_POLYXX_DEFINE_SERIES(compose_series_horner)
NMOD_POLYXX_DEFINE_SERIES(compose_series_brent_kung)
NMOD_POLYXX_DEFINE_SERIES(compose_series_divconquer)
#define NMOD_POLYXX_DEFINE_SERIESUN(name) \
FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, nmod_polyxx, \
NMOD_POLYXX_COND_S, traits::fits_into_slong, \
nmod_poly_##name(to._poly(), e1._poly(), e2))
NMOD_POLYXX_DEFINE_SERIESUN(revert_series)
NMOD_POLYXX_DEFINE_SERIESUN(revert_series_newton)
NMOD_POLYXX_DEFINE_SERIESUN(revert_series_lagrange_fast)
NMOD_POLYXX_DEFINE_SERIESUN(revert_series_lagrange)
#define NMOD_POLYXX_DEFINE_SERIES_F(name) \
FLINT_DEFINE_BINARY_EXPR_COND2(name##_series_op, nmod_polyxx, \
NMOD_POLYXX_COND_S, traits::fits_into_slong, \
nmod_poly_##name##_series(to._poly(), e1._poly(), e2))
NMOD_POLYXX_DEFINE_SERIES_F(sqrt)
NMOD_POLYXX_DEFINE_SERIES_F(invsqrt)
NMOD_POLYXX_DEFINE_SERIES_F(log)
NMOD_POLYXX_DEFINE_SERIES_F(exp)
NMOD_POLYXX_DEFINE_SERIES_F(atan)
NMOD_POLYXX_DEFINE_SERIES_F(atanh)
NMOD_POLYXX_DEFINE_SERIES_F(asin)
NMOD_POLYXX_DEFINE_SERIES_F(asinh)
NMOD_POLYXX_DEFINE_SERIES_F(sin)
NMOD_POLYXX_DEFINE_SERIES_F(cos)
NMOD_POLYXX_DEFINE_SERIES_F(tan)
NMOD_POLYXX_DEFINE_SERIES_F(sinh)
NMOD_POLYXX_DEFINE_SERIES_F(cosh)
NMOD_POLYXX_DEFINE_SERIES_F(tanh)
FLINT_DEFINE_BINARY_EXPR_COND2(exp_series_basecase_op, nmod_polyxx,
NMOD_POLYXX_COND_S, traits::fits_into_slong,
nmod_poly_exp_series_basecase(to._poly(), e1._poly(), e2))
FLINT_DEFINE_THREEARY_EXPR_COND3(log_series_monomial_op, nmod_polyxx,
NMODXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong,
nmod_poly_log_series_monomial_ui(to._poly(), e1._limb(), e2, e3))
FLINT_DEFINE_THREEARY_EXPR_COND3(exp_series_monomial_op, nmod_polyxx,
NMODXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong,
nmod_poly_exp_series_monomial_ui(to._poly(), e1._limb(), e2, e3))
FLINT_DEFINE_UNARY_EXPR_COND(sqrt_op, nmod_polyxx, NMOD_POLYXX_COND_S,
execution_check(nmod_poly_sqrt(to._poly(), from._poly()),
"sqrt", "nmod_polyxx"))
FLINT_DEFINE_UNARY_EXPR_COND(nmod_polyxx_product_roots_op, nmod_polyxx,
NMOD_VECXX_COND_S,
nmod_poly_product_roots_nmod_vec(to._poly(),
from._data().array, from.size()))
FLINT_DEFINE_BINARY_EXPR_COND2(deflate_op, nmod_polyxx,
NMOD_POLYXX_COND_S, traits::is_unsigned_integer,
nmod_poly_deflate(to._poly(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(inflate_op, nmod_polyxx,
NMOD_POLYXX_COND_S, traits::is_unsigned_integer,
nmod_poly_inflate(to._poly(), e1._poly(), e2))
} // rules
//////////////////////////////////////////////////////////////////////////////
// FACTORISATION
//////////////////////////////////////////////////////////////////////////////
class nmod_poly_factorxx
{
private:
nmod_poly_factor_t inner;
public:
nmod_poly_factorxx() {nmod_poly_factor_init(inner);}
~nmod_poly_factorxx() {nmod_poly_factor_clear(inner);}
nmod_poly_factorxx(const nmod_poly_factorxx& o)
{
nmod_poly_factor_init(inner);
nmod_poly_factor_set(inner, o.inner);
}
bool operator==(const nmod_poly_factorxx& o)
{
if(o.size() != size())
return false;
for(slong i = 0;i < size();++i)
if(p(i) != o.p(i) || exp(i) != o.exp(i))
return false;
return true;
}
nmod_poly_factorxx& operator=(const nmod_poly_factorxx& o)
{
nmod_poly_factor_set(inner, o.inner);
return *this;
}
slong size() const {return inner->num;}
slong exp(slong i) const {return inner->exp[i];}
slong& exp(slong i) {return inner->exp[i];}
nmod_polyxx_srcref p(slong i) const
{return nmod_polyxx_srcref::make(inner->p + i);}
nmod_polyxx_ref p(slong i) {return nmod_polyxx_ref::make(inner->p + i);}
nmod_poly_factor_t& _data() {return inner;}
const nmod_poly_factor_t& _data() const {return inner;}
void realloc(slong a) {nmod_poly_factor_realloc(inner, a);}
void fit_length(slong a) {nmod_poly_factor_fit_length(inner, a);}
void print() const {nmod_poly_factor_print(inner);}
template
void insert(const Nmod_poly& p, slong e,
typename mp::enable_if >::type* = 0)
{nmod_poly_factor_insert(_data(), p.evaluate()._poly(), e);}
void concat(const nmod_poly_factorxx& o)
{nmod_poly_factor_concat(_data(), o._data());}
void pow(slong exp) {nmod_poly_factor_pow(_data(), exp);}
#define NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(name) \
template \
void set_##name(const Nmod_poly& p, \
typename mp::enable_if >::type* = 0) \
{nmod_poly_##name(_data(), p.evaluate()._poly());}
NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor)
NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_squarefree)
NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_cantor_zassenhaus)
NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_berlekamp)
NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_kaltofen_shoup)
NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_with_cantor_zassenhaus)
NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_with_berlekamp)
NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_with_kaltofen_shoup)
template
bool set_factor_equal_deg_probab(frandxx& state, const Nmod_poly& p, slong d,
typename mp::enable_if >::type* = 0)
{
return nmod_poly_factor_equal_deg_prob(_data(), state._data(),
p.evaluate()._poly(), d);
}
template
void set_factor_equal_deg(const Nmod_poly& p, slong d,
typename mp::enable_if >::type* = 0)
{
nmod_poly_factor_equal_deg(_data(), p.evaluate()._poly(), d);
}
template
void set_factor_distinct_deg(const Nmod_poly& p, std::vector& degs,
typename mp::enable_if >::type* = 0)
{
slong* dgs = °s.front();
nmod_poly_factor_distinct_deg(_data(), p.evaluate()._poly(), &dgs);
}
};
#define NMOD_POLY_FACTORXX_DEFINE_FACTOR(name) \
template \
nmod_poly_factorxx name(const Nmod_poly& p, \
typename mp::enable_if >::type* = 0) \
{ \
nmod_poly_factorxx res; \
res.set_##name(p); \
return res; \
}
NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor)
NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_squarefree)
NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_cantor_zassenhaus)
NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_berlekamp)
NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_kaltofen_shoup)
NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_with_cantor_zassenhaus)
NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_with_berlekamp)
NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_with_kaltofen_shoup)
// TODO do we want global versions of factor_distinct_deg etc?
inline void print(const nmod_poly_factorxx& f)
{
f.print();
}
// CRT stuff
// Here for circular dependency reasons
namespace rules {
FLINT_DEFINE_FOURARY_EXPR_COND4(CRT_op, fmpz_polyxx,
FMPZ_POLYXX_COND_T, FMPZXX_COND_S, NMOD_POLYXX_COND_S, tools::is_bool,
fmpz_poly_CRT_ui(to._poly(), e1._poly(), e2._fmpz(), e3._poly(), e4))
} // rules
} // flint
#endif