/*============================================================================= 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_POLYXX_H #define FMPZ_POLYXX_H #include #include #include "flint.h" #include "fmpz_poly.h" #include "fmpzxx.h" #include "fmpz_vecxx.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/traits.h" #include "flintxx/traits_fwd.h" // TODO exhibit this as a specialisation of a generic poly // TODO newton basis? // TODO power series class? // TODO input // TODO addmul // TODO more hensel lifting? namespace flint { // function "declarations" FLINT_DEFINE_UNOP(sqr_karatsuba) FLINT_DEFINE_UNOP(sqrt_classical) FLINT_DEFINE_BINOP(evaluate_divconquer) FLINT_DEFINE_BINOP(evaluate_horner) FLINT_DEFINE_BINOP(gcd_heuristic) FLINT_DEFINE_BINOP(gcd_modular) FLINT_DEFINE_BINOP(gcd_subresultant) FLINT_DEFINE_BINOP(mul_karatsuba) FLINT_DEFINE_BINOP(mulmid_classical) FLINT_DEFINE_BINOP(mul_SS) FLINT_DEFINE_BINOP(divides) FLINT_DEFINE_BINOP(pow_addchains) FLINT_DEFINE_BINOP(pow_binomial) FLINT_DEFINE_BINOP(pow_multinomial) FLINT_DEFINE_BINOP(pseudo_div) FLINT_DEFINE_BINOP(pseudo_divrem) FLINT_DEFINE_BINOP(pseudo_divrem_basecase) FLINT_DEFINE_BINOP(pseudo_divrem_cohen) FLINT_DEFINE_BINOP(pseudo_divrem_divconquer) FLINT_DEFINE_BINOP(pseudo_rem) FLINT_DEFINE_BINOP(pseudo_rem_cohen) FLINT_DEFINE_BINOP(sqrlow) FLINT_DEFINE_BINOP(sqrlow_classical) FLINT_DEFINE_BINOP(sqrlow_karatsuba_n) FLINT_DEFINE_BINOP(sqrlow_KS) FLINT_DEFINE_BINOP(taylor_shift_divconquer) FLINT_DEFINE_BINOP(xgcd_modular) FLINT_DEFINE_THREEARY(mulhigh_karatsuba_n) FLINT_DEFINE_THREEARY(mulhigh_n) FLINT_DEFINE_THREEARY(mullow_karatsuba_n) FLINT_DEFINE_THREEARY(mullow_SS) FLINT_DEFINE_BINOP(fmpz_polyxx_interpolate) FLINT_DEFINE_UNOP(fmpz_polyxx_product_roots) FLINT_DEFINE_UNOP(fmpz_polyxx_lead) FLINT_DEFINE_BINOP(fmpz_polyxx_get_coeff) FLINT_DEFINE_BINOP(fmpz_polyxx_bit_unpack) FLINT_DEFINE_BINOP(fmpz_polyxx_bit_unpack_unsigned) FLINT_DEFINE_SEVENARY(hensel_lift) FLINT_DEFINE_SEVENARY(hensel_lift_without_inverse) FLINT_DEFINE_SIXARY(hensel_lift_only_inverse) namespace detail { template struct fmpz_poly_traits { typedef FLINT_UNOP_BUILD_RETTYPE( fmpz_polyxx_lead, fmpzxx, Poly) lead_ref_t; typedef lead_ref_t lead_srcref_t; static lead_ref_t lead(const Poly& p) {return fmpz_polyxx_lead(p);} template struct coeff { typedef FLINT_BINOP_ENABLE_RETTYPE(fmpz_polyxx_get_coeff, Poly, T) ref_t; typedef ref_t srcref_t; static ref_t get(const Poly& p, const T& t) {return fmpz_polyxx_get_coeff(p, t);} }; }; } template class fmpz_polyxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; typedef detail::fmpz_poly_traits poly_traits_t; FLINTXX_DEFINE_BASICS(fmpz_polyxx_expression) FLINTXX_DEFINE_CTORS(fmpz_polyxx_expression) FLINTXX_DEFINE_C_REF(fmpz_polyxx_expression, fmpz_poly_struct, _poly) // static methods which only make sense with fmpz_polyxx static fmpz_polyxx_expression randtest(frandxx& state, slong len, mp_bitcnt_t bits) { fmpz_polyxx_expression res; fmpz_poly_randtest(res._poly(), state._data(), len, bits); return res; } static fmpz_polyxx_expression randtest_unsigned(frandxx& state, slong len, mp_bitcnt_t bits) { fmpz_polyxx_expression res; fmpz_poly_randtest_unsigned(res._poly(), state._data(), len, bits); return res; } static fmpz_polyxx_expression randtest_not_zero(frandxx& state, slong len, mp_bitcnt_t bits) { fmpz_polyxx_expression res; fmpz_poly_randtest_not_zero(res._poly(), state._data(), len, bits); return res; } template static FLINT_BINOP_ENABLE_RETTYPE(fmpz_polyxx_interpolate, Fmpz_vec1, Fmpz_vec2) interpolate(const Fmpz_vec1& xs, const Fmpz_vec2& ys) { return fmpz_polyxx_interpolate(xs, ys); } template static FLINT_UNOP_ENABLE_RETTYPE(fmpz_polyxx_product_roots, Fmpz_vec) product_roots(const Fmpz_vec& xs) { return fmpz_polyxx_product_roots(xs); } template static FLINT_BINOP_ENABLE_RETTYPE(fmpz_polyxx_bit_unpack, Arg1, Arg2) bit_unpack(const Arg1& a1, const Arg2& a2) { return fmpz_polyxx_bit_unpack(a1, a2); } template static FLINT_BINOP_ENABLE_RETTYPE(fmpz_polyxx_bit_unpack_unsigned, Arg1, Arg2) bit_unpack_unsigned(const Arg1& a1, const Arg2& a2) { return fmpz_polyxx_bit_unpack_unsigned(a1, a2); } template static fmpz_polyxx_expression from_ground(const T& t) { fmpz_polyxx_expression res; fmpzxx u; u = t; res.set_coeff(0, u); return res; } template static fmpz_polyxx_expression _lift(const Nmod_poly& poly) { fmpz_polyxx_expression res(poly.length()); fmpz_poly_set_nmod_poly(res._poly(), poly._poly()); return res; } template static fmpz_polyxx_expression lift(const Nmod_poly& poly, typename mp::enable_if >::type* = 0) { return _lift(poly.evaluate()); } template static fmpz_polyxx_expression _lift_unsigned(const Nmod_poly& poly) { fmpz_polyxx_expression res(poly.length()); fmpz_poly_set_nmod_poly_unsigned(res._poly(), poly.evaluate()._poly()); return res; } template static fmpz_polyxx_expression lift_unsigned(const Nmod_poly& poly, typename mp::enable_if >::type* = 0) { return _lift_unsigned(poly.evaluate()); } static fmpz_polyxx_expression zero() {return fmpz_polyxx_expression();} static fmpz_polyxx_expression one() { fmpz_polyxx_expression res; res.set_one(); return res; } // These only make sense with immediates void realloc(slong alloc) {fmpz_poly_realloc(_poly(), alloc);} void fit_length(slong len) {fmpz_poly_fit_length(_poly(), len);} void _normalise() {_fmpz_poly_normalise(_poly());} void _set_length(slong len) {_fmpz_poly_set_length(_poly(), len);} void zero_coeffs(slong i, slong j) {fmpz_poly_zero_coeffs(_poly(), i, j);} void set_zero() {fmpz_poly_zero(_poly());} void set_one() {fmpz_poly_one(_poly());} // The result of these are undefined if n is >= length // You also may have to call _normalise(). template typename poly_traits_t::template coeff::ref_t coeff(const T& n) { return poly_traits_t::template coeff::get(*this, n); } template typename poly_traits_t::template coeff::srcref_t coeff(const T& n) const { return poly_traits_t::template coeff::get(*this, n); } 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); } // These only make sense with target immediates template typename mp::enable_if >::type set_coeff(slong n, const Fmpz& x) { fmpz_poly_set_coeff_fmpz(_poly(), n, x.evaluate()._fmpz()); } template typename mp::enable_if >::type set_coeff(slong n, T x) { fmpz_poly_set_coeff_si(_poly(), n, x); } template typename mp::enable_if >::type set_coeff(slong n, T x) { fmpz_poly_set_coeff_ui(_poly(), n, x); } void truncate(slong n) {fmpz_poly_truncate(_poly(), n);} // These cause evaluation slong length() const {return fmpz_poly_length(this->evaluate()._poly());} slong degree() const {return fmpz_poly_degree(this->evaluate()._poly());} bool is_one() const {return fmpz_poly_is_one(this->evaluate()._poly());} bool is_zero() const {return fmpz_poly_is_zero(this->evaluate()._poly());} bool is_unit() const {return fmpz_poly_is_unit(this->evaluate()._poly());} ulong max_limbs() const {return fmpz_poly_max_limbs(this->evaluate()._poly());} slong max_bits() const {return fmpz_poly_max_bits(this->evaluate()._poly());} std::string pretty(const char* x) const { char* str = fmpz_poly_get_str_pretty(this->evaluate()._poly(), x); std::string res(str); flint_free(str); return res; } void signature(slong& r1, slong& r2) const { fmpz_poly_signature(&r1, &r2, this->evaluate()._poly()); } int read_pretty(char** x, FILE* f = stdin) { return fmpz_poly_fread_pretty(f, _poly(), x); } // lazy member forwarding FLINTXX_DEFINE_MEMBER_BINOP_(operator(), compeval) FLINTXX_DEFINE_MEMBER_BINOP_(get_coeff, fmpz_polyxx_get_coeff) FLINTXX_DEFINE_MEMBER_BINOP(bit_pack) 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(divexact) FLINTXX_DEFINE_MEMBER_BINOP(divides) FLINTXX_DEFINE_MEMBER_BINOP(divrem) FLINTXX_DEFINE_MEMBER_BINOP(divrem_basecase) FLINTXX_DEFINE_MEMBER_BINOP(divrem_divconquer) FLINTXX_DEFINE_MEMBER_BINOP(div_root) FLINTXX_DEFINE_MEMBER_BINOP(evaluate_divconquer) FLINTXX_DEFINE_MEMBER_BINOP(evaluate_horner) FLINTXX_DEFINE_MEMBER_BINOP(fdiv_2exp) FLINTXX_DEFINE_MEMBER_BINOP(gcd) FLINTXX_DEFINE_MEMBER_BINOP(gcd_heuristic) FLINTXX_DEFINE_MEMBER_BINOP(gcd_modular) FLINTXX_DEFINE_MEMBER_BINOP(gcd_subresultant) FLINTXX_DEFINE_MEMBER_BINOP(inv_series) FLINTXX_DEFINE_MEMBER_BINOP(inv_series_newton) FLINTXX_DEFINE_MEMBER_BINOP(lcm) FLINTXX_DEFINE_MEMBER_BINOP(mul_2exp) FLINTXX_DEFINE_MEMBER_BINOP(mul_classical) FLINTXX_DEFINE_MEMBER_BINOP(mul_karatsuba) FLINTXX_DEFINE_MEMBER_BINOP(mul_KS) FLINTXX_DEFINE_MEMBER_BINOP(mulmid_classical) FLINTXX_DEFINE_MEMBER_BINOP(mul_SS) FLINTXX_DEFINE_MEMBER_BINOP(shift_left) FLINTXX_DEFINE_MEMBER_BINOP(shift_right) FLINTXX_DEFINE_MEMBER_BINOP(pow) FLINTXX_DEFINE_MEMBER_BINOP(pow_addchains) FLINTXX_DEFINE_MEMBER_BINOP(pow_binexp) FLINTXX_DEFINE_MEMBER_BINOP(pow_binomial) FLINTXX_DEFINE_MEMBER_BINOP(pow_multinomial) FLINTXX_DEFINE_MEMBER_BINOP(pseudo_div) FLINTXX_DEFINE_MEMBER_BINOP(pseudo_divrem) FLINTXX_DEFINE_MEMBER_BINOP(pseudo_divrem_basecase) FLINTXX_DEFINE_MEMBER_BINOP(pseudo_divrem_cohen) FLINTXX_DEFINE_MEMBER_BINOP(pseudo_divrem_divconquer) FLINTXX_DEFINE_MEMBER_BINOP(pseudo_rem) FLINTXX_DEFINE_MEMBER_BINOP(pseudo_rem_cohen) FLINTXX_DEFINE_MEMBER_BINOP(resultant) 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(smod) FLINTXX_DEFINE_MEMBER_BINOP(sqrlow) FLINTXX_DEFINE_MEMBER_BINOP(sqrlow_classical) FLINTXX_DEFINE_MEMBER_BINOP(sqrlow_karatsuba_n) FLINTXX_DEFINE_MEMBER_BINOP(sqrlow_KS) FLINTXX_DEFINE_MEMBER_BINOP(taylor_shift) FLINTXX_DEFINE_MEMBER_BINOP(taylor_shift_divconquer) FLINTXX_DEFINE_MEMBER_BINOP(taylor_shift_horner) FLINTXX_DEFINE_MEMBER_BINOP(tdiv) FLINTXX_DEFINE_MEMBER_BINOP(tdiv_2exp) FLINTXX_DEFINE_MEMBER_BINOP(xgcd) FLINTXX_DEFINE_MEMBER_BINOP(xgcd_modular) FLINTXX_DEFINE_MEMBER_UNOP(derivative) FLINTXX_DEFINE_MEMBER_UNOP(primitive_part) FLINTXX_DEFINE_MEMBER_UNOP(sqr) FLINTXX_DEFINE_MEMBER_UNOP(sqr_classical) FLINTXX_DEFINE_MEMBER_UNOP(sqr_karatsuba) FLINTXX_DEFINE_MEMBER_UNOP(sqr_KS) FLINTXX_DEFINE_MEMBER_UNOP(sqrt) FLINTXX_DEFINE_MEMBER_UNOP(sqrt_classical) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpzxx, bound_roots) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpzxx, twonorm) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpzxx, content) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpzxx, height) FLINTXX_DEFINE_MEMBER_3OP(compose_series) FLINTXX_DEFINE_MEMBER_3OP(compose_series_brent_kung) FLINTXX_DEFINE_MEMBER_3OP(compose_series_horner) FLINTXX_DEFINE_MEMBER_3OP(div_series) FLINTXX_DEFINE_MEMBER_3OP(mulhigh_classical) FLINTXX_DEFINE_MEMBER_3OP(mulhigh_karatsuba_n) FLINTXX_DEFINE_MEMBER_3OP(mulhigh_n) FLINTXX_DEFINE_MEMBER_3OP(mullow) FLINTXX_DEFINE_MEMBER_3OP(mullow_classical) FLINTXX_DEFINE_MEMBER_3OP(mullow_karatsuba_n) FLINTXX_DEFINE_MEMBER_3OP(mullow_KS) FLINTXX_DEFINE_MEMBER_3OP(mullow_SS) FLINTXX_DEFINE_MEMBER_3OP(pow_trunc) FLINTXX_DEFINE_MEMBER_4OP(CRT) }; namespace detail { struct fmpz_poly_data; } typedef fmpz_polyxx_expression fmpz_polyxx; typedef fmpz_polyxx_expression > fmpz_polyxx_ref; typedef fmpz_polyxx_expression > fmpz_polyxx_srcref; namespace detail { template<> struct fmpz_poly_traits { typedef fmpzxx_srcref lead_srcref_t; typedef fmpzxx_srcref lead_ref_t; template static lead_srcref_t lead(const P& p) {return lead_srcref_t::make(fmpz_poly_lead(p._poly()));} template struct coeff { typedef typename mp::enable_if< traits::is_integer, fmpzxx_srcref>::type ref_t; typedef ref_t srcref_t; template static srcref_t get(const P& p, const T& n) {return srcref_t::make(fmpz_poly_coeff_ptr(p._poly(), n));} }; }; template<> struct fmpz_poly_traits { typedef fmpzxx_ref lead_ref_t; typedef fmpzxx_ref lead_srcref_t; template static lead_ref_t lead(P p) {return lead_ref_t::make(fmpz_poly_lead(p._poly()));} template struct coeff { typedef fmpzxx_ref ref_t; typedef fmpzxx_ref srcref_t; template static ref_t get(P p, const T& n) {return ref_t::make(fmpz_poly_get_coeff_ptr(p._poly(), n));} }; }; template<> struct fmpz_poly_traits { typedef fmpzxx_ref lead_ref_t; typedef fmpzxx_srcref lead_srcref_t; template static lead_ref_t lead(P& p) {return lead_ref_t::make(fmpz_poly_lead(p._poly()));} template static lead_srcref_t lead(const P& p) {return lead_srcref_t::make(fmpz_poly_lead(p._poly()));} template struct coeff { typedef fmpzxx_ref ref_t; typedef fmpzxx_srcref srcref_t; template static ref_t get(P& p, const T& n) {return ref_t::make(fmpz_poly_get_coeff_ptr(p._poly(), n));} template static srcref_t get(const P& p, const T& n) {return srcref_t::make(fmpz_poly_get_coeff_ptr(p._poly(), n));} }; }; struct fmpz_poly_data { fmpz_poly_t inner; typedef fmpz_poly_t& data_ref_t; typedef const fmpz_poly_t& data_srcref_t; fmpz_poly_data() {fmpz_poly_init(inner);} ~fmpz_poly_data() {fmpz_poly_clear(inner);} fmpz_poly_data(const fmpz_poly_data& o) { fmpz_poly_init(inner); fmpz_poly_set(inner, o.inner); } fmpz_poly_data(fmpz_polyxx_srcref r) { fmpz_poly_init(inner); fmpz_poly_set(inner, r._poly()); } fmpz_poly_data(slong alloc) { fmpz_poly_init2(inner, alloc); } fmpz_poly_data(const char* str) { fmpz_poly_init(inner); execution_check(!fmpz_poly_set_str(inner, str), "construct from string", "fmpz_polyxx"); } }; } // detail namespace traits { template struct is_fmpz_polyxx : mp::or_< traits::is_T_expr, flint_classes::is_source > { }; } // traits namespace mp { template struct all_fmpz_polyxx : mp::and_, all_fmpz_polyxx > { }; template struct all_fmpz_polyxx : traits::is_fmpz_polyxx { }; template struct enable_all_fmpz_polyxx : mp::enable_if, Out> { }; } // mp namespace rules { #define FMPZ_POLYXX_COND_S FLINTXX_COND_S(fmpz_polyxx) #define FMPZ_POLYXX_COND_T FLINTXX_COND_T(fmpz_polyxx) FLINTXX_DEFINE_EQUALS(fmpz_polyxx, fmpz_poly_equal(e1._poly(), e2._poly())) FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_POLYXX_COND_T, FMPZ_POLYXX_COND_S, fmpz_poly_set(to._poly(), from._poly())) FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_POLYXX_COND_T, traits::is_signed_integer, fmpz_poly_set_si(to._poly(), from)) FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_POLYXX_COND_T, traits::is_unsigned_integer, fmpz_poly_set_ui(to._poly(), from)) FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_POLYXX_COND_T, FMPZXX_COND_S, fmpz_poly_set_fmpz(to._poly(), from._fmpz())) FLINTXX_DEFINE_ASSIGN_STR(fmpz_polyxx, execution_check( !fmpz_poly_set_str(to._poly(), from), "assign string", "fmpz_polyxx")) FLINT_DEFINE_PRINT_COND(FMPZ_POLYXX_COND_S, fmpz_poly_fprint(to, from._poly())) FLINT_DEFINE_PRINT_PRETTY_COND_2(FMPZ_POLYXX_COND_S, const char*, fmpz_poly_fprint_pretty(to, from._poly(), extra)) FLINT_DEFINE_READ_COND(FMPZ_POLYXX_COND_T, fmpz_poly_fread(from, to._poly())) FLINTXX_DEFINE_TO_STR(fmpz_polyxx, fmpz_poly_get_str(from._poly())) FLINTXX_DEFINE_SWAP(fmpz_polyxx, fmpz_poly_swap(e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(reverse_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::fits_into_slong, fmpz_poly_reverse(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(plus, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_add(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_sub(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_UNARY_EXPR_COND(negate, fmpz_polyxx, FMPZ_POLYXX_COND_S, fmpz_poly_neg(to._poly(), from._poly())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_scalar_mul_fmpz(to._poly(), e1._poly(), e2._fmpz())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::is_signed_integer, fmpz_poly_scalar_mul_si(to._poly(), e1._poly(), e2)) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::is_unsigned_integer, fmpz_poly_scalar_mul_ui(to._poly(), e1._poly(), e2)) FLINT_DEFINE_CBINARY_EXPR_COND2(mul_2exp_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::is_unsigned_integer, fmpz_poly_scalar_mul_2exp(to._poly(), e1._poly(), e2)) FLINT_DEFINE_CBINARY_EXPR_COND2(divided_by, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_scalar_fdiv_fmpz(to._poly(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::is_unsigned_integer, fmpz_poly_scalar_fdiv_ui(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::is_signed_integer, fmpz_poly_scalar_fdiv_si(to._poly(), e1._poly(), e2)) FLINT_DEFINE_CBINARY_EXPR_COND2(fdiv_2exp_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::is_unsigned_integer, fmpz_poly_scalar_fdiv_2exp(to._poly(), e1._poly(), e2)) #define FMPZ_POLYXX_DEFINE_SCALAR_DIVFUNCS(name) \ FLINT_DEFINE_CBINARY_EXPR_COND2(name##_op, fmpz_polyxx, \ FMPZ_POLYXX_COND_S, FMPZXX_COND_S, \ fmpz_poly_scalar_##name##_fmpz(to._poly(), e1._poly(), e2._fmpz())) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, fmpz_polyxx, \ FMPZ_POLYXX_COND_S, traits::is_unsigned_integer, \ fmpz_poly_scalar_##name##_ui(to._poly(), e1._poly(), e2)) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, fmpz_polyxx, \ FMPZ_POLYXX_COND_S, traits::is_signed_integer, \ fmpz_poly_scalar_##name##_si(to._poly(), e1._poly(), e2)) FMPZ_POLYXX_DEFINE_SCALAR_DIVFUNCS(tdiv) FMPZ_POLYXX_DEFINE_SCALAR_DIVFUNCS(divexact) FLINT_DEFINE_CBINARY_EXPR_COND2(tdiv_2exp_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::is_unsigned_integer, fmpz_poly_scalar_tdiv_2exp(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(modulo, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_scalar_mod_fmpz(to._poly(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(smod_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_scalar_smod_fmpz(to._poly(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(bit_pack_op, fmpzxx, FMPZ_POLYXX_COND_S, traits::fits_into_mp_bitcnt_t, fmpz_poly_bit_pack(to._fmpz(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(fmpz_polyxx_bit_unpack_op, fmpz_polyxx, FMPZXX_COND_S, traits::fits_into_mp_bitcnt_t, fmpz_poly_bit_unpack(to._poly(), e1._fmpz(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(fmpz_polyxx_bit_unpack_unsigned_op, fmpz_polyxx, FMPZXX_COND_S, traits::fits_into_mp_bitcnt_t, fmpz_poly_bit_unpack_unsigned(to._poly(), e1._fmpz(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_mul(to._poly(), e1._poly(), e2._poly())) #define FMPZ_POLYXX_DEFINE_MUL(name) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, fmpz_polyxx, \ FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, \ fmpz_poly_##name(to._poly(), e1._poly(), e2._poly())) FMPZ_POLYXX_DEFINE_MUL(mul_classical) FMPZ_POLYXX_DEFINE_MUL(mulmid_classical) FMPZ_POLYXX_DEFINE_MUL(mul_karatsuba) FMPZ_POLYXX_DEFINE_MUL(mul_SS) FMPZ_POLYXX_DEFINE_MUL(mul_KS) FLINT_DEFINE_UNARY_EXPR_COND(sqr_KS_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, fmpz_poly_sqr_KS(to._poly(), from._poly())) FLINT_DEFINE_UNARY_EXPR_COND(sqr_karatsuba_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, fmpz_poly_sqr_karatsuba(to._poly(), from._poly())) FLINT_DEFINE_UNARY_EXPR_COND(sqr_classical_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, fmpz_poly_sqr_classical(to._poly(), from._poly())) FLINT_DEFINE_UNARY_EXPR_COND(sqr_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, fmpz_poly_sqr(to._poly(), from._poly())) #define FMPZ_POLYXX_DEFINE_SQRLOW(name) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, fmpz_polyxx, \ FMPZ_POLYXX_COND_S, traits::fits_into_slong, \ fmpz_poly_##name(to._poly(), e1._poly(), e2)) FMPZ_POLYXX_DEFINE_SQRLOW(sqrlow_KS) FMPZ_POLYXX_DEFINE_SQRLOW(sqrlow_karatsuba_n) FMPZ_POLYXX_DEFINE_SQRLOW(sqrlow_classical) FMPZ_POLYXX_DEFINE_SQRLOW(sqrlow) #define FMPZ_POLYXX_DEFINE_POW(name) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, fmpz_polyxx, \ FMPZ_POLYXX_COND_S, traits::is_unsigned_integer, \ fmpz_poly_##name(to._poly(), e1._poly(), e2)) FMPZ_POLYXX_DEFINE_POW(pow_multinomial) FMPZ_POLYXX_DEFINE_POW(pow_binomial) FMPZ_POLYXX_DEFINE_POW(pow_addchains) FMPZ_POLYXX_DEFINE_POW(pow_binexp) FMPZ_POLYXX_DEFINE_POW(pow) FLINT_DEFINE_BINARY_EXPR_COND2(shift_left_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::fits_into_slong, fmpz_poly_shift_left(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(shift_right_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::fits_into_slong, fmpz_poly_shift_right(to._poly(), e1._poly(), e2)) FLINT_DEFINE_UNARY_EXPR_COND(height_op, fmpzxx, FMPZ_POLYXX_COND_S, fmpz_poly_height(to._fmpz(), from._poly())) FLINT_DEFINE_UNARY_EXPR_COND(twonorm_op, fmpzxx, FMPZ_POLYXX_COND_S, fmpz_poly_2norm(to._fmpz(), from._poly())) FMPZ_POLYXX_DEFINE_MUL(gcd) FMPZ_POLYXX_DEFINE_MUL(gcd_subresultant) FMPZ_POLYXX_DEFINE_MUL(gcd_heuristic) FMPZ_POLYXX_DEFINE_MUL(gcd_modular) FMPZ_POLYXX_DEFINE_MUL(lcm) FLINT_DEFINE_BINARY_EXPR_COND2(resultant_op, fmpzxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_resultant(to._fmpz(), e1._poly(), e2._poly())) FLINT_DEFINE_UNARY_EXPR_COND(content_op, fmpzxx, FMPZ_POLYXX_COND_S, fmpz_poly_content(to._fmpz(), from._poly())) FLINT_DEFINE_UNARY_EXPR_COND(primitive_part_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, fmpz_poly_primitive_part(to._poly(), from._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(div_basecase_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_div_basecase(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(div_divconquer_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_div_divconquer(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_div(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(rem_basecase_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_rem_basecase(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(modulo, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_rem(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(div_root_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_div_root(to._poly(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_newton_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::fits_into_slong, fmpz_poly_inv_series_newton(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::fits_into_slong, fmpz_poly_inv_series(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(pseudo_rem_cohen_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_pseudo_rem_cohen(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_UNARY_EXPR_COND(derivative_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, fmpz_poly_derivative(to._poly(), from._poly())) FMPZ_POLYXX_DEFINE_MUL(compose) FMPZ_POLYXX_DEFINE_MUL(compose_horner) FMPZ_POLYXX_DEFINE_MUL(compose_divconquer) FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, fmpzxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_evaluate_fmpz(to._fmpz(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_divconquer_op, fmpzxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_evaluate_divconquer_fmpz(to._fmpz(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_horner_op, fmpzxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_evaluate_horner_fmpz(to._fmpz(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, fmpz_vecxx, FMPZ_POLYXX_COND_S, FMPZ_VECXX_COND_S, fmpz_poly_evaluate_fmpz_vec(to._data().array, e1._poly(), e2._data().array, e2.size())) FLINT_DEFINE_BINARY_EXPR_COND2(fmpz_polyxx_interpolate_op, fmpz_polyxx, FMPZ_VECXX_COND_S, FMPZ_VECXX_COND_S, fmpz_poly_interpolate_fmpz_vec(to._poly(), e1._data().array, e2._data().array, e2.size())) FLINT_DEFINE_BINARY_EXPR_COND2(taylor_shift_horner_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_taylor_shift_horner(to._poly(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(taylor_shift_divconquer_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_taylor_shift_divconquer(to._poly(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(taylor_shift_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_taylor_shift(to._poly(), e1._poly(), e2._fmpz())) FMPZ_POLYXX_DEFINE_SQRLOW(revert_series) FMPZ_POLYXX_DEFINE_SQRLOW(revert_series_newton) FMPZ_POLYXX_DEFINE_SQRLOW(revert_series_lagrange_fast) FMPZ_POLYXX_DEFINE_SQRLOW(revert_series_lagrange) FLINT_DEFINE_UNARY_EXPR_COND(sqrt_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, execution_check(fmpz_poly_sqrt(to._poly(), from._poly()), "sqrt", "fmpz_polyxx")) FLINT_DEFINE_UNARY_EXPR_COND(sqrt_classical_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, execution_check(fmpz_poly_sqrt_classical(to._poly(), from._poly()), "sqrt_classical", "fmpz_polyxx")) FLINT_DEFINE_UNARY_EXPR_COND(fmpz_polyxx_product_roots_op, fmpz_polyxx, FMPZ_VECXX_COND_S, fmpz_poly_product_roots_fmpz_vec(to._poly(), from._data().array, from.size())) FLINT_DEFINE_BINARY_EXPR_COND2(fmpz_polyxx_get_coeff_op, fmpzxx, FMPZ_POLYXX_COND_S, traits::is_integer, fmpz_poly_get_coeff_fmpz(to._fmpz(), e1._poly(), e2)) FLINT_DEFINE_UNARY_EXPR_COND(fmpz_polyxx_lead_op, fmpzxx, FMPZ_POLYXX_COND_S, fmpz_set(to._fmpz(), fmpz_poly_lead(from._poly()))) FLINT_DEFINE_UNARY_EXPR_COND(bound_roots_op, fmpzxx, FMPZ_POLYXX_COND_S, fmpz_poly_bound_roots(to._fmpz(), from._poly())) namespace rdetail { typedef make_ltuple::type>::type fmpz_polyxx_pair; typedef make_ltuple::type>::type fmpzxx_fmpz_polyxx_pair; } // rdetail #define FMPZ_POLYXX_DEFINE_DIVREM(name) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, rdetail::fmpz_polyxx_pair, \ FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, \ fmpz_poly_##name(to.template get<0>()._poly(), to.template get<1>()._poly(), \ e1._poly(), e2._poly())) FMPZ_POLYXX_DEFINE_DIVREM(divrem_basecase) FMPZ_POLYXX_DEFINE_DIVREM(divrem_divconquer) FMPZ_POLYXX_DEFINE_DIVREM(divrem) FMPZ_POLYXX_DEFINE_DIVREM(pseudo_divrem_cohen) #define FMPZ_POLYXX_DEFINE_MULFUNC(name) \ FLINT_DEFINE_THREEARY_EXPR_COND3(name##_op, fmpz_polyxx, \ FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, traits::fits_into_slong, \ fmpz_poly_##name(to._poly(), e1._poly(), e2._poly(), e3)) FMPZ_POLYXX_DEFINE_MULFUNC(mullow_classical) FMPZ_POLYXX_DEFINE_MULFUNC(mulhigh_classical) FMPZ_POLYXX_DEFINE_MULFUNC(mullow_karatsuba_n) FMPZ_POLYXX_DEFINE_MULFUNC(mulhigh_karatsuba_n) FMPZ_POLYXX_DEFINE_MULFUNC(mullow_KS) FMPZ_POLYXX_DEFINE_MULFUNC(mullow_SS) FMPZ_POLYXX_DEFINE_MULFUNC(mullow) FMPZ_POLYXX_DEFINE_MULFUNC(mulhigh_n) FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_op, rdetail::fmpzxx_fmpz_polyxx_pair, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_xgcd(to.template get<0>()._fmpz(), to.template get<1>()._poly(), to.template get<2>()._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_modular_op, rdetail::fmpzxx_fmpz_polyxx_pair, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_xgcd_modular(to.template get<0>()._fmpz(), to.template get<1>()._poly(), to.template get<2>()._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_THREEARY_EXPR_COND3(pow_trunc_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong, fmpz_poly_pow_trunc(to._poly(), e1._poly(), e2, e3)) #define FMPZ_POLYXX_DEFINE_SERIES(name) \ FLINT_DEFINE_THREEARY_EXPR_COND3(name##_op, fmpz_polyxx, \ FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, traits::fits_into_slong, \ fmpz_poly_##name(to._poly(), e1._poly(), e2._poly(), e3)) FMPZ_POLYXX_DEFINE_SERIES(div_series) FMPZ_POLYXX_DEFINE_SERIES(compose_series_brent_kung) FMPZ_POLYXX_DEFINE_SERIES(compose_series_horner) FMPZ_POLYXX_DEFINE_SERIES(compose_series) namespace rdetail { typedef make_ltuple::type>::type fmpz_polyxx_pair_ulong; typedef make_ltuple::type>::type fmpz_polyxx_ulong; typedef make_ltuple::type>::type bool_fmpz_polyxx; } #define FMPZ_POLYXX_DEFINE_PSEUDO_DIVREM(name) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, rdetail::fmpz_polyxx_pair_ulong, \ FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, \ fmpz_poly_##name(to.template get<0>()._poly(), to.template get<1>()._poly(), \ &to.template get<2>(), e1._poly(), e2._poly())) FMPZ_POLYXX_DEFINE_PSEUDO_DIVREM(pseudo_divrem_basecase) FMPZ_POLYXX_DEFINE_PSEUDO_DIVREM(pseudo_divrem_divconquer) FMPZ_POLYXX_DEFINE_PSEUDO_DIVREM(pseudo_divrem) FLINT_DEFINE_BINARY_EXPR_COND2(pseudo_div_op, rdetail::fmpz_polyxx_ulong, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_pseudo_div(to.template get<0>()._poly(), &to.template get<1>(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(pseudo_rem_op, rdetail::fmpz_polyxx_ulong, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_pseudo_rem(to.template get<0>()._poly(), &to.template get<1>(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(divides_op, rdetail::bool_fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, to.template get<0> () = fmpz_poly_divides(to.template get<1>()._poly(), e1._poly(), e2._poly())) namespace rdetail { typedef make_ltuple::type>::type fmpz_polyxx_quadruple; } FLINT_DEFINE_SEVENARY_EXPR_COND7(hensel_lift_op, rdetail::fmpz_polyxx_quadruple, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_poly_hensel_lift(to.template get<0>()._poly(), to.template get<1>()._poly(), to.template get<2>()._poly(), to.template get<3>()._poly(), e1._poly(), e2._poly(), e3._poly(), e4._poly(), e5._poly(), e6._fmpz(), e7._fmpz())) FLINT_DEFINE_SEVENARY_EXPR_COND7(hensel_lift_without_inverse_op, rdetail::fmpz_polyxx_pair, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_poly_hensel_lift_without_inverse(to.template get<0>()._poly(), to.template get<1>()._poly(), e1._poly(), e2._poly(), e3._poly(), e4._poly(), e5._poly(), e6._fmpz(), e7._fmpz())) FLINT_DEFINE_SIXARY_EXPR_COND6(hensel_lift_only_inverse_op, rdetail::fmpz_polyxx_pair, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_poly_hensel_lift_only_inverse(to.template get<0>()._poly(), to.template get<1>()._poly(), e1._poly(), e2._poly(), e3._poly(), e4._poly(), e5._fmpz(), e6._fmpz())) } // rules // immediate functions // TODO make lazy when we have nmod class template inline typename mp::enable_all_fmpz_polyxx::type evaluate_mod(const Poly& p, mp_limb_t x, mp_limb_t n) { return fmpz_poly_evaluate_mod(p.evaluate()._poly(), x, n); } template int read_pretty(Fmpz_poly& f, char** x, typename mp::enable_if >::type* = 0) { return f.read_pretty(x); } template int read_pretty(FILE* fi, Fmpz_poly& f, char** x, typename mp::enable_if >::type* = 0) { return f.read_pretty(x, fi); } } // flint #include "nmod_polyxx.h" // modular reconstruction code #include "fmpz_poly_factorxx.h" #endif