pqc/external/flint-2.4.3/fmpz_mod_polyxx.h

689 lines
26 KiB
C++

/*=============================================================================
This file is part of FLINT.
FLINT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FLINT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FLINT; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=============================================================================*/
/******************************************************************************
Copyright (C) 2013 Tom Bachmann
******************************************************************************/
#ifndef FMPZ_MOD_POLYXX_H
#define FMPZ_MOD_POLYXX_H
#include "fmpz_mod_poly.h"
#include "fmpzxx.h"
#include "fmpz_polyxx.h"
#include "nmod_polyxx.h"
#include "flintxx/expression.h"
#include "flintxx/flint_classes.h"
#include "flintxx/flint_exception.h"
#include "flintxx/frandxx.h"
#include "flintxx/ltuple.h"
#include "flintxx/stdmath.h"
#include "flintxx/vector.h"
// TODO create/use fmpz_modxx class?
namespace flint {
FLINT_DEFINE_BINOP(divrem_f)
FLINT_DEFINE_BINOP(gcd_euclidean_f)
FLINT_DEFINE_BINOP(gcd_f)
FLINT_DEFINE_BINOP(radix)
FLINT_DEFINE_UNOP(fmpz_mod_polyxx_lead) // TODO standardise?
FLINT_DEFINE_BINOP(fmpz_mod_polyxx_get_coeff) // TODO standardise?
namespace detail {
template<class Poly>
struct fmpz_mod_poly_traits
{
typedef FLINT_UNOP_BUILD_RETTYPE(
fmpz_mod_polyxx_lead, fmpzxx, Poly) lead_ref_t;
typedef lead_ref_t lead_srcref_t;
static lead_ref_t lead(const Poly& p) {return fmpz_mod_polyxx_lead(p);}
};
}
template<class Operation, class Data>
class fmpz_mod_polyxx_expression
: public expression<derived_wrapper<fmpz_mod_polyxx_expression>,
Operation, Data>
{
typedef expression<derived_wrapper< ::flint::fmpz_mod_polyxx_expression>,
Operation, Data> base_t;
typedef detail::fmpz_mod_poly_traits<fmpz_mod_polyxx_expression>
poly_traits_t;
FLINTXX_DEFINE_BASICS(fmpz_mod_polyxx_expression)
FLINTXX_DEFINE_CTORS(fmpz_mod_polyxx_expression)
FLINTXX_DEFINE_C_REF(fmpz_mod_polyxx_expression, fmpz_mod_poly_struct, _poly)
template<class Fmpz>
static fmpz_mod_polyxx_expression randtest(const Fmpz& m,
frandxx& state, slong len)
{
fmpz_mod_polyxx_expression res(m);
res.set_randtest(state, len);
return res;
}
template<class Fmpz>
static fmpz_mod_polyxx_expression randtest_irreducible(const Fmpz& m,
frandxx& state, slong len)
{
fmpz_mod_polyxx_expression res(m);
res.set_randtest_irreducible(state, len);
return res;
}
template<class Fmpz>
static fmpz_mod_polyxx_expression randtest_not_zero(const Fmpz& m,
frandxx& state, slong len)
{
fmpz_mod_polyxx_expression res(m);
res.set_randtest_not_zero(state, len);
return res;
}
template<class Fmpz>
static fmpz_mod_polyxx_expression zero(const Fmpz& m)
{return fmpz_mod_polyxx_expression(m);}
// these only make sense with immediates
fmpzxx_srcref _mod() const
{return fmpzxx_srcref::make(fmpz_mod_poly_modulus(_poly()));}
// These only make sense with target immediates
void realloc(slong alloc) {fmpz_mod_poly_realloc(_poly(), alloc);}
void fit_length(slong len) {fmpz_mod_poly_fit_length(_poly(), len);}
void _normalise() {_fmpz_mod_poly_normalise(_poly());}
void set_coeff(slong n, ulong c) {fmpz_mod_poly_set_coeff_ui(_poly(), n, c);}
template<class Fmpz>
typename mp::enable_if<traits::is_fmpzxx<Fmpz> >::type
set_coeff(slong j, const Fmpz& c)
{
fmpz_mod_poly_set_coeff_fmpz(_poly(), j, c.evaluate()._fmpz());
}
void truncate(slong n) {fmpz_mod_poly_truncate(_poly(), n);}
void zero_coeffs(slong i, slong j) {fmpz_mod_poly_zero_coeffs(_poly(), i, j);}
void set_randtest(frandxx& state, slong len)
{fmpz_mod_poly_randtest(_poly(), state._data(), len);}
void set_randtest_irreducible(frandxx& state, slong len)
{fmpz_mod_poly_randtest_irreducible(_poly(), state._data(), len);}
void set_randtest_not_zero(frandxx& state, slong len)
{fmpz_mod_poly_randtest_not_zero(_poly(), state._data(), len);}
template<class Poly>
slong remove(const Poly& p)
{
return fmpz_mod_poly_remove(_poly(), p.evaluate()._poly());
}
void set_zero() {fmpz_mod_poly_zero(_poly());}
// unified coefficient access
typename poly_traits_t::lead_ref_t lead()
{
return poly_traits_t::lead(*this);
}
typename poly_traits_t::lead_srcref_t lead() const
{
return poly_traits_t::lead(*this);
}
// this works without evaluation
fmpzxx_srcref modulus() const;
evaluated_t create_temporary() const
{
return evaluated_t(modulus());
}
// These cause evaluation
slong length() const {return fmpz_mod_poly_length(this->evaluate()._poly());}
slong degree() const {return fmpz_mod_poly_degree(this->evaluate()._poly());}
bool is_zero() const {return fmpz_mod_poly_is_zero(this->evaluate()._poly());}
bool is_squarefree() const
{return fmpz_mod_poly_is_squarefree(this->evaluate()._poly());}
bool is_irreducible() const
{return fmpz_mod_poly_is_irreducible(this->evaluate()._poly());}
bool is_irreducible_ddf() const
{return fmpz_mod_poly_is_irreducible_ddf(this->evaluate()._poly());}
bool is_irreducible_rabin() const
{return fmpz_mod_poly_is_irreducible_rabin(this->evaluate()._poly());}
// Lazy members
FLINTXX_DEFINE_MEMBER_BINOP_(get_coeff, fmpz_mod_polyxx_get_coeff)
FLINTXX_DEFINE_MEMBER_BINOP_(operator(), compeval)
FLINTXX_DEFINE_MEMBER_UNOP(derivative)
FLINTXX_DEFINE_MEMBER_UNOP(invmod)
FLINTXX_DEFINE_MEMBER_UNOP(make_monic)
FLINTXX_DEFINE_MEMBER_UNOP(sqr)
FLINTXX_DEFINE_MEMBER_BINOP(compose_divconquer)
FLINTXX_DEFINE_MEMBER_BINOP(compose_horner)
FLINTXX_DEFINE_MEMBER_BINOP(div_basecase)
FLINTXX_DEFINE_MEMBER_BINOP(divrem)
FLINTXX_DEFINE_MEMBER_BINOP(divrem_basecase)
FLINTXX_DEFINE_MEMBER_BINOP(divrem_divconquer)
FLINTXX_DEFINE_MEMBER_BINOP(divrem_f)
FLINTXX_DEFINE_MEMBER_BINOP(gcd)
FLINTXX_DEFINE_MEMBER_BINOP(gcd_euclidean)
FLINTXX_DEFINE_MEMBER_BINOP(gcd_euclidean_f)
FLINTXX_DEFINE_MEMBER_BINOP(gcd_f)
FLINTXX_DEFINE_MEMBER_BINOP(gcdinv)
FLINTXX_DEFINE_MEMBER_BINOP(invmod)
FLINTXX_DEFINE_MEMBER_BINOP(inv_series_newton)
FLINTXX_DEFINE_MEMBER_BINOP(shift_left)
FLINTXX_DEFINE_MEMBER_BINOP(shift_right)
FLINTXX_DEFINE_MEMBER_BINOP(pow)
FLINTXX_DEFINE_MEMBER_BINOP(radix)
FLINTXX_DEFINE_MEMBER_BINOP(rem_basecase)
FLINTXX_DEFINE_MEMBER_BINOP(xgcd)
FLINTXX_DEFINE_MEMBER_BINOP(xgcd_euclidean)
FLINTXX_DEFINE_MEMBER_3OP(compose_mod)
FLINTXX_DEFINE_MEMBER_3OP(compose_mod_brent_kung)
FLINTXX_DEFINE_MEMBER_3OP(compose_mod_horner)
FLINTXX_DEFINE_MEMBER_3OP(mullow)
FLINTXX_DEFINE_MEMBER_3OP(mulmod)
FLINTXX_DEFINE_MEMBER_3OP(powmod_binexp)
FLINTXX_DEFINE_MEMBER_3OP(pow_trunc)
FLINTXX_DEFINE_MEMBER_3OP(pow_trunc_binexp)
};
namespace detail {
struct fmpz_mod_poly_data;
}
typedef fmpz_mod_polyxx_expression<operations::immediate, detail::fmpz_mod_poly_data>
fmpz_mod_polyxx;
typedef fmpz_mod_polyxx_expression<operations::immediate,
flint_classes::ref_data<fmpz_mod_polyxx, fmpz_mod_poly_struct> >
fmpz_mod_polyxx_ref;
typedef fmpz_mod_polyxx_expression<operations::immediate,
flint_classes::srcref_data<
fmpz_mod_polyxx, fmpz_mod_polyxx_ref, fmpz_mod_poly_struct> >
fmpz_mod_polyxx_srcref;
#define FMPZ_MOD_POLYXX_COND_S FLINTXX_COND_S(fmpz_mod_polyxx)
#define FMPZ_MOD_POLYXX_COND_T FLINTXX_COND_T(fmpz_mod_polyxx)
namespace detail {
template<>
struct fmpz_mod_poly_traits<fmpz_mod_polyxx_srcref>
{
typedef fmpzxx_srcref lead_srcref_t;
typedef fmpzxx_srcref lead_ref_t;
template<class P>
static lead_srcref_t lead(P p)
{return lead_srcref_t::make(fmpz_mod_poly_lead(p._poly()));}
};
template<>
struct fmpz_mod_poly_traits<fmpz_mod_polyxx_ref>
{
typedef fmpzxx_ref lead_ref_t;
typedef fmpzxx_ref lead_srcref_t;
template<class P>
static lead_ref_t lead(P p)
{return lead_ref_t::make(fmpz_mod_poly_lead(p._poly()));}
};
template<>
struct fmpz_mod_poly_traits<fmpz_mod_polyxx>
{
typedef fmpzxx_ref lead_ref_t;
typedef fmpzxx_srcref lead_srcref_t;
template<class P>
static lead_ref_t lead(P& p)
{return lead_ref_t::make(fmpz_mod_poly_lead(p._poly()));}
template<class P>
static lead_srcref_t lead(const P& p)
{return lead_srcref_t::make(fmpz_mod_poly_lead(p._poly()));}
};
struct fmpz_mod_poly_data
{
fmpz_mod_poly_t inner;
typedef fmpz_mod_poly_t& data_ref_t;
typedef const fmpz_mod_poly_t& data_srcref_t;
template<class Fmpz>
fmpz_mod_poly_data(const Fmpz& n,
typename mp::enable_if<traits::is_fmpzxx<Fmpz> >::type* = 0)
{
fmpz_mod_poly_init(inner, n.evaluate()._fmpz());
}
template<class Fmpz>
fmpz_mod_poly_data(const Fmpz& n, slong alloc,
typename mp::enable_if<traits::is_fmpzxx<Fmpz> >::type* = 0)
{
fmpz_mod_poly_init2(inner, n.evaluate()._fmpz(), alloc);
}
~fmpz_mod_poly_data() {fmpz_mod_poly_clear(inner);}
fmpz_mod_poly_data(const fmpz_mod_poly_data& o)
{
fmpz_mod_poly_init(inner, fmpz_mod_poly_modulus(o.inner));
fmpz_mod_poly_set(inner, o.inner);
}
fmpz_mod_poly_data(fmpz_mod_polyxx_srcref r)
{
fmpz_mod_poly_init(inner, r.modulus()._fmpz());
fmpz_mod_poly_set(inner, r._poly());
}
};
struct is_fmpz_mod_polyxx_predicate
{
template<class T> struct type : FMPZ_MOD_POLYXX_COND_S<T> { };
};
}
template<class Operation, class Data>
inline fmpzxx_srcref
fmpz_mod_polyxx_expression<Operation, Data>::modulus() const
{
return tools::find_subexpr<detail::is_fmpz_mod_polyxx_predicate>(
*this)._mod();
}
namespace traits {
template<class T> struct is_fmpz_mod_polyxx : mp::or_<
traits::is_T_expr<T, fmpz_mod_polyxx>,
flint_classes::is_source<fmpz_mod_polyxx, T> > { };
}
namespace rules {
FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_MOD_POLYXX_COND_T,
FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_set(to._poly(), from._poly()))
FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_MOD_POLYXX_COND_T,
traits::is_unsigned_integer, fmpz_mod_poly_set_ui(to._poly(), from))
FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_MOD_POLYXX_COND_T,
FMPZXX_COND_S, fmpz_mod_poly_set_fmpz(to._poly(), from._fmpz()))
FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_MOD_POLYXX_COND_T, FMPZ_POLYXX_COND_S,
fmpz_mod_poly_set_fmpz_poly(to._poly(), from._poly()))
FLINTXX_DEFINE_CONVERSION_TMP(fmpz_polyxx, fmpz_mod_polyxx,
fmpz_mod_poly_get_fmpz_poly(to._poly(), from._poly()))
FLINTXX_DEFINE_SWAP(fmpz_mod_polyxx, fmpz_mod_poly_swap(e1._poly(), e2._poly()))
FLINTXX_DEFINE_EQUALS(fmpz_mod_polyxx, fmpz_mod_poly_equal(e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(fmpz_mod_polyxx_get_coeff_op, fmpzxx,
FMPZ_MOD_POLYXX_COND_S, traits::fits_into_slong,
fmpz_mod_poly_get_coeff_fmpz(to._fmpz(), e1._poly(), e2))
FLINT_DEFINE_PRINT_COND(FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_fprint(to, from._poly()))
FLINT_DEFINE_PRINT_PRETTY_COND_2(FMPZ_MOD_POLYXX_COND_S, const char*,
fmpz_mod_poly_fprint_pretty(to, from._poly(), extra))
FLINT_DEFINE_READ_COND(FMPZ_MOD_POLYXX_COND_T, fmpz_mod_poly_fread(from, to._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(plus, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_add(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_sub(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZXX_COND_S,
fmpz_mod_poly_scalar_mul_fmpz(to._poly(), e1._poly(), e2._fmpz()))
FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_mul(to._poly(), e1._poly(), e2._poly()))
// TODO expose the temporary
FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_polyxx tmp(to.modulus());
fmpz_mod_poly_divrem(to._poly(), tmp._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_UNARY_EXPR_COND(negate, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_neg(to._poly(), from._poly()))
FLINT_DEFINE_UNARY_EXPR_COND(fmpz_mod_polyxx_lead_op, fmpzxx,
FMPZ_MOD_POLYXX_COND_S,
fmpz_set(to._fmpz(), fmpz_mod_poly_lead(from._poly())))
FLINT_DEFINE_BINARY_EXPR_COND2(shift_left_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, traits::fits_into_slong,
fmpz_mod_poly_shift_left(to._poly(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(shift_right_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, traits::fits_into_slong,
fmpz_mod_poly_shift_right(to._poly(), e1._poly(), e2))
FLINT_DEFINE_UNARY_EXPR_COND(make_monic_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_make_monic(to._poly(), from._poly()))
FLINT_DEFINE_THREEARY_EXPR_COND3(mullow_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, traits::fits_into_slong,
fmpz_mod_poly_mullow(to._poly(), e1._poly(), e2._poly(), e3))
FLINT_DEFINE_THREEARY_EXPR_COND3(mulmod_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_mulmod(to._poly(), e1._poly(), e2._poly(), e3._poly()))
FLINT_DEFINE_UNARY_EXPR_COND(sqr_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_sqr(to._poly(), from._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(modulo, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_rem(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_THREEARY_EXPR_COND3(powmod_binexp_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, traits::is_unsigned_integer, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_powmod_ui_binexp(to._poly(), e1._poly(), e2, e3._poly()))
FLINT_DEFINE_THREEARY_EXPR_COND3(powmod_binexp_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_powmod_fmpz_binexp(
to._poly(), e1._poly(), e2._fmpz(), e3._poly()))
FLINT_DEFINE_THREEARY_EXPR_COND3(pow_trunc_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong,
fmpz_mod_poly_pow_trunc(to._poly(), e1._poly(), e2, e3))
FLINT_DEFINE_THREEARY_EXPR_COND3(pow_trunc_binexp_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong,
fmpz_mod_poly_pow_trunc_binexp(to._poly(), e1._poly(), e2, e3))
FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, traits::is_unsigned_integer,
fmpz_mod_poly_pow(to._poly(), e1._poly(), e2))
namespace rdetail {
typedef make_ltuple<mp::make_tuple<fmpz_mod_polyxx, fmpz_mod_polyxx>::type>::type
fmpz_mod_polyxx_pair;
typedef make_ltuple<mp::make_tuple<
fmpzxx, fmpz_mod_polyxx, fmpz_mod_polyxx>::type>::type
fmpz_mod_poly_divrem_f_rt;
} // rdetail
FLINT_DEFINE_BINARY_EXPR_COND2(divrem_basecase_op, rdetail::fmpz_mod_polyxx_pair,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_divrem_basecase(
to.template get<0>()._poly(), to.template get<1>()._poly(),
e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(divrem_divconquer_op, rdetail::fmpz_mod_polyxx_pair,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_divrem_divconquer(
to.template get<0>()._poly(), to.template get<1>()._poly(),
e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(divrem_op, rdetail::fmpz_mod_polyxx_pair,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_divrem_divconquer(
to.template get<0>()._poly(), to.template get<1>()._poly(),
e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(divrem_f_op, rdetail::fmpz_mod_poly_divrem_f_rt,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_divrem_f(
to.template get<0>()._fmpz(), to.template get<1>()._poly(),
to.template get<2>()._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(div_basecase_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_div_basecase(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(rem_basecase_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_rem_basecase(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_newton_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, traits::fits_into_slong,
fmpz_mod_poly_inv_series_newton(to._poly(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(gcd_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_gcd(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(gcd_euclidean_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_gcd_euclidean(to._poly(), e1._poly(), e2._poly()))
namespace rdetail {
typedef make_ltuple<mp::make_tuple<
fmpz_mod_polyxx, fmpz_mod_polyxx, fmpz_mod_polyxx>::type>::type
fmpz_mod_polyxx_triple;
} // rdetail
FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_op, rdetail::fmpz_mod_polyxx_triple,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_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_euclidean_op, rdetail::fmpz_mod_polyxx_triple,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_xgcd_euclidean(to.template get<0>()._poly(),
to.template get<1>()._poly(),
to.template get<2>()._poly(), e1._poly(), e2._poly()))
namespace rdetail {
typedef make_ltuple<mp::make_tuple<fmpzxx, fmpz_mod_polyxx>::type>::type
fmpz_mod_gcd_f_rt;
} // rdetail
FLINT_DEFINE_BINARY_EXPR_COND2(gcd_f_op, rdetail::fmpz_mod_gcd_f_rt,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_gcd_f(to.template get<0>()._fmpz(),
to.template get<1>()._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(gcd_euclidean_f_op, rdetail::fmpz_mod_gcd_f_rt,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_gcd_euclidean_f(to.template get<0>()._fmpz(),
to.template get<1>()._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(gcdinv_op, rdetail::fmpz_mod_polyxx_pair,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_gcdinv(
to.template get<0>()._poly(), to.template get<1>()._poly(),
e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(invmod_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
execution_check(fmpz_mod_poly_invmod(to._poly(), e1._poly(), e2._poly()),
"invmod", "fmpz_mod_polyxx"))
FLINT_DEFINE_UNARY_EXPR_COND(derivative_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_derivative(to._poly(), from._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, fmpzxx,
FMPZ_MOD_POLYXX_COND_S, FMPZXX_COND_S,
fmpz_mod_poly_evaluate_fmpz(to._fmpz(), e1._poly(), e2._fmpz()))
FLINT_DEFINE_BINARY_EXPR_COND2(compose_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_compose(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(compose_divconquer_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_compose_divconquer(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(compose_horner_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_compose_horner(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_THREEARY_EXPR_COND3(compose_mod_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_compose_mod(to._poly(), e1._poly(), e2._poly(), e3._poly()))
FLINT_DEFINE_THREEARY_EXPR_COND3(compose_mod_horner_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_compose_mod_horner(
to._poly(), e1._poly(), e2._poly(), e3._poly()))
FLINT_DEFINE_THREEARY_EXPR_COND3(compose_mod_brent_kung_op, fmpz_mod_polyxx,
FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S,
fmpz_mod_poly_compose_mod_brent_kung(
to._poly(), e1._poly(), e2._poly(), e3._poly()))
} // rules
///////////////////////////////////////////////////////////////////////////////
// fmpz_mod_poly_vecxx (for radix conversion)
///////////////////////////////////////////////////////////////////////////////
namespace detail {
struct fmpz_mod_poly_vector_data
{
slong size;
fmpz_mod_poly_struct** array;
template<class Fmpz>
void init(slong n, const Fmpz& f)
{
size = n;
array = new fmpz_mod_poly_struct*[n];
for(slong i = 0;i < n;++i)
{
array[i] = new fmpz_mod_poly_struct();
fmpz_mod_poly_init(array[i], f._fmpz());
}
}
template<class Fmpz>
fmpz_mod_poly_vector_data(slong n, const Fmpz& f,
typename mp::enable_if<traits::is_fmpzxx<Fmpz> >::type* = 0)
{
init(n, f.evaluate());
}
~fmpz_mod_poly_vector_data()
{
for(slong i = 0;i < size;++i)
{
fmpz_mod_poly_clear(array[i]);
delete array[i];
}
delete[] array;
}
fmpz_mod_poly_vector_data(const fmpz_mod_poly_vector_data& o)
: size(o.size)
{
array = new fmpz_mod_poly_struct*[size];
for(slong i = 0;i < size;++i)
{
array[i] = new fmpz_mod_poly_struct();
fmpz_mod_poly_init(array[i], &o.array[0]->p);
fmpz_mod_poly_set(array[i], o.array[i]);
}
}
fmpz_mod_polyxx_ref at(slong i)
{return fmpz_mod_polyxx_ref::make(array[i]);}
fmpz_mod_polyxx_srcref at(slong i) const
{return fmpz_mod_polyxx_srcref::make(array[i]);}
bool equals(const fmpz_mod_poly_vector_data& o) const
{
if(size != o.size)
return false;
for(slong i = 0;i < size;++i)
if(!fmpz_mod_poly_equal(array[i], o.array[i]))
return false;
return true;
}
};
// TODO extend this somewhat similarly to the nmod* setup
template<class T>
fmpzxx_srcref find_fmpz_mod_polyxx_mod(const T& t)
{
// this works because there are not actually any functions operating on
// fmpz_mod_poly_vecxx
return tools::find_subexpr<detail::is_fmpz_mod_polyxx_predicate>(
t)._mod();
}
struct fmpz_mod_poly_vector_traits
: wrapped_vector_traits<fmpz_mod_polyxx, slong, fmpz_mod_polyxx_ref,
fmpz_mod_polyxx_srcref, fmpz_mod_poly_struct*>
{
template<class Expr>
static typename Expr::evaluated_t create_temporary(const Expr& e)
{
return typename Expr::evaluated_t(
e.size(), find_fmpz_mod_polyxx_mod(e));
}
};
} // detail
// TODO would it make more sense to have this have its own class?
typedef vector_expression<
detail::fmpz_mod_poly_vector_traits, operations::immediate,
detail::fmpz_mod_poly_vector_data> fmpz_mod_poly_vecxx;
// TODO references
template<>
struct enable_vector_rules<fmpz_mod_poly_vecxx> : mp::false_ { };
namespace rules {
// TODO hack to make code look like references are implemented
template<class T> struct FMPZ_MOD_POLY_VECXX_COND_S
: mp::equal_types<T, fmpz_mod_poly_vecxx> { };
#define FMPZ_MOD_POLY_VECXX_COND_T FMPZ_MOD_POLY_VECXX_COND_S
// TODO references
FLINT_DEFINE_GET(equals, bool, fmpz_mod_poly_vecxx, e1._data().equals(e2._data()))
} // rules
///////////////////////////////////////////////////////////////////////////////
// radix conversion
///////////////////////////////////////////////////////////////////////////////
class fmpz_mod_poly_radixxx
{
private:
fmpz_mod_poly_radix_t inner;
// not copyable
fmpz_mod_poly_radixxx(const fmpz_mod_poly_radixxx&);
public:
template<class Fmpz_mod_poly>
fmpz_mod_poly_radixxx(const Fmpz_mod_poly& r, slong deg,
typename mp::enable_if<
traits::is_fmpz_mod_polyxx<Fmpz_mod_poly> >::type* = 0)
{fmpz_mod_poly_radix_init(inner, r.evaluate()._poly(), deg);}
~fmpz_mod_poly_radixxx() {fmpz_mod_poly_radix_clear(inner);}
fmpz_mod_poly_radix_t& _data() {return inner;}
const fmpz_mod_poly_radix_t& _data() const {return inner;}
slong degR() const {return inner->degR;}
};
namespace traits {
template<class T> struct is_fmpz_mod_poly_radixxx
: mp::equal_types<T, fmpz_mod_poly_radixxx> { };
} // traits
namespace vectors {
template<>
struct outsize<operations::radix_op>
{
template<class Expr>
static unsigned get(const Expr& e)
{
return e._data().first().degree() / e._data().second().degR() + 1;
}
};
}
namespace rules {
FLINT_DEFINE_BINARY_EXPR_COND2(radix_op, fmpz_mod_poly_vecxx,
FMPZ_MOD_POLYXX_COND_S, traits::is_fmpz_mod_poly_radixxx,
fmpz_mod_poly_radix(to._array(), e1._poly(), e2._data()))
}
} // flint
#include "fmpz_mod_poly_factorxx.h"
#endif