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