/*
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 FMPQ_POLYXX_H
#define FMPQ_POLYXX_H
#include
#include
#include "flint.h"
#include "fmpq_poly.h"
#include "fmpqxx.h"
#include "flintxx/expression.h"
#include "flintxx/flint_classes.h"
#include "flintxx/traits.h"
// TODO exhibit this as a specialisation of a generic poly
// TODO lazy version of numref?
namespace flint {
// function "declarations"
FLINT_DEFINE_BINOP(fmpq_polyxx_get_coeff)
FLINT_DEFINE_BINOP(fmpq_polyxx_interpolate)
FLINT_DEFINE_UNOP(fmpq_polyxx_den)
// TODO move to stdmath?
// TODO move to stdmath?
FLINT_DEFINE_BINOP(rescale)
namespace detail {
template
struct fmpq_poly_traits
{
typedef FLINT_UNOP_BUILD_RETTYPE(fmpq_polyxx_den, fmpzxx, Poly) coeff_ref_t;
typedef coeff_ref_t coeff_srcref_t;
static coeff_srcref_t den(const Poly& p) {return fmpq_polyxx_den(p);}
};
} // detail
template
class fmpq_polyxx_expression
: public expression,
Operation, Data>
{
public:
typedef expression,
Operation, Data> base_t;
typedef detail::fmpq_poly_traits poly_traits_t;
typedef typename poly_traits_t::coeff_ref_t coeff_ref_t;
typedef typename poly_traits_t::coeff_srcref_t coeff_srcref_t;
FLINTXX_DEFINE_BASICS(fmpq_polyxx_expression)
FLINTXX_DEFINE_CTORS(fmpq_polyxx_expression)
FLINTXX_DEFINE_C_REF(fmpq_polyxx_expression, fmpq_poly_struct, _poly)
// static methods which only make sense with fmpq_polyxx
static fmpq_polyxx_expression randtest(frandxx& state, slong len,
flint_bitcnt_t bits)
{
fmpq_polyxx_expression res;
fmpq_poly_randtest(res._poly(), state._data(), len, bits);
return res;
}
static fmpq_polyxx_expression randtest_unsigned(frandxx& state, slong len,
flint_bitcnt_t bits)
{
fmpq_polyxx_expression res;
fmpq_poly_randtest_unsigned(res._poly(), state._data(), len, bits);
return res;
}
static fmpq_polyxx_expression randtest_not_zero(frandxx& state, slong len,
flint_bitcnt_t bits)
{
fmpq_polyxx_expression res;
fmpq_poly_randtest_not_zero(res._poly(), state._data(), len, bits);
return res;
}
// TODO make lazy
// TODO perhaps as member function (non-static?)
template
static fmpq_polyxx_expression get_slice(const Poly& p, slong i, slong j)
{
fmpq_polyxx_expression res;
fmpq_poly_get_slice(res._poly(), p.evaluate()._poly(), i, j);
return res;
}
template
static FLINT_BINOP_ENABLE_RETTYPE(fmpq_polyxx_interpolate,
Fmpq_vec1, Fmpq_vec2)
interpolate(const Fmpq_vec1& xs, const Fmpq_vec2& ys)
{
return fmpq_polyxx_interpolate(xs, ys);
}
static fmpq_polyxx_expression zero() {return fmpq_polyxx_expression();}
static fmpq_polyxx_expression one()
{
fmpq_polyxx_expression res;
res.set_one();
return res;
}
// These only make sense with immediates
void realloc(slong alloc) {fmpq_poly_realloc(_poly(), alloc);}
void fit_length(slong len) {fmpq_poly_fit_length(_poly(), len);}
void _normalise() {_fmpq_poly_normalise(_poly());}
void _set_length(slong len) {_fmpq_poly_set_length(_poly(), len);}
void canonicalise() {fmpq_poly_canonicalise(_poly());}
bool is_canonical() const {return fmpq_poly_is_canonical(_poly());}
void set_zero() {fmpq_poly_zero(_poly());}
void set_one() {fmpq_poly_one(_poly());}
coeff_ref_t get_coeff_numref(slong n)
{
return coeff_ref_t::make(fmpq_poly_numref(_poly()) + n);
}
coeff_srcref_t get_coeff_numref(slong n) const
{
return coeff_srcref_t::make(fmpq_poly_numref(_poly()) + n);
}
coeff_ref_t den() {return poly_traits_t::den(*this);}
coeff_srcref_t den() const {return poly_traits_t::den(*this);}
// These only make sense with target immediates
template
typename mp::enable_if >::type
set_coeff(slong n, const Fmpz& x)
{
fmpq_poly_set_coeff_fmpz(_poly(), n, x.evaluate()._fmpz());
}
template
typename mp::enable_if >::type
set_coeff(slong n, const Fmpq& x)
{
fmpq_poly_set_coeff_fmpq(_poly(), n, x.evaluate()._fmpq());
}
template
typename mp::enable_if >::type
set_coeff(slong n, T x)
{
fmpq_poly_set_coeff_si(_poly(), n, x);
}
template
typename mp::enable_if >::type
set_coeff(slong n, T x)
{
fmpq_poly_set_coeff_ui(_poly(), n, x);
}
void truncate(slong n) {fmpq_poly_truncate(_poly(), n);}
// These cause evaluation
slong length() const {return fmpq_poly_length(this->evaluate()._poly());}
slong degree() const {return fmpq_poly_degree(this->evaluate()._poly());}
bool is_one() const {return fmpq_poly_is_one(this->evaluate()._poly());}
bool is_zero() const {return fmpq_poly_is_zero(this->evaluate()._poly());}
bool is_monic() const {return fmpq_poly_is_monic(this->evaluate()._poly());}
bool is_squarefree() const
{return fmpq_poly_is_squarefree(this->evaluate()._poly());}
std::string pretty(const char* x) const
{
char* str = fmpq_poly_get_str_pretty(this->evaluate()._poly(), x);
std::string res(str);
flint_free(str);
return res;
}
// lazy members
FLINTXX_DEFINE_MEMBER_BINOP_(operator(), compeval)
template // NB: template to instantiate lazily
FLINT_BINOP_ENABLE_RETTYPE(
fmpq_polyxx_get_coeff, fmpq_polyxx_expression, Slong)
get_coeff(const Slong& n) const
{
return fmpq_polyxx_get_coeff(*this, n);
}
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(mullow)
FLINTXX_DEFINE_MEMBER_BINOP(asinh_series)
FLINTXX_DEFINE_MEMBER_BINOP(asin_series)
FLINTXX_DEFINE_MEMBER_BINOP(atanh_series)
FLINTXX_DEFINE_MEMBER_BINOP(atan_series)
FLINTXX_DEFINE_MEMBER_BINOP(cosh_series)
FLINTXX_DEFINE_MEMBER_BINOP(cos_series)
FLINTXX_DEFINE_MEMBER_BINOP(divrem)
FLINTXX_DEFINE_MEMBER_BINOP(exp_series)
FLINTXX_DEFINE_MEMBER_BINOP(gcd)
FLINTXX_DEFINE_MEMBER_BINOP(inv_series)
FLINTXX_DEFINE_MEMBER_BINOP(inv_series_newton)
FLINTXX_DEFINE_MEMBER_BINOP(invsqrt_series)
FLINTXX_DEFINE_MEMBER_BINOP(lcm)
FLINTXX_DEFINE_MEMBER_BINOP(log_series)
FLINTXX_DEFINE_MEMBER_BINOP(pow)
FLINTXX_DEFINE_MEMBER_BINOP_(rescale, rescale)
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_(shift_left, shift_left)
FLINTXX_DEFINE_MEMBER_BINOP_(shift_right, shift_right)
FLINTXX_DEFINE_MEMBER_BINOP(sinh_series)
FLINTXX_DEFINE_MEMBER_BINOP(sin_series)
FLINTXX_DEFINE_MEMBER_BINOP(sqrt_series)
FLINTXX_DEFINE_MEMBER_BINOP(tanh_series)
FLINTXX_DEFINE_MEMBER_BINOP(tan_series)
FLINTXX_DEFINE_MEMBER_BINOP(xgcd)
FLINTXX_DEFINE_MEMBER_UNOP(derivative)
FLINTXX_DEFINE_MEMBER_UNOP(integral)
FLINTXX_DEFINE_MEMBER_UNOP(inv)
FLINTXX_DEFINE_MEMBER_UNOP(make_monic)
FLINTXX_DEFINE_MEMBER_UNOP(primitive_part)
FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpqxx, content)
};
namespace detail {
struct fmpq_poly_data;
}
typedef fmpq_polyxx_expression
fmpq_polyxx;
typedef fmpq_polyxx_expression >
fmpq_polyxx_ref;
typedef fmpq_polyxx_expression >
fmpq_polyxx_srcref;
namespace detail {
template<>
struct fmpq_poly_traits
{
typedef fmpzxx_srcref coeff_ref_t;
typedef fmpzxx_srcref coeff_srcref_t;
template static coeff_srcref_t den(const P& p)
{return coeff_srcref_t::make(fmpq_poly_denref(p._poly()));}
};
template<>
struct fmpq_poly_traits
{
typedef fmpzxx_ref coeff_ref_t;
typedef fmpzxx_ref coeff_srcref_t;
template
static coeff_ref_t den(P p)
{return coeff_ref_t::make(fmpq_poly_denref(p._poly()));}
};
template<>
struct fmpq_poly_traits
{
typedef fmpzxx_ref coeff_ref_t;
typedef fmpzxx_srcref coeff_srcref_t;
template
static coeff_ref_t den(P& p)
{return coeff_ref_t::make(fmpq_poly_denref(p._poly()));}
template
static coeff_srcref_t den(const P& p)
{return coeff_srcref_t::make(fmpq_poly_denref(p._poly()));}
};
struct fmpq_poly_data
{
fmpq_poly_t inner;
typedef fmpq_poly_t& data_ref_t;
typedef const fmpq_poly_t& data_srcref_t;
fmpq_poly_data() {fmpq_poly_init(inner);}
~fmpq_poly_data() {fmpq_poly_clear(inner);}
fmpq_poly_data(const fmpq_poly_data& o)
{
fmpq_poly_init(inner);
fmpq_poly_set(inner, o.inner);
}
fmpq_poly_data(fmpq_polyxx_srcref r)
{
fmpq_poly_init(inner);
fmpq_poly_set(inner, r._poly());
}
fmpq_poly_data(slong alloc)
{
fmpq_poly_init2(inner, alloc);
}
fmpq_poly_data(const char* str)
{
fmpq_poly_init(inner);
execution_check(!fmpq_poly_set_str(inner, str),
"construct from string", "fmpq_polyxx");
}
};
} // detail
namespace traits {
template struct is_fmpq_polyxx : mp::or_<
traits::is_T_expr,
flint_classes::is_source > { };
} // traits
namespace mp {
template
struct all_fmpq_polyxx : mp::and_, all_fmpq_polyxx > { };
template
struct all_fmpq_polyxx : traits::is_fmpq_polyxx { };
template
struct enable_all_fmpq_polyxx
: mp::enable_if, Out> { };
} // mp
} // flint
// here to deal with circular dependencies...
#include "fmpz_polyxx.h"
namespace flint {
namespace rules {
#define FMPQ_POLYXX_COND_S FLINTXX_COND_S(fmpq_polyxx)
#define FMPQ_POLYXX_COND_T FLINTXX_COND_T(fmpq_polyxx)
FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_POLYXX_COND_T, FMPQ_POLYXX_COND_S,
fmpq_poly_set(to._poly(), from._poly()))
FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_POLYXX_COND_T,
traits::is_signed_integer, fmpq_poly_set_si(to._poly(), from))
FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_POLYXX_COND_T,
traits::is_unsigned_integer, fmpq_poly_set_ui(to._poly(), from))
FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_POLYXX_COND_T, FMPZXX_COND_S,
fmpq_poly_set_fmpz(to._poly(), from._fmpz()))
FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_POLYXX_COND_T, FMPQXX_COND_S,
fmpq_poly_set_fmpq(to._poly(), from._fmpq()))
FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_POLYXX_COND_T, FMPZ_POLYXX_COND_S,
fmpq_poly_set_fmpz_poly(to._poly(), from._poly()))
FLINTXX_DEFINE_ASSIGN_STR(fmpq_polyxx, execution_check(
!fmpq_poly_set_str(to._poly(), from), "assign string", "fmpq_polyxx"))
FLINTXX_DEFINE_TO_STR(fmpq_polyxx, fmpq_poly_get_str(from._poly()))
FLINTXX_DEFINE_SWAP(fmpq_polyxx, fmpq_poly_swap(e1._poly(), e2._poly()))
FLINT_DEFINE_PRINT_COND(FMPQ_POLYXX_COND_S, fmpq_poly_fprint(to, from._poly()))
FLINT_DEFINE_PRINT_PRETTY_COND_2(FMPQ_POLYXX_COND_S, const char*,
fmpq_poly_fprint_pretty(to, from._poly(), extra))
FLINT_DEFINE_READ_COND(FMPQ_POLYXX_COND_T, fmpq_poly_fread(from, to._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(reverse_op, fmpq_polyxx,
FMPQ_POLYXX_COND_S, traits::fits_into_slong,
fmpq_poly_reverse(to._poly(), e1._poly(), e2))
FLINTXX_DEFINE_CMP(fmpq_polyxx, fmpq_poly_cmp(e1._poly(), e2._poly()))
FLINT_DEFINE_UNARY_EXPR_COND(negate, fmpq_polyxx, FMPQ_POLYXX_COND_S,
fmpq_poly_neg(to._poly(), from._poly()))
FLINT_DEFINE_UNARY_EXPR_COND(inv_op, fmpq_polyxx, FMPQ_POLYXX_COND_S,
fmpq_poly_inv(to._poly(), from._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(fmpq_polyxx_get_coeff_op, fmpqxx,
FMPQ_POLYXX_COND_S, traits::fits_into_slong,
fmpq_poly_get_coeff_fmpq(to._fmpq(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(plus, fmpq_polyxx,
FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
fmpq_poly_add(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpq_polyxx,
FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
fmpq_poly_sub(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpq_polyxx,
FMPQ_POLYXX_COND_S, FMPZXX_COND_S,
fmpq_poly_scalar_mul_fmpz(to._poly(), e1._poly(), e2._fmpz()))
FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpq_polyxx,
FMPQ_POLYXX_COND_S, FMPQXX_COND_S,
fmpq_poly_scalar_mul_fmpq(to._poly(), e1._poly(), e2._fmpq()))
FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpq_polyxx,
FMPQ_POLYXX_COND_S, traits::is_signed_integer,
fmpq_poly_scalar_mul_si(to._poly(), e1._poly(), e2))
FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpq_polyxx,
FMPQ_POLYXX_COND_S, traits::is_unsigned_integer,
fmpq_poly_scalar_mul_ui(to._poly(), e1._poly(), e2))
FLINT_DEFINE_CBINARY_EXPR_COND2(divided_by, fmpq_polyxx,
FMPQ_POLYXX_COND_S, FMPQXX_COND_S,
fmpq_poly_scalar_div_fmpq(to._poly(), e1._poly(), e2._fmpq()))
FLINT_DEFINE_CBINARY_EXPR_COND2(divided_by, fmpq_polyxx,
FMPQ_POLYXX_COND_S, FMPZXX_COND_S,
fmpq_poly_scalar_div_fmpz(to._poly(), e1._poly(), e2._fmpz()))
FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpq_polyxx,
FMPQ_POLYXX_COND_S, traits::is_unsigned_integer,
fmpq_poly_scalar_div_ui(to._poly(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpq_polyxx,
FMPQ_POLYXX_COND_S, traits::is_signed_integer,
fmpq_poly_scalar_div_si(to._poly(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpq_polyxx,
FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
fmpq_poly_mul(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, fmpq_polyxx,
FMPQ_POLYXX_COND_S, traits::is_unsigned_integer,
fmpq_poly_pow(to._poly(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(shift_left_op, fmpq_polyxx,
FMPQ_POLYXX_COND_S, traits::fits_into_slong,
fmpq_poly_shift_left(to._poly(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(shift_right_op, fmpq_polyxx,
FMPQ_POLYXX_COND_S, traits::fits_into_slong,
fmpq_poly_shift_right(to._poly(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpq_polyxx,
FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
fmpq_poly_div(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(modulo, fmpq_polyxx,
FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
fmpq_poly_rem(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_newton_op, fmpq_polyxx,
FMPQ_POLYXX_COND_S, traits::fits_into_slong,
fmpq_poly_inv_series_newton(to._poly(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_op, fmpq_polyxx,
FMPQ_POLYXX_COND_S, traits::fits_into_slong,
fmpq_poly_inv_series(to._poly(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(gcd_op, fmpq_polyxx,
FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
fmpq_poly_gcd(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(lcm_op, fmpq_polyxx,
FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
fmpq_poly_lcm(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(resultant_op, fmpqxx,
FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
fmpq_poly_resultant(to._fmpq(), e1._poly(), e2._poly()))
FLINT_DEFINE_UNARY_EXPR_COND(derivative_op, fmpq_polyxx, FMPQ_POLYXX_COND_S,
fmpq_poly_derivative(to._poly(), from._poly()))
FLINT_DEFINE_UNARY_EXPR_COND(integral_op, fmpq_polyxx, FMPQ_POLYXX_COND_S,
fmpq_poly_integral(to._poly(), from._poly()))
#define FMPQ_POLYXX_DEFINE_SERIES(name) \
FLINT_DEFINE_BINARY_EXPR_COND2(name##_series_op, fmpq_polyxx, \
FMPQ_POLYXX_COND_S, traits::fits_into_slong, \
fmpq_poly_##name##_series(to._poly(), e1._poly(), e2))
FMPQ_POLYXX_DEFINE_SERIES(sqrt)
FMPQ_POLYXX_DEFINE_SERIES(invsqrt)
FMPQ_POLYXX_DEFINE_SERIES(exp)
FMPQ_POLYXX_DEFINE_SERIES(log)
FMPQ_POLYXX_DEFINE_SERIES(atan)
FMPQ_POLYXX_DEFINE_SERIES(atanh)
FMPQ_POLYXX_DEFINE_SERIES(asin)
FMPQ_POLYXX_DEFINE_SERIES(asinh)
FMPQ_POLYXX_DEFINE_SERIES(tan)
FMPQ_POLYXX_DEFINE_SERIES(sin)
FMPQ_POLYXX_DEFINE_SERIES(cos)
FMPQ_POLYXX_DEFINE_SERIES(sinh)
FMPQ_POLYXX_DEFINE_SERIES(cosh)
FMPQ_POLYXX_DEFINE_SERIES(tanh)
FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, fmpqxx,
FMPQ_POLYXX_COND_S, FMPQXX_COND_S,
fmpq_poly_evaluate_fmpq(to._fmpq(), e1._poly(), e2._fmpq()))
FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, fmpqxx,
FMPQ_POLYXX_COND_S, FMPZXX_COND_S,
fmpq_poly_evaluate_fmpz(to._fmpq(), e1._poly(), e2._fmpz()))
FLINT_DEFINE_BINARY_EXPR_COND2(compose_op, fmpq_polyxx,
FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
fmpq_poly_compose(to._poly(), e1._poly(), e2._poly()))
FLINT_DEFINE_BINARY_EXPR_COND2(fmpq_polyxx_interpolate_op, fmpq_polyxx,
FMPZ_VECXX_COND_S, FMPZ_VECXX_COND_S,
fmpq_poly_interpolate_fmpz_vec(to._poly(), e1._data().array,
e2._data().array, e2.size()))
FLINT_DEFINE_BINARY_EXPR_COND2(rescale_op, fmpq_polyxx,
FMPQ_POLYXX_COND_S, FMPQXX_COND_S,
fmpq_poly_rescale(to._poly(), e1._poly(), e2._fmpq()))
FLINT_DEFINE_BINARY_EXPR_COND2(revert_series_op, fmpq_polyxx,
FMPQ_POLYXX_COND_S, traits::fits_into_slong,
fmpq_poly_revert_series(to._poly(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(revert_series_lagrange_op, fmpq_polyxx,
FMPQ_POLYXX_COND_S, traits::fits_into_slong,
fmpq_poly_revert_series_lagrange(to._poly(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(revert_series_lagrange_fast_op, fmpq_polyxx,
FMPQ_POLYXX_COND_S, traits::fits_into_slong,
fmpq_poly_revert_series_lagrange_fast(to._poly(), e1._poly(), e2))
FLINT_DEFINE_BINARY_EXPR_COND2(revert_series_newton_op, fmpq_polyxx,
FMPQ_POLYXX_COND_S, traits::fits_into_slong,
fmpq_poly_revert_series_newton(to._poly(), e1._poly(), e2))
FLINT_DEFINE_UNARY_EXPR_COND(content_op, fmpqxx, FMPQ_POLYXX_COND_S,
fmpq_poly_content(to._fmpq(), from._poly()))
FLINT_DEFINE_UNARY_EXPR_COND(primitive_part_op, fmpq_polyxx, FMPQ_POLYXX_COND_S,
fmpq_poly_primitive_part(to._poly(), from._poly()))
FLINT_DEFINE_UNARY_EXPR_COND(make_monic_op, fmpq_polyxx, FMPQ_POLYXX_COND_S,
fmpq_poly_make_monic(to._poly(), from._poly()))
FLINT_DEFINE_UNARY_EXPR_COND(fmpq_polyxx_den_op, fmpzxx, FMPQ_POLYXX_COND_S,
fmpz_set(to._fmpz(), fmpq_poly_denref(from._poly())))
namespace rdetail {
typedef make_ltuple::type>::type fmpq_polyxx_triple;
typedef make_ltuple::type>::type fmpq_polyxx_pair;
} // rdetail
FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_op, rdetail::fmpq_polyxx_triple,
FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
fmpq_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(divrem_op, rdetail::fmpq_polyxx_pair,
FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
fmpq_poly_divrem(to.template get<0>()._poly(), to.template get<1>()._poly(),
e1._poly(), e2._poly()))
#define FMPQ_POLYXX_DEFINE_SERIES_FUNC(name) \
FLINT_DEFINE_THREEARY_EXPR_COND3(name##_op, fmpq_polyxx, \
FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S, traits::fits_into_slong, \
fmpq_poly_##name(to._poly(), e1._poly(), e2._poly(), e3))
FMPQ_POLYXX_DEFINE_SERIES_FUNC(mullow)
FMPQ_POLYXX_DEFINE_SERIES_FUNC(div_series)
FMPQ_POLYXX_DEFINE_SERIES_FUNC(compose_series)
FMPQ_POLYXX_DEFINE_SERIES_FUNC(compose_series_brent_kung)
FMPQ_POLYXX_DEFINE_SERIES_FUNC(compose_series_horner)
} // rules
// NB: fmpq_poly addmul is just done by hand currently, no need to wrap that ..
} // flint
#endif