1 /*
2     Copyright (C) 2013 Tom Bachmann
3 
4     This file is part of FLINT.
5 
6     FLINT is free software: you can redistribute it and/or modify it under
7     the terms of the GNU Lesser General Public License (LGPL) as published
8     by the Free Software Foundation; either version 2.1 of the License, or
9     (at your option) any later version.  See <http://www.gnu.org/licenses/>.
10 */
11 
12 #ifndef FMPQ_POLYXX_H
13 #define FMPQ_POLYXX_H
14 
15 #include <cstdlib>
16 #include <string>
17 
18 #include "flint.h"
19 #include "fmpq_poly.h"
20 
21 #include "fmpqxx.h"
22 
23 #include "flintxx/expression.h"
24 #include "flintxx/flint_classes.h"
25 #include "flintxx/traits.h"
26 
27 // TODO exhibit this as a specialisation of a generic poly<fmpzxx>
28 // TODO lazy version of numref?
29 
30 namespace flint {
31 // function "declarations"
32 FLINT_DEFINE_BINOP(fmpq_polyxx_get_coeff)
FLINT_DEFINE_BINOP(fmpq_polyxx_interpolate)33 FLINT_DEFINE_BINOP(fmpq_polyxx_interpolate)
34 FLINT_DEFINE_UNOP(fmpq_polyxx_den)
35 
36 // TODO move to stdmath?
37 
38 // TODO move to stdmath?
39 FLINT_DEFINE_BINOP(rescale)
40 
41 namespace detail {
42 template<class Poly>
43 struct fmpq_poly_traits
44 {
45     typedef FLINT_UNOP_BUILD_RETTYPE(fmpq_polyxx_den, fmpzxx, Poly) coeff_ref_t;
46     typedef coeff_ref_t coeff_srcref_t;
47 
48     static coeff_srcref_t den(const Poly& p) {return fmpq_polyxx_den(p);}
49 };
50 } // detail
51 
52 template<class Operation, class Data>
53 class fmpq_polyxx_expression
54     : public expression<derived_wrapper<fmpq_polyxx_expression>,
55                             Operation, Data>
56 {
57 public:
58     typedef expression<derived_wrapper< ::flint::fmpq_polyxx_expression>,
59               Operation, Data> base_t;
60     typedef detail::fmpq_poly_traits<fmpq_polyxx_expression> poly_traits_t;
61     typedef typename poly_traits_t::coeff_ref_t coeff_ref_t;
62     typedef typename poly_traits_t::coeff_srcref_t coeff_srcref_t;
63 
64     FLINTXX_DEFINE_BASICS(fmpq_polyxx_expression)
FLINTXX_DEFINE_CTORS(fmpq_polyxx_expression)65     FLINTXX_DEFINE_CTORS(fmpq_polyxx_expression)
66     FLINTXX_DEFINE_C_REF(fmpq_polyxx_expression, fmpq_poly_struct, _poly)
67 
68     // static methods which only make sense with fmpq_polyxx
69     static fmpq_polyxx_expression randtest(frandxx& state, slong len,
70             flint_bitcnt_t bits)
71     {
72         fmpq_polyxx_expression res;
73         fmpq_poly_randtest(res._poly(), state._data(), len, bits);
74         return res;
75     }
randtest_unsigned(frandxx & state,slong len,flint_bitcnt_t bits)76     static fmpq_polyxx_expression randtest_unsigned(frandxx& state, slong len,
77             flint_bitcnt_t bits)
78     {
79         fmpq_polyxx_expression res;
80         fmpq_poly_randtest_unsigned(res._poly(), state._data(), len, bits);
81         return res;
82     }
randtest_not_zero(frandxx & state,slong len,flint_bitcnt_t bits)83     static fmpq_polyxx_expression randtest_not_zero(frandxx& state, slong len,
84             flint_bitcnt_t bits)
85     {
86         fmpq_polyxx_expression res;
87         fmpq_poly_randtest_not_zero(res._poly(), state._data(), len, bits);
88         return res;
89     }
90 
91     // TODO make lazy
92     // TODO perhaps as member function (non-static?)
93     template<class Poly>
get_slice(const Poly & p,slong i,slong j)94     static fmpq_polyxx_expression get_slice(const Poly& p, slong i, slong j)
95     {
96         fmpq_polyxx_expression res;
97         fmpq_poly_get_slice(res._poly(), p.evaluate()._poly(), i, j);
98         return res;
99     }
100 
101     template<class Fmpq_vec1, class Fmpq_vec2>
FLINT_BINOP_ENABLE_RETTYPE(fmpq_polyxx_interpolate,Fmpq_vec1,Fmpq_vec2)102     static FLINT_BINOP_ENABLE_RETTYPE(fmpq_polyxx_interpolate,
103         Fmpq_vec1, Fmpq_vec2)
104     interpolate(const Fmpq_vec1& xs, const Fmpq_vec2& ys)
105     {
106         return fmpq_polyxx_interpolate(xs, ys);
107     }
108 
zero()109     static fmpq_polyxx_expression zero() {return fmpq_polyxx_expression();}
one()110     static fmpq_polyxx_expression one()
111     {
112         fmpq_polyxx_expression res;
113         res.set_one();
114         return res;
115     }
116 
117     // These only make sense with immediates
realloc(slong alloc)118     void realloc(slong alloc) {fmpq_poly_realloc(_poly(), alloc);}
fit_length(slong len)119     void fit_length(slong len) {fmpq_poly_fit_length(_poly(), len);}
_normalise()120     void _normalise() {_fmpq_poly_normalise(_poly());}
_set_length(slong len)121     void _set_length(slong len) {_fmpq_poly_set_length(_poly(), len);}
canonicalise()122     void canonicalise() {fmpq_poly_canonicalise(_poly());}
is_canonical()123     bool is_canonical() const {return fmpq_poly_is_canonical(_poly());}
set_zero()124     void set_zero() {fmpq_poly_zero(_poly());}
set_one()125     void set_one() {fmpq_poly_one(_poly());}
126 
get_coeff_numref(slong n)127     coeff_ref_t get_coeff_numref(slong n)
128     {
129         return coeff_ref_t::make(fmpq_poly_numref(_poly()) + n);
130     }
get_coeff_numref(slong n)131     coeff_srcref_t get_coeff_numref(slong n) const
132     {
133         return coeff_srcref_t::make(fmpq_poly_numref(_poly()) + n);
134     }
den()135     coeff_ref_t den() {return poly_traits_t::den(*this);}
den()136     coeff_srcref_t den() const {return poly_traits_t::den(*this);}
137 
138     // These only make sense with target immediates
139     template<class Fmpz>
140     typename mp::enable_if<traits::is_fmpzxx<Fmpz> >::type
set_coeff(slong n,const Fmpz & x)141     set_coeff(slong n, const Fmpz& x)
142     {
143         fmpq_poly_set_coeff_fmpz(_poly(), n, x.evaluate()._fmpz());
144     }
145     template<class Fmpq>
146     typename mp::enable_if<traits::is_fmpqxx<Fmpq> >::type
set_coeff(slong n,const Fmpq & x)147     set_coeff(slong n, const Fmpq& x)
148     {
149         fmpq_poly_set_coeff_fmpq(_poly(), n, x.evaluate()._fmpq());
150     }
151     template<class T>
152     typename mp::enable_if<traits::is_signed_integer<T> >::type
set_coeff(slong n,T x)153     set_coeff(slong n, T x)
154     {
155         fmpq_poly_set_coeff_si(_poly(), n, x);
156     }
157     template<class T>
158     typename mp::enable_if<traits::is_unsigned_integer<T> >::type
set_coeff(slong n,T x)159     set_coeff(slong n, T x)
160     {
161         fmpq_poly_set_coeff_ui(_poly(), n, x);
162     }
163 
truncate(slong n)164     void truncate(slong n) {fmpq_poly_truncate(_poly(), n);}
165 
166     // These cause evaluation
length()167     slong length() const {return fmpq_poly_length(this->evaluate()._poly());}
degree()168     slong degree() const {return fmpq_poly_degree(this->evaluate()._poly());}
is_one()169     bool is_one() const {return fmpq_poly_is_one(this->evaluate()._poly());}
is_zero()170     bool is_zero() const {return fmpq_poly_is_zero(this->evaluate()._poly());}
is_monic()171     bool is_monic() const {return fmpq_poly_is_monic(this->evaluate()._poly());}
is_squarefree()172     bool is_squarefree() const
173         {return fmpq_poly_is_squarefree(this->evaluate()._poly());}
174 
pretty(const char * x)175     std::string pretty(const char* x) const
176     {
177         char* str = fmpq_poly_get_str_pretty(this->evaluate()._poly(), x);
178         std::string res(str);
179         flint_free(str);
180         return res;
181     }
182 
183     // lazy members
FLINTXX_DEFINE_MEMBER_BINOP_(operator (),compeval)184     FLINTXX_DEFINE_MEMBER_BINOP_(operator(), compeval)
185 
186     template<class Slong> // NB: template to instantiate lazily
187     FLINT_BINOP_ENABLE_RETTYPE(
188             fmpq_polyxx_get_coeff, fmpq_polyxx_expression, Slong)
189     get_coeff(const Slong& n) const
190     {
191         return fmpq_polyxx_get_coeff(*this, n);
192     }
193 
194     FLINTXX_DEFINE_MEMBER_3OP(compose_series)
195     FLINTXX_DEFINE_MEMBER_3OP(compose_series_brent_kung)
196     FLINTXX_DEFINE_MEMBER_3OP(compose_series_horner)
197     FLINTXX_DEFINE_MEMBER_3OP(div_series)
198     FLINTXX_DEFINE_MEMBER_3OP(mullow)
199     FLINTXX_DEFINE_MEMBER_BINOP(asinh_series)
200     FLINTXX_DEFINE_MEMBER_BINOP(asin_series)
201     FLINTXX_DEFINE_MEMBER_BINOP(atanh_series)
202     FLINTXX_DEFINE_MEMBER_BINOP(atan_series)
203     FLINTXX_DEFINE_MEMBER_BINOP(cosh_series)
204     FLINTXX_DEFINE_MEMBER_BINOP(cos_series)
205     FLINTXX_DEFINE_MEMBER_BINOP(divrem)
206     FLINTXX_DEFINE_MEMBER_BINOP(exp_series)
207     FLINTXX_DEFINE_MEMBER_BINOP(gcd)
208     FLINTXX_DEFINE_MEMBER_BINOP(inv_series)
209     FLINTXX_DEFINE_MEMBER_BINOP(inv_series_newton)
210     FLINTXX_DEFINE_MEMBER_BINOP(invsqrt_series)
211     FLINTXX_DEFINE_MEMBER_BINOP(lcm)
212     FLINTXX_DEFINE_MEMBER_BINOP(log_series)
213     FLINTXX_DEFINE_MEMBER_BINOP(pow)
214     FLINTXX_DEFINE_MEMBER_BINOP_(rescale, rescale)
215     FLINTXX_DEFINE_MEMBER_BINOP(resultant)
216     FLINTXX_DEFINE_MEMBER_BINOP(reverse)
217     FLINTXX_DEFINE_MEMBER_BINOP(revert_series)
218     FLINTXX_DEFINE_MEMBER_BINOP(revert_series_lagrange)
219     FLINTXX_DEFINE_MEMBER_BINOP(revert_series_lagrange_fast)
220     FLINTXX_DEFINE_MEMBER_BINOP(revert_series_newton)
221     FLINTXX_DEFINE_MEMBER_BINOP_(shift_left, shift_left)
222     FLINTXX_DEFINE_MEMBER_BINOP_(shift_right, shift_right)
223     FLINTXX_DEFINE_MEMBER_BINOP(sinh_series)
224     FLINTXX_DEFINE_MEMBER_BINOP(sin_series)
225     FLINTXX_DEFINE_MEMBER_BINOP(sqrt_series)
226     FLINTXX_DEFINE_MEMBER_BINOP(tanh_series)
227     FLINTXX_DEFINE_MEMBER_BINOP(tan_series)
228     FLINTXX_DEFINE_MEMBER_BINOP(xgcd)
229     FLINTXX_DEFINE_MEMBER_UNOP(derivative)
230     FLINTXX_DEFINE_MEMBER_UNOP(integral)
231     FLINTXX_DEFINE_MEMBER_UNOP(inv)
232     FLINTXX_DEFINE_MEMBER_UNOP(make_monic)
233     FLINTXX_DEFINE_MEMBER_UNOP(primitive_part)
234     FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpqxx, content)
235 };
236 
237 namespace detail {
238 struct fmpq_poly_data;
239 }
240 
241 typedef fmpq_polyxx_expression<operations::immediate, detail::fmpq_poly_data>
242            fmpq_polyxx;
243 typedef fmpq_polyxx_expression<operations::immediate,
244             flint_classes::ref_data<fmpq_polyxx, fmpq_poly_struct> >
245            fmpq_polyxx_ref;
246 typedef fmpq_polyxx_expression<operations::immediate,
247             flint_classes::srcref_data<
248                 fmpq_polyxx, fmpq_polyxx_ref, fmpq_poly_struct> >
249            fmpq_polyxx_srcref;
250 
251 namespace detail {
252 template<>
253 struct fmpq_poly_traits<fmpq_polyxx_srcref>
254 {
255     typedef fmpzxx_srcref coeff_ref_t;
256     typedef fmpzxx_srcref coeff_srcref_t;
257     template<class P> static coeff_srcref_t den(const P& p)
258         {return coeff_srcref_t::make(fmpq_poly_denref(p._poly()));}
259 };
260 template<>
261 struct fmpq_poly_traits<fmpq_polyxx_ref>
262 {
263     typedef fmpzxx_ref coeff_ref_t;
264     typedef fmpzxx_ref coeff_srcref_t;
265     template<class P>
266     static coeff_ref_t den(P p)
267         {return coeff_ref_t::make(fmpq_poly_denref(p._poly()));}
268 };
269 template<>
270 struct fmpq_poly_traits<fmpq_polyxx>
271 {
272     typedef fmpzxx_ref coeff_ref_t;
273     typedef fmpzxx_srcref coeff_srcref_t;
274     template<class P>
275     static coeff_ref_t den(P& p)
276         {return coeff_ref_t::make(fmpq_poly_denref(p._poly()));}
277     template<class P>
278     static coeff_srcref_t den(const P& p)
279         {return coeff_srcref_t::make(fmpq_poly_denref(p._poly()));}
280 };
281 
282 struct fmpq_poly_data
283 {
284     fmpq_poly_t inner;
285     typedef fmpq_poly_t& data_ref_t;
286     typedef const fmpq_poly_t& data_srcref_t;
287 
288     fmpq_poly_data() {fmpq_poly_init(inner);}
289     ~fmpq_poly_data() {fmpq_poly_clear(inner);}
290 
291     fmpq_poly_data(const fmpq_poly_data& o)
292     {
293         fmpq_poly_init(inner);
294         fmpq_poly_set(inner, o.inner);
295     }
296 
297     fmpq_poly_data(fmpq_polyxx_srcref r)
298     {
299         fmpq_poly_init(inner);
300         fmpq_poly_set(inner, r._poly());
301     }
302 
303     fmpq_poly_data(slong alloc)
304     {
305         fmpq_poly_init2(inner, alloc);
306     }
307 
308     fmpq_poly_data(const char* str)
309     {
310         fmpq_poly_init(inner);
311         execution_check(!fmpq_poly_set_str(inner, str),
312                 "construct from string", "fmpq_polyxx");
313     }
314 };
315 } // detail
316 
317 namespace traits {
318 template<class T> struct is_fmpq_polyxx : mp::or_<
319      traits::is_T_expr<T, fmpq_polyxx>,
320      flint_classes::is_source<fmpq_polyxx, T> > { };
321 } // traits
322 namespace mp {
323 template<class T1, class T2 = void, class T3 = void, class T4 = void>
324 struct all_fmpq_polyxx : mp::and_<all_fmpq_polyxx<T1>, all_fmpq_polyxx<T2, T3, T4> > { };
325 template<class T>
326 struct all_fmpq_polyxx<T, void, void, void> : traits::is_fmpq_polyxx<T> { };
327 
328 template<class Out, class T1, class T2 = void, class T3 = void, class T4 = void>
329 struct enable_all_fmpq_polyxx
330     : mp::enable_if<all_fmpq_polyxx<T1, T2, T3, T4>, Out> { };
331 } // mp
332 } // flint
333 
334 // here to deal with circular dependencies...
335 #include "fmpz_polyxx.h"
336 
337 namespace flint {
338 namespace rules {
339 #define FMPQ_POLYXX_COND_S FLINTXX_COND_S(fmpq_polyxx)
340 #define FMPQ_POLYXX_COND_T FLINTXX_COND_T(fmpq_polyxx)
341 
342 FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_POLYXX_COND_T, FMPQ_POLYXX_COND_S,
343         fmpq_poly_set(to._poly(), from._poly()))
344 FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_POLYXX_COND_T,
345         traits::is_signed_integer, fmpq_poly_set_si(to._poly(), from))
346 FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_POLYXX_COND_T,
347         traits::is_unsigned_integer, fmpq_poly_set_ui(to._poly(), from))
348 FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_POLYXX_COND_T, FMPZXX_COND_S,
349         fmpq_poly_set_fmpz(to._poly(), from._fmpz()))
350 FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_POLYXX_COND_T, FMPQXX_COND_S,
351         fmpq_poly_set_fmpq(to._poly(), from._fmpq()))
352 FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_POLYXX_COND_T, FMPZ_POLYXX_COND_S,
353         fmpq_poly_set_fmpz_poly(to._poly(), from._poly()))
354 
355 FLINTXX_DEFINE_ASSIGN_STR(fmpq_polyxx, execution_check(
356             !fmpq_poly_set_str(to._poly(), from), "assign string", "fmpq_polyxx"))
357 
358 FLINTXX_DEFINE_TO_STR(fmpq_polyxx, fmpq_poly_get_str(from._poly()))
359 FLINTXX_DEFINE_SWAP(fmpq_polyxx, fmpq_poly_swap(e1._poly(), e2._poly()))
360 
361 FLINT_DEFINE_PRINT_COND(FMPQ_POLYXX_COND_S, fmpq_poly_fprint(to, from._poly()))
362 FLINT_DEFINE_PRINT_PRETTY_COND_2(FMPQ_POLYXX_COND_S, const char*,
363         fmpq_poly_fprint_pretty(to, from._poly(), extra))
364 FLINT_DEFINE_READ_COND(FMPQ_POLYXX_COND_T, fmpq_poly_fread(from, to._poly()))
365 
366 FLINT_DEFINE_BINARY_EXPR_COND2(reverse_op, fmpq_polyxx,
367         FMPQ_POLYXX_COND_S, traits::fits_into_slong,
368         fmpq_poly_reverse(to._poly(), e1._poly(), e2))
369 
370 FLINTXX_DEFINE_CMP(fmpq_polyxx, fmpq_poly_cmp(e1._poly(), e2._poly()))
371 
372 FLINT_DEFINE_UNARY_EXPR_COND(negate, fmpq_polyxx, FMPQ_POLYXX_COND_S,
373         fmpq_poly_neg(to._poly(), from._poly()))
374 FLINT_DEFINE_UNARY_EXPR_COND(inv_op, fmpq_polyxx, FMPQ_POLYXX_COND_S,
375         fmpq_poly_inv(to._poly(), from._poly()))
376 
377 FLINT_DEFINE_BINARY_EXPR_COND2(fmpq_polyxx_get_coeff_op, fmpqxx,
378         FMPQ_POLYXX_COND_S, traits::fits_into_slong,
379         fmpq_poly_get_coeff_fmpq(to._fmpq(), e1._poly(), e2))
380 
381 FLINT_DEFINE_BINARY_EXPR_COND2(plus, fmpq_polyxx,
382         FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
383         fmpq_poly_add(to._poly(), e1._poly(), e2._poly()))
384 FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpq_polyxx,
385         FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
386         fmpq_poly_sub(to._poly(), e1._poly(), e2._poly()))
387 
388 FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpq_polyxx,
389         FMPQ_POLYXX_COND_S, FMPZXX_COND_S,
390         fmpq_poly_scalar_mul_fmpz(to._poly(), e1._poly(), e2._fmpz()))
391 FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpq_polyxx,
392         FMPQ_POLYXX_COND_S, FMPQXX_COND_S,
393         fmpq_poly_scalar_mul_fmpq(to._poly(), e1._poly(), e2._fmpq()))
394 FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpq_polyxx,
395         FMPQ_POLYXX_COND_S, traits::is_signed_integer,
396         fmpq_poly_scalar_mul_si(to._poly(), e1._poly(), e2))
397 FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpq_polyxx,
398         FMPQ_POLYXX_COND_S, traits::is_unsigned_integer,
399         fmpq_poly_scalar_mul_ui(to._poly(), e1._poly(), e2))
400 
401 FLINT_DEFINE_CBINARY_EXPR_COND2(divided_by, fmpq_polyxx,
402         FMPQ_POLYXX_COND_S, FMPQXX_COND_S,
403         fmpq_poly_scalar_div_fmpq(to._poly(), e1._poly(), e2._fmpq()))
404 FLINT_DEFINE_CBINARY_EXPR_COND2(divided_by, fmpq_polyxx,
405         FMPQ_POLYXX_COND_S, FMPZXX_COND_S,
406         fmpq_poly_scalar_div_fmpz(to._poly(), e1._poly(), e2._fmpz()))
407 FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpq_polyxx,
408         FMPQ_POLYXX_COND_S, traits::is_unsigned_integer,
409         fmpq_poly_scalar_div_ui(to._poly(), e1._poly(), e2))
410 FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpq_polyxx,
411         FMPQ_POLYXX_COND_S, traits::is_signed_integer,
412         fmpq_poly_scalar_div_si(to._poly(), e1._poly(), e2))
413 
414 FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpq_polyxx,
415         FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
416         fmpq_poly_mul(to._poly(), e1._poly(), e2._poly()))
417 
418 FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, fmpq_polyxx,
419         FMPQ_POLYXX_COND_S, traits::is_unsigned_integer,
420         fmpq_poly_pow(to._poly(), e1._poly(), e2))
421 
422 FLINT_DEFINE_BINARY_EXPR_COND2(shift_left_op, fmpq_polyxx,
423         FMPQ_POLYXX_COND_S, traits::fits_into_slong,
424         fmpq_poly_shift_left(to._poly(), e1._poly(), e2))
425 FLINT_DEFINE_BINARY_EXPR_COND2(shift_right_op, fmpq_polyxx,
426         FMPQ_POLYXX_COND_S, traits::fits_into_slong,
427         fmpq_poly_shift_right(to._poly(), e1._poly(), e2))
428 
429 FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpq_polyxx,
430         FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
431         fmpq_poly_div(to._poly(), e1._poly(), e2._poly()))
432 FLINT_DEFINE_BINARY_EXPR_COND2(modulo, fmpq_polyxx,
433         FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
434         fmpq_poly_rem(to._poly(), e1._poly(), e2._poly()))
435 
436 FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_newton_op, fmpq_polyxx,
437         FMPQ_POLYXX_COND_S, traits::fits_into_slong,
438         fmpq_poly_inv_series_newton(to._poly(), e1._poly(), e2))
439 FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_op, fmpq_polyxx,
440         FMPQ_POLYXX_COND_S, traits::fits_into_slong,
441         fmpq_poly_inv_series(to._poly(), e1._poly(), e2))
442 
443 FLINT_DEFINE_BINARY_EXPR_COND2(gcd_op, fmpq_polyxx,
444         FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
445         fmpq_poly_gcd(to._poly(), e1._poly(), e2._poly()))
446 FLINT_DEFINE_BINARY_EXPR_COND2(lcm_op, fmpq_polyxx,
447         FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
448         fmpq_poly_lcm(to._poly(), e1._poly(), e2._poly()))
449 FLINT_DEFINE_BINARY_EXPR_COND2(resultant_op, fmpqxx,
450         FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
451         fmpq_poly_resultant(to._fmpq(), e1._poly(), e2._poly()))
452 
453 FLINT_DEFINE_UNARY_EXPR_COND(derivative_op, fmpq_polyxx, FMPQ_POLYXX_COND_S,
454         fmpq_poly_derivative(to._poly(), from._poly()))
455 FLINT_DEFINE_UNARY_EXPR_COND(integral_op, fmpq_polyxx, FMPQ_POLYXX_COND_S,
456         fmpq_poly_integral(to._poly(), from._poly()))
457 
458 #define FMPQ_POLYXX_DEFINE_SERIES(name) \
459 FLINT_DEFINE_BINARY_EXPR_COND2(name##_series_op, fmpq_polyxx, \
460         FMPQ_POLYXX_COND_S, traits::fits_into_slong, \
461         fmpq_poly_##name##_series(to._poly(), e1._poly(), e2))
462 FMPQ_POLYXX_DEFINE_SERIES(sqrt)
463 FMPQ_POLYXX_DEFINE_SERIES(invsqrt)
464 FMPQ_POLYXX_DEFINE_SERIES(exp)
465 FMPQ_POLYXX_DEFINE_SERIES(log)
466 FMPQ_POLYXX_DEFINE_SERIES(atan)
467 FMPQ_POLYXX_DEFINE_SERIES(atanh)
468 FMPQ_POLYXX_DEFINE_SERIES(asin)
469 FMPQ_POLYXX_DEFINE_SERIES(asinh)
470 FMPQ_POLYXX_DEFINE_SERIES(tan)
471 FMPQ_POLYXX_DEFINE_SERIES(sin)
472 FMPQ_POLYXX_DEFINE_SERIES(cos)
473 FMPQ_POLYXX_DEFINE_SERIES(sinh)
474 FMPQ_POLYXX_DEFINE_SERIES(cosh)
475 FMPQ_POLYXX_DEFINE_SERIES(tanh)
476 
477 FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, fmpqxx,
478         FMPQ_POLYXX_COND_S, FMPQXX_COND_S,
479         fmpq_poly_evaluate_fmpq(to._fmpq(), e1._poly(), e2._fmpq()))
480 FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, fmpqxx,
481         FMPQ_POLYXX_COND_S, FMPZXX_COND_S,
482         fmpq_poly_evaluate_fmpz(to._fmpq(), e1._poly(), e2._fmpz()))
483 FLINT_DEFINE_BINARY_EXPR_COND2(compose_op, fmpq_polyxx,
484         FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
485         fmpq_poly_compose(to._poly(), e1._poly(), e2._poly()))
486 
487 FLINT_DEFINE_BINARY_EXPR_COND2(fmpq_polyxx_interpolate_op, fmpq_polyxx,
488         FMPZ_VECXX_COND_S, FMPZ_VECXX_COND_S,
489         fmpq_poly_interpolate_fmpz_vec(to._poly(), e1._data().array,
490             e2._data().array, e2.size()))
491 
492 FLINT_DEFINE_BINARY_EXPR_COND2(rescale_op, fmpq_polyxx,
493         FMPQ_POLYXX_COND_S, FMPQXX_COND_S,
494         fmpq_poly_rescale(to._poly(), e1._poly(), e2._fmpq()))
495 
496 FLINT_DEFINE_BINARY_EXPR_COND2(revert_series_op, fmpq_polyxx,
497         FMPQ_POLYXX_COND_S, traits::fits_into_slong,
498         fmpq_poly_revert_series(to._poly(), e1._poly(), e2))
499 
500 FLINT_DEFINE_BINARY_EXPR_COND2(revert_series_lagrange_op, fmpq_polyxx,
501         FMPQ_POLYXX_COND_S, traits::fits_into_slong,
502         fmpq_poly_revert_series_lagrange(to._poly(), e1._poly(), e2))
503 
504 FLINT_DEFINE_BINARY_EXPR_COND2(revert_series_lagrange_fast_op, fmpq_polyxx,
505         FMPQ_POLYXX_COND_S, traits::fits_into_slong,
506         fmpq_poly_revert_series_lagrange_fast(to._poly(), e1._poly(), e2))
507 
508 FLINT_DEFINE_BINARY_EXPR_COND2(revert_series_newton_op, fmpq_polyxx,
509         FMPQ_POLYXX_COND_S, traits::fits_into_slong,
510         fmpq_poly_revert_series_newton(to._poly(), e1._poly(), e2))
511 
512 FLINT_DEFINE_UNARY_EXPR_COND(content_op, fmpqxx, FMPQ_POLYXX_COND_S,
513         fmpq_poly_content(to._fmpq(), from._poly()))
514 FLINT_DEFINE_UNARY_EXPR_COND(primitive_part_op, fmpq_polyxx, FMPQ_POLYXX_COND_S,
515         fmpq_poly_primitive_part(to._poly(), from._poly()))
516 
517 FLINT_DEFINE_UNARY_EXPR_COND(make_monic_op, fmpq_polyxx, FMPQ_POLYXX_COND_S,
518         fmpq_poly_make_monic(to._poly(), from._poly()))
519 
520 FLINT_DEFINE_UNARY_EXPR_COND(fmpq_polyxx_den_op, fmpzxx, FMPQ_POLYXX_COND_S,
521         fmpz_set(to._fmpz(), fmpq_poly_denref(from._poly())))
522 
523 namespace rdetail {
524 typedef make_ltuple<mp::make_tuple<
525     fmpq_polyxx, fmpq_polyxx, fmpq_polyxx>::type>::type fmpq_polyxx_triple;
526 typedef make_ltuple<mp::make_tuple<
527     fmpq_polyxx, fmpq_polyxx>::type>::type fmpq_polyxx_pair;
528 } // rdetail
529 
530 FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_op, rdetail::fmpq_polyxx_triple,
531     FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
532     fmpq_poly_xgcd(to.template get<0>()._poly(), to.template get<1>()._poly(),
533         to.template get<2>()._poly(), e1._poly(), e2._poly()))
534 FLINT_DEFINE_BINARY_EXPR_COND2(divrem_op, rdetail::fmpq_polyxx_pair,
535     FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S,
536     fmpq_poly_divrem(to.template get<0>()._poly(), to.template get<1>()._poly(),
537         e1._poly(), e2._poly()))
538 
539 #define FMPQ_POLYXX_DEFINE_SERIES_FUNC(name) \
540 FLINT_DEFINE_THREEARY_EXPR_COND3(name##_op, fmpq_polyxx, \
541     FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S, traits::fits_into_slong, \
542     fmpq_poly_##name(to._poly(), e1._poly(), e2._poly(), e3))
543 FMPQ_POLYXX_DEFINE_SERIES_FUNC(mullow)
544 FMPQ_POLYXX_DEFINE_SERIES_FUNC(div_series)
545 FMPQ_POLYXX_DEFINE_SERIES_FUNC(compose_series)
546 FMPQ_POLYXX_DEFINE_SERIES_FUNC(compose_series_brent_kung)
547 FMPQ_POLYXX_DEFINE_SERIES_FUNC(compose_series_horner)
548 } // rules
549 
550 // NB: fmpq_poly addmul is just done by hand currently, no need to wrap that ..
551 
552 } // flint
553 
554 #endif
555