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 FMPZ_POLYXX_H
13 #define FMPZ_POLYXX_H
14
15 #include <cstdlib>
16 #include <string>
17
18 #include "flint.h"
19 #include "fmpz_poly.h"
20
21 #include "fmpzxx.h"
22 #include "fmpz_vecxx.h"
23
24 #include "flintxx/expression.h"
25 #include "flintxx/flint_classes.h"
26 #include "flintxx/flint_exception.h"
27 #include "flintxx/frandxx.h"
28 #include "flintxx/ltuple.h"
29 #include "flintxx/traits.h"
30 #include "flintxx/traits_fwd.h"
31
32 // TODO exhibit this as a specialisation of a generic poly<fmpzxx>
33 // TODO newton basis?
34 // TODO power series class?
35 // TODO input
36 // TODO addmul
37 // TODO more hensel lifting?
38
39 namespace flint {
40 // function "declarations"
41 FLINT_DEFINE_UNOP(sqr_karatsuba)
FLINT_DEFINE_UNOP(sqrt_classical)42 FLINT_DEFINE_UNOP(sqrt_classical)
43
44 FLINT_DEFINE_BINOP(evaluate_divconquer)
45 FLINT_DEFINE_BINOP(evaluate_horner)
46 FLINT_DEFINE_BINOP(gcd_heuristic)
47 FLINT_DEFINE_BINOP(gcd_modular)
48 FLINT_DEFINE_BINOP(gcd_subresultant)
49 FLINT_DEFINE_BINOP(mul_karatsuba)
50 FLINT_DEFINE_BINOP(mulmid_classical)
51 FLINT_DEFINE_BINOP(mul_SS)
52 FLINT_DEFINE_BINOP(divides)
53 FLINT_DEFINE_BINOP(pow_addchains)
54 FLINT_DEFINE_BINOP(pow_binomial)
55 FLINT_DEFINE_BINOP(pow_multinomial)
56 FLINT_DEFINE_BINOP(pseudo_div)
57 FLINT_DEFINE_BINOP(pseudo_divrem)
58 FLINT_DEFINE_BINOP(pseudo_divrem_basecase)
59 FLINT_DEFINE_BINOP(pseudo_divrem_cohen)
60 FLINT_DEFINE_BINOP(pseudo_divrem_divconquer)
61 FLINT_DEFINE_BINOP(pseudo_rem)
62 FLINT_DEFINE_BINOP(pseudo_rem_cohen)
63 FLINT_DEFINE_BINOP(sqrlow)
64 FLINT_DEFINE_BINOP(sqrlow_classical)
65 FLINT_DEFINE_BINOP(sqrlow_karatsuba_n)
66 FLINT_DEFINE_BINOP(sqrlow_KS)
67 FLINT_DEFINE_BINOP(taylor_shift_divconquer)
68 FLINT_DEFINE_BINOP(xgcd_modular)
69
70 FLINT_DEFINE_THREEARY(mulhigh_karatsuba_n)
71 FLINT_DEFINE_THREEARY(mulhigh_n)
72 FLINT_DEFINE_THREEARY(mullow_karatsuba_n)
73 FLINT_DEFINE_THREEARY(mullow_SS)
74
75
76 FLINT_DEFINE_BINOP(fmpz_polyxx_interpolate)
77 FLINT_DEFINE_UNOP(fmpz_polyxx_product_roots)
78 FLINT_DEFINE_UNOP(fmpz_polyxx_lead)
79 FLINT_DEFINE_BINOP(fmpz_polyxx_get_coeff)
80 FLINT_DEFINE_BINOP(fmpz_polyxx_bit_unpack)
81 FLINT_DEFINE_BINOP(fmpz_polyxx_bit_unpack_unsigned)
82
83 FLINT_DEFINE_SEVENARY(hensel_lift)
84 FLINT_DEFINE_SEVENARY(hensel_lift_without_inverse)
85 FLINT_DEFINE_SIXARY(hensel_lift_only_inverse)
86
87
88 namespace detail {
89 template<class Poly>
90 struct fmpz_poly_traits
91 {
92 typedef FLINT_UNOP_BUILD_RETTYPE(
93 fmpz_polyxx_lead, fmpzxx, Poly) lead_ref_t;
94 typedef lead_ref_t lead_srcref_t;
95 static lead_ref_t lead(const Poly& p) {return fmpz_polyxx_lead(p);}
96
97 template<class T>
98 struct coeff
99 {
100 typedef FLINT_BINOP_ENABLE_RETTYPE(fmpz_polyxx_get_coeff, Poly, T) ref_t;
101 typedef ref_t srcref_t;
102 static ref_t get(const Poly& p, const T& t)
103 {return fmpz_polyxx_get_coeff(p, t);}
104 };
105 };
106 }
107
108 template<class Operation, class Data>
109 class fmpz_polyxx_expression
110 : public expression<derived_wrapper<fmpz_polyxx_expression>,
111 Operation, Data>
112 {
113 public:
114 typedef expression<derived_wrapper< ::flint::fmpz_polyxx_expression>,
115 Operation, Data> base_t;
116 typedef detail::fmpz_poly_traits<fmpz_polyxx_expression> poly_traits_t;
117
118 FLINTXX_DEFINE_BASICS(fmpz_polyxx_expression)
FLINTXX_DEFINE_CTORS(fmpz_polyxx_expression)119 FLINTXX_DEFINE_CTORS(fmpz_polyxx_expression)
120 FLINTXX_DEFINE_C_REF(fmpz_polyxx_expression, fmpz_poly_struct, _poly)
121
122 // static methods which only make sense with fmpz_polyxx
123 static fmpz_polyxx_expression randtest(frandxx& state, slong len,
124 flint_bitcnt_t bits)
125 {
126 fmpz_polyxx_expression res;
127 fmpz_poly_randtest(res._poly(), state._data(), len, bits);
128 return res;
129 }
randtest_unsigned(frandxx & state,slong len,flint_bitcnt_t bits)130 static fmpz_polyxx_expression randtest_unsigned(frandxx& state, slong len,
131 flint_bitcnt_t bits)
132 {
133 fmpz_polyxx_expression res;
134 fmpz_poly_randtest_unsigned(res._poly(), state._data(), len, bits);
135 return res;
136 }
randtest_not_zero(frandxx & state,slong len,flint_bitcnt_t bits)137 static fmpz_polyxx_expression randtest_not_zero(frandxx& state, slong len,
138 flint_bitcnt_t bits)
139 {
140 fmpz_polyxx_expression res;
141 fmpz_poly_randtest_not_zero(res._poly(), state._data(), len, bits);
142 return res;
143 }
144
145 template<class Fmpz_vec1, class Fmpz_vec2>
FLINT_BINOP_ENABLE_RETTYPE(fmpz_polyxx_interpolate,Fmpz_vec1,Fmpz_vec2)146 static FLINT_BINOP_ENABLE_RETTYPE(fmpz_polyxx_interpolate,
147 Fmpz_vec1, Fmpz_vec2)
148 interpolate(const Fmpz_vec1& xs, const Fmpz_vec2& ys)
149 {
150 return fmpz_polyxx_interpolate(xs, ys);
151 }
152
153 template<class Fmpz_vec>
FLINT_UNOP_ENABLE_RETTYPE(fmpz_polyxx_product_roots,Fmpz_vec)154 static FLINT_UNOP_ENABLE_RETTYPE(fmpz_polyxx_product_roots, Fmpz_vec)
155 product_roots(const Fmpz_vec& xs)
156 {
157 return fmpz_polyxx_product_roots(xs);
158 }
159
160 template<class Arg1, class Arg2>
FLINT_BINOP_ENABLE_RETTYPE(fmpz_polyxx_bit_unpack,Arg1,Arg2)161 static FLINT_BINOP_ENABLE_RETTYPE(fmpz_polyxx_bit_unpack,
162 Arg1, Arg2)
163 bit_unpack(const Arg1& a1, const Arg2& a2)
164 {
165 return fmpz_polyxx_bit_unpack(a1, a2);
166 }
167 template<class Arg1, class Arg2>
FLINT_BINOP_ENABLE_RETTYPE(fmpz_polyxx_bit_unpack_unsigned,Arg1,Arg2)168 static FLINT_BINOP_ENABLE_RETTYPE(fmpz_polyxx_bit_unpack_unsigned,
169 Arg1, Arg2)
170 bit_unpack_unsigned(const Arg1& a1, const Arg2& a2)
171 {
172 return fmpz_polyxx_bit_unpack_unsigned(a1, a2);
173 }
174
175 template<class T>
from_ground(const T & t)176 static fmpz_polyxx_expression from_ground(const T& t)
177 {
178 fmpz_polyxx_expression res;
179 fmpzxx u; u = t;
180 res.set_coeff(0, u);
181 return res;
182 }
183
184 template<class Nmod_poly>
_lift(const Nmod_poly & poly)185 static fmpz_polyxx_expression _lift(const Nmod_poly& poly)
186 {
187 fmpz_polyxx_expression res(poly.length());
188 fmpz_poly_set_nmod_poly(res._poly(), poly._poly());
189 return res;
190 }
191 template<class Nmod_poly>
192 static fmpz_polyxx_expression lift(const Nmod_poly& poly,
193 typename mp::enable_if<traits::is_nmod_polyxx<Nmod_poly> >::type* = 0)
194 {
195 return _lift(poly.evaluate());
196 }
197 template<class Nmod_poly>
_lift_unsigned(const Nmod_poly & poly)198 static fmpz_polyxx_expression _lift_unsigned(const Nmod_poly& poly)
199 {
200 fmpz_polyxx_expression res(poly.length());
201 fmpz_poly_set_nmod_poly_unsigned(res._poly(), poly.evaluate()._poly());
202 return res;
203 }
204 template<class Nmod_poly>
205 static fmpz_polyxx_expression lift_unsigned(const Nmod_poly& poly,
206 typename mp::enable_if<traits::is_nmod_polyxx<Nmod_poly> >::type* = 0)
207 {
208 return _lift_unsigned(poly.evaluate());
209 }
210
zero()211 static fmpz_polyxx_expression zero() {return fmpz_polyxx_expression();}
one()212 static fmpz_polyxx_expression one()
213 {
214 fmpz_polyxx_expression res;
215 res.set_one();
216 return res;
217 }
218
219 // These only make sense with immediates
realloc(slong alloc)220 void realloc(slong alloc) {fmpz_poly_realloc(_poly(), alloc);}
fit_length(slong len)221 void fit_length(slong len) {fmpz_poly_fit_length(_poly(), len);}
_normalise()222 void _normalise() {_fmpz_poly_normalise(_poly());}
_set_length(slong len)223 void _set_length(slong len) {_fmpz_poly_set_length(_poly(), len);}
zero_coeffs(slong i,slong j)224 void zero_coeffs(slong i, slong j) {fmpz_poly_zero_coeffs(_poly(), i, j);}
set_zero()225 void set_zero() {fmpz_poly_zero(_poly());}
set_one()226 void set_one() {fmpz_poly_one(_poly());}
227
228 // The result of these are undefined if n is >= length
229 // You also may have to call _normalise().
230 template<class T>
coeff(const T & n)231 typename poly_traits_t::template coeff<T>::ref_t coeff(const T& n)
232 {
233 return poly_traits_t::template coeff<T>::get(*this, n);
234 }
235 template<class T>
236 typename poly_traits_t::template coeff<T>::srcref_t
coeff(const T & n)237 coeff(const T& n) const
238 {
239 return poly_traits_t::template coeff<T>::get(*this, n);
240 }
lead()241 typename poly_traits_t::lead_ref_t lead()
242 {
243 return poly_traits_t::lead(*this);
244 }
lead()245 typename poly_traits_t::lead_srcref_t lead() const
246 {
247 return poly_traits_t::lead(*this);
248 }
249
250 // These only make sense with target immediates
251 template<class Fmpz>
252 typename mp::enable_if<traits::is_fmpzxx<Fmpz> >::type
set_coeff(slong n,const Fmpz & x)253 set_coeff(slong n, const Fmpz& x)
254 {
255 fmpz_poly_set_coeff_fmpz(_poly(), n, x.evaluate()._fmpz());
256 }
257 template<class T>
258 typename mp::enable_if<traits::is_signed_integer<T> >::type
set_coeff(slong n,T x)259 set_coeff(slong n, T x)
260 {
261 fmpz_poly_set_coeff_si(_poly(), n, x);
262 }
263 template<class T>
264 typename mp::enable_if<traits::is_unsigned_integer<T> >::type
set_coeff(slong n,T x)265 set_coeff(slong n, T x)
266 {
267 fmpz_poly_set_coeff_ui(_poly(), n, x);
268 }
269
truncate(slong n)270 void truncate(slong n) {fmpz_poly_truncate(_poly(), n);}
271
272 // These cause evaluation
length()273 slong length() const {return fmpz_poly_length(this->evaluate()._poly());}
degree()274 slong degree() const {return fmpz_poly_degree(this->evaluate()._poly());}
is_one()275 bool is_one() const {return fmpz_poly_is_one(this->evaluate()._poly());}
is_zero()276 bool is_zero() const {return fmpz_poly_is_zero(this->evaluate()._poly());}
is_unit()277 bool is_unit() const {return fmpz_poly_is_unit(this->evaluate()._poly());}
max_limbs()278 ulong max_limbs() const {return fmpz_poly_max_limbs(this->evaluate()._poly());}
max_bits()279 slong max_bits() const {return fmpz_poly_max_bits(this->evaluate()._poly());}
280
pretty(const char * x)281 std::string pretty(const char* x) const
282 {
283 char* str = fmpz_poly_get_str_pretty(this->evaluate()._poly(), x);
284 std::string res(str);
285 flint_free(str);
286 return res;
287 }
288
signature(slong & r1,slong & r2)289 void signature(slong& r1, slong& r2) const
290 {
291 fmpz_poly_signature(&r1, &r2, this->evaluate()._poly());
292 }
293
294 int read_pretty(char** x, FILE* f = stdin)
295 {
296 return fmpz_poly_fread_pretty(f, _poly(), x);
297 }
298
299 // lazy member forwarding
300 FLINTXX_DEFINE_MEMBER_BINOP_(operator(), compeval)
301 FLINTXX_DEFINE_MEMBER_BINOP_(get_coeff, fmpz_polyxx_get_coeff)
302
303 FLINTXX_DEFINE_MEMBER_BINOP(bit_pack)
304 FLINTXX_DEFINE_MEMBER_BINOP(compose_divconquer)
305 FLINTXX_DEFINE_MEMBER_BINOP(compose_horner)
306 FLINTXX_DEFINE_MEMBER_BINOP(div_basecase)
307 FLINTXX_DEFINE_MEMBER_BINOP(div_divconquer)
308 FLINTXX_DEFINE_MEMBER_BINOP(divexact)
309 FLINTXX_DEFINE_MEMBER_BINOP(divides)
310 FLINTXX_DEFINE_MEMBER_BINOP(divrem)
311 FLINTXX_DEFINE_MEMBER_BINOP(divrem_basecase)
312 FLINTXX_DEFINE_MEMBER_BINOP(divrem_divconquer)
313 FLINTXX_DEFINE_MEMBER_BINOP(div_root)
314 FLINTXX_DEFINE_MEMBER_BINOP(evaluate_divconquer)
315 FLINTXX_DEFINE_MEMBER_BINOP(evaluate_horner)
316 FLINTXX_DEFINE_MEMBER_BINOP(fdiv_2exp)
317 FLINTXX_DEFINE_MEMBER_BINOP(gcd)
318 FLINTXX_DEFINE_MEMBER_BINOP(gcd_heuristic)
319 FLINTXX_DEFINE_MEMBER_BINOP(gcd_modular)
320 FLINTXX_DEFINE_MEMBER_BINOP(gcd_subresultant)
321 FLINTXX_DEFINE_MEMBER_BINOP(inv_series)
322 FLINTXX_DEFINE_MEMBER_BINOP(inv_series_newton)
323 FLINTXX_DEFINE_MEMBER_BINOP(lcm)
324 FLINTXX_DEFINE_MEMBER_BINOP(mul_2exp)
325 FLINTXX_DEFINE_MEMBER_BINOP(mul_classical)
326 FLINTXX_DEFINE_MEMBER_BINOP(mul_karatsuba)
327 FLINTXX_DEFINE_MEMBER_BINOP(mul_KS)
328 FLINTXX_DEFINE_MEMBER_BINOP(mulmid_classical)
329 FLINTXX_DEFINE_MEMBER_BINOP(mul_SS)
330 FLINTXX_DEFINE_MEMBER_BINOP(shift_left)
331 FLINTXX_DEFINE_MEMBER_BINOP(shift_right)
332 FLINTXX_DEFINE_MEMBER_BINOP(pow)
333 FLINTXX_DEFINE_MEMBER_BINOP(pow_addchains)
334 FLINTXX_DEFINE_MEMBER_BINOP(pow_binexp)
335 FLINTXX_DEFINE_MEMBER_BINOP(pow_binomial)
336 FLINTXX_DEFINE_MEMBER_BINOP(pow_multinomial)
337 FLINTXX_DEFINE_MEMBER_BINOP(pseudo_div)
338 FLINTXX_DEFINE_MEMBER_BINOP(pseudo_divrem)
339 FLINTXX_DEFINE_MEMBER_BINOP(pseudo_divrem_basecase)
340 FLINTXX_DEFINE_MEMBER_BINOP(pseudo_divrem_cohen)
341 FLINTXX_DEFINE_MEMBER_BINOP(pseudo_divrem_divconquer)
342 FLINTXX_DEFINE_MEMBER_BINOP(pseudo_rem)
343 FLINTXX_DEFINE_MEMBER_BINOP(pseudo_rem_cohen)
344 FLINTXX_DEFINE_MEMBER_BINOP(resultant)
345 FLINTXX_DEFINE_MEMBER_BINOP(reverse)
346 FLINTXX_DEFINE_MEMBER_BINOP(revert_series)
347 FLINTXX_DEFINE_MEMBER_BINOP(revert_series_lagrange)
348 FLINTXX_DEFINE_MEMBER_BINOP(revert_series_lagrange_fast)
349 FLINTXX_DEFINE_MEMBER_BINOP(revert_series_newton)
350 FLINTXX_DEFINE_MEMBER_BINOP(smod)
351 FLINTXX_DEFINE_MEMBER_BINOP(sqrlow)
352 FLINTXX_DEFINE_MEMBER_BINOP(sqrlow_classical)
353 FLINTXX_DEFINE_MEMBER_BINOP(sqrlow_karatsuba_n)
354 FLINTXX_DEFINE_MEMBER_BINOP(sqrlow_KS)
355 FLINTXX_DEFINE_MEMBER_BINOP(taylor_shift)
356 FLINTXX_DEFINE_MEMBER_BINOP(taylor_shift_divconquer)
357 FLINTXX_DEFINE_MEMBER_BINOP(taylor_shift_horner)
358 FLINTXX_DEFINE_MEMBER_BINOP(tdiv)
359 FLINTXX_DEFINE_MEMBER_BINOP(tdiv_2exp)
360 FLINTXX_DEFINE_MEMBER_BINOP(xgcd)
361 FLINTXX_DEFINE_MEMBER_BINOP(xgcd_modular)
362
363 FLINTXX_DEFINE_MEMBER_UNOP(derivative)
364 FLINTXX_DEFINE_MEMBER_UNOP(primitive_part)
365 FLINTXX_DEFINE_MEMBER_UNOP(sqr)
366 FLINTXX_DEFINE_MEMBER_UNOP(sqr_classical)
367 FLINTXX_DEFINE_MEMBER_UNOP(sqr_karatsuba)
368 FLINTXX_DEFINE_MEMBER_UNOP(sqr_KS)
369 FLINTXX_DEFINE_MEMBER_UNOP(sqrt)
370 FLINTXX_DEFINE_MEMBER_UNOP(sqrt_classical)
371
372 FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpzxx, bound_roots)
373 FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpzxx, twonorm)
374
375 FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpzxx, content)
376 FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpzxx, height)
377
378 FLINTXX_DEFINE_MEMBER_3OP(compose_series)
379 FLINTXX_DEFINE_MEMBER_3OP(compose_series_brent_kung)
380 FLINTXX_DEFINE_MEMBER_3OP(compose_series_horner)
381 FLINTXX_DEFINE_MEMBER_3OP(div_series)
382 FLINTXX_DEFINE_MEMBER_3OP(mulhigh_classical)
383 FLINTXX_DEFINE_MEMBER_3OP(mulhigh_karatsuba_n)
384 FLINTXX_DEFINE_MEMBER_3OP(mulhigh_n)
385 FLINTXX_DEFINE_MEMBER_3OP(mullow)
386 FLINTXX_DEFINE_MEMBER_3OP(mullow_classical)
387 FLINTXX_DEFINE_MEMBER_3OP(mullow_karatsuba_n)
388 FLINTXX_DEFINE_MEMBER_3OP(mullow_KS)
389 FLINTXX_DEFINE_MEMBER_3OP(mullow_SS)
390 FLINTXX_DEFINE_MEMBER_3OP(pow_trunc)
391
392 FLINTXX_DEFINE_MEMBER_4OP(CRT)
393 };
394
395 namespace detail {
396 struct fmpz_poly_data;
397 }
398
399 typedef fmpz_polyxx_expression<operations::immediate, detail::fmpz_poly_data>
400 fmpz_polyxx;
401 typedef fmpz_polyxx_expression<operations::immediate,
402 flint_classes::ref_data<fmpz_polyxx, fmpz_poly_struct> >
403 fmpz_polyxx_ref;
404 typedef fmpz_polyxx_expression<operations::immediate,
405 flint_classes::srcref_data<
406 fmpz_polyxx, fmpz_polyxx_ref, fmpz_poly_struct> >
407 fmpz_polyxx_srcref;
408
409 namespace detail {
410 template<>
411 struct fmpz_poly_traits<fmpz_polyxx_srcref>
412 {
413 typedef fmpzxx_srcref lead_srcref_t;
414 typedef fmpzxx_srcref lead_ref_t;
415
416 template<class P>
417 static lead_srcref_t lead(const P& p)
418 {return lead_srcref_t::make(fmpz_poly_lead(p._poly()));}
419
420 template<class T>
421 struct coeff
422 {
423 typedef typename mp::enable_if<
424 traits::is_integer<T>, fmpzxx_srcref>::type ref_t;
425 typedef ref_t srcref_t;
426
427 template<class P>
428 static srcref_t get(const P& p, const T& n)
429 {return srcref_t::make(fmpz_poly_coeff_ptr(p._poly(), n));}
430 };
431 };
432 template<>
433 struct fmpz_poly_traits<fmpz_polyxx_ref>
434 {
435 typedef fmpzxx_ref lead_ref_t;
436 typedef fmpzxx_ref lead_srcref_t;
437
438 template<class P>
439 static lead_ref_t lead(P p)
440 {return lead_ref_t::make(fmpz_poly_lead(p._poly()));}
441
442 template<class T>
443 struct coeff
444 {
445 typedef fmpzxx_ref ref_t;
446 typedef fmpzxx_ref srcref_t;
447
448 template<class P>
449 static ref_t get(P p, const T& n)
450 {return ref_t::make(fmpz_poly_get_coeff_ptr(p._poly(), n));}
451 };
452 };
453 template<>
454 struct fmpz_poly_traits<fmpz_polyxx>
455 {
456 typedef fmpzxx_ref lead_ref_t;
457 typedef fmpzxx_srcref lead_srcref_t;
458
459 template<class P>
460 static lead_ref_t lead(P& p)
461 {return lead_ref_t::make(fmpz_poly_lead(p._poly()));}
462 template<class P>
463 static lead_srcref_t lead(const P& p)
464 {return lead_srcref_t::make(fmpz_poly_lead(p._poly()));}
465
466 template<class T>
467 struct coeff
468 {
469 typedef fmpzxx_ref ref_t;
470 typedef fmpzxx_srcref srcref_t;
471
472 template<class P>
473 static ref_t get(P& p, const T& n)
474 {return ref_t::make(fmpz_poly_get_coeff_ptr(p._poly(), n));}
475 template<class P>
476 static srcref_t get(const P& p, const T& n)
477 {return srcref_t::make(fmpz_poly_get_coeff_ptr(p._poly(), n));}
478 };
479 };
480
481 struct fmpz_poly_data
482 {
483 fmpz_poly_t inner;
484 typedef fmpz_poly_t& data_ref_t;
485 typedef const fmpz_poly_t& data_srcref_t;
486
487 fmpz_poly_data() {fmpz_poly_init(inner);}
488 ~fmpz_poly_data() {fmpz_poly_clear(inner);}
489
490 fmpz_poly_data(const fmpz_poly_data& o)
491 {
492 fmpz_poly_init(inner);
493 fmpz_poly_set(inner, o.inner);
494 }
495
496 fmpz_poly_data(fmpz_polyxx_srcref r)
497 {
498 fmpz_poly_init(inner);
499 fmpz_poly_set(inner, r._poly());
500 }
501
502 fmpz_poly_data(slong alloc)
503 {
504 fmpz_poly_init2(inner, alloc);
505 }
506
507 fmpz_poly_data(const char* str)
508 {
509 fmpz_poly_init(inner);
510 execution_check(!fmpz_poly_set_str(inner, str),
511 "construct from string", "fmpz_polyxx");
512 }
513 };
514 } // detail
515
516 namespace traits {
517 template<class T> struct is_fmpz_polyxx : mp::or_<
518 traits::is_T_expr<T, fmpz_polyxx>,
519 flint_classes::is_source<fmpz_polyxx, T> > { };
520 } // traits
521 namespace mp {
522 template<class T1, class T2 = void, class T3 = void, class T4 = void>
523 struct all_fmpz_polyxx : mp::and_<all_fmpz_polyxx<T1>, all_fmpz_polyxx<T2, T3, T4> > { };
524 template<class T>
525 struct all_fmpz_polyxx<T, void, void, void> : traits::is_fmpz_polyxx<T> { };
526
527 template<class Out, class T1, class T2 = void, class T3 = void, class T4 = void>
528 struct enable_all_fmpz_polyxx
529 : mp::enable_if<all_fmpz_polyxx<T1, T2, T3, T4>, Out> { };
530 } // mp
531
532 namespace rules {
533 #define FMPZ_POLYXX_COND_S FLINTXX_COND_S(fmpz_polyxx)
534 #define FMPZ_POLYXX_COND_T FLINTXX_COND_T(fmpz_polyxx)
535
536 FLINTXX_DEFINE_EQUALS(fmpz_polyxx, fmpz_poly_equal(e1._poly(), e2._poly()))
537
538 FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_POLYXX_COND_T, FMPZ_POLYXX_COND_S,
539 fmpz_poly_set(to._poly(), from._poly()))
540 FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_POLYXX_COND_T,
541 traits::is_signed_integer,
542 fmpz_poly_set_si(to._poly(), from))
543 FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_POLYXX_COND_T,
544 traits::is_unsigned_integer,
545 fmpz_poly_set_ui(to._poly(), from))
546 FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_POLYXX_COND_T, FMPZXX_COND_S,
547 fmpz_poly_set_fmpz(to._poly(), from._fmpz()))
548 FLINTXX_DEFINE_ASSIGN_STR(fmpz_polyxx, execution_check(
549 !fmpz_poly_set_str(to._poly(), from), "assign string", "fmpz_polyxx"))
550
551 FLINT_DEFINE_PRINT_COND(FMPZ_POLYXX_COND_S, fmpz_poly_fprint(to, from._poly()))
552 FLINT_DEFINE_PRINT_PRETTY_COND_2(FMPZ_POLYXX_COND_S, const char*,
553 fmpz_poly_fprint_pretty(to, from._poly(), extra))
554 FLINT_DEFINE_READ_COND(FMPZ_POLYXX_COND_T, fmpz_poly_fread(from, to._poly()))
555
556 FLINTXX_DEFINE_TO_STR(fmpz_polyxx, fmpz_poly_get_str(from._poly()))
557 FLINTXX_DEFINE_SWAP(fmpz_polyxx, fmpz_poly_swap(e1._poly(), e2._poly()))
558
559 FLINT_DEFINE_BINARY_EXPR_COND2(reverse_op, fmpz_polyxx,
560 FMPZ_POLYXX_COND_S, traits::fits_into_slong,
561 fmpz_poly_reverse(to._poly(), e1._poly(), e2))
562
563 FLINT_DEFINE_BINARY_EXPR_COND2(plus, fmpz_polyxx,
564 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
565 fmpz_poly_add(to._poly(), e1._poly(), e2._poly()))
566 FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpz_polyxx,
567 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
568 fmpz_poly_sub(to._poly(), e1._poly(), e2._poly()))
569
570 FLINT_DEFINE_UNARY_EXPR_COND(negate, fmpz_polyxx, FMPZ_POLYXX_COND_S,
571 fmpz_poly_neg(to._poly(), from._poly()))
572
573 FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_polyxx,
574 FMPZ_POLYXX_COND_S, FMPZXX_COND_S,
575 fmpz_poly_scalar_mul_fmpz(to._poly(), e1._poly(), e2._fmpz()))
576 FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_polyxx,
577 FMPZ_POLYXX_COND_S, traits::is_signed_integer,
578 fmpz_poly_scalar_mul_si(to._poly(), e1._poly(), e2))
579 FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_polyxx,
580 FMPZ_POLYXX_COND_S, traits::is_unsigned_integer,
581 fmpz_poly_scalar_mul_ui(to._poly(), e1._poly(), e2))
582
583 FLINT_DEFINE_CBINARY_EXPR_COND2(mul_2exp_op, fmpz_polyxx,
584 FMPZ_POLYXX_COND_S, traits::is_unsigned_integer,
585 fmpz_poly_scalar_mul_2exp(to._poly(), e1._poly(), e2))
586
587 FLINT_DEFINE_CBINARY_EXPR_COND2(divided_by, fmpz_polyxx,
588 FMPZ_POLYXX_COND_S, FMPZXX_COND_S,
589 fmpz_poly_scalar_fdiv_fmpz(to._poly(), e1._poly(), e2._fmpz()))
590 FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpz_polyxx,
591 FMPZ_POLYXX_COND_S, traits::is_unsigned_integer,
592 fmpz_poly_scalar_fdiv_ui(to._poly(), e1._poly(), e2))
593 FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpz_polyxx,
594 FMPZ_POLYXX_COND_S, traits::is_signed_integer,
595 fmpz_poly_scalar_fdiv_si(to._poly(), e1._poly(), e2))
596
597 FLINT_DEFINE_CBINARY_EXPR_COND2(fdiv_2exp_op, fmpz_polyxx,
598 FMPZ_POLYXX_COND_S, traits::is_unsigned_integer,
599 fmpz_poly_scalar_fdiv_2exp(to._poly(), e1._poly(), e2))
600
601 #define FMPZ_POLYXX_DEFINE_SCALAR_DIVFUNCS(name) \
602 FLINT_DEFINE_CBINARY_EXPR_COND2(name##_op, fmpz_polyxx, \
603 FMPZ_POLYXX_COND_S, FMPZXX_COND_S, \
604 fmpz_poly_scalar_##name##_fmpz(to._poly(), e1._poly(), e2._fmpz())) \
605 FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, fmpz_polyxx, \
606 FMPZ_POLYXX_COND_S, traits::is_unsigned_integer, \
607 fmpz_poly_scalar_##name##_ui(to._poly(), e1._poly(), e2)) \
608 FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, fmpz_polyxx, \
609 FMPZ_POLYXX_COND_S, traits::is_signed_integer, \
610 fmpz_poly_scalar_##name##_si(to._poly(), e1._poly(), e2))
611 FMPZ_POLYXX_DEFINE_SCALAR_DIVFUNCS(tdiv)
612 FMPZ_POLYXX_DEFINE_SCALAR_DIVFUNCS(divexact)
613
614 FLINT_DEFINE_CBINARY_EXPR_COND2(tdiv_2exp_op, fmpz_polyxx,
615 FMPZ_POLYXX_COND_S, traits::is_unsigned_integer,
616 fmpz_poly_scalar_tdiv_2exp(to._poly(), e1._poly(), e2))
617
618 FLINT_DEFINE_BINARY_EXPR_COND2(modulo, fmpz_polyxx,
619 FMPZ_POLYXX_COND_S, FMPZXX_COND_S,
620 fmpz_poly_scalar_mod_fmpz(to._poly(), e1._poly(), e2._fmpz()))
621
622 FLINT_DEFINE_BINARY_EXPR_COND2(smod_op, fmpz_polyxx,
623 FMPZ_POLYXX_COND_S, FMPZXX_COND_S,
624 fmpz_poly_scalar_smod_fmpz(to._poly(), e1._poly(), e2._fmpz()))
625
626 FLINT_DEFINE_BINARY_EXPR_COND2(bit_pack_op, fmpzxx,
627 FMPZ_POLYXX_COND_S, traits::fits_into_flint_bitcnt_t,
628 fmpz_poly_bit_pack(to._fmpz(), e1._poly(), e2))
629
630 FLINT_DEFINE_BINARY_EXPR_COND2(fmpz_polyxx_bit_unpack_op, fmpz_polyxx,
631 FMPZXX_COND_S, traits::fits_into_flint_bitcnt_t,
632 fmpz_poly_bit_unpack(to._poly(), e1._fmpz(), e2))
633
634 FLINT_DEFINE_BINARY_EXPR_COND2(fmpz_polyxx_bit_unpack_unsigned_op, fmpz_polyxx,
635 FMPZXX_COND_S, traits::fits_into_flint_bitcnt_t,
636 fmpz_poly_bit_unpack_unsigned(to._poly(), e1._fmpz(), e2))
637
638 FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpz_polyxx,
639 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
640 fmpz_poly_mul(to._poly(), e1._poly(), e2._poly()))
641
642 #define FMPZ_POLYXX_DEFINE_MUL(name) \
643 FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, fmpz_polyxx, \
644 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, \
645 fmpz_poly_##name(to._poly(), e1._poly(), e2._poly()))
646 FMPZ_POLYXX_DEFINE_MUL(mul_classical)
647 FMPZ_POLYXX_DEFINE_MUL(mulmid_classical)
648 FMPZ_POLYXX_DEFINE_MUL(mul_karatsuba)
649 FMPZ_POLYXX_DEFINE_MUL(mul_SS)
650 FMPZ_POLYXX_DEFINE_MUL(mul_KS)
651
652 FLINT_DEFINE_UNARY_EXPR_COND(sqr_KS_op, fmpz_polyxx, FMPZ_POLYXX_COND_S,
653 fmpz_poly_sqr_KS(to._poly(), from._poly()))
654 FLINT_DEFINE_UNARY_EXPR_COND(sqr_karatsuba_op, fmpz_polyxx, FMPZ_POLYXX_COND_S,
655 fmpz_poly_sqr_karatsuba(to._poly(), from._poly()))
656 FLINT_DEFINE_UNARY_EXPR_COND(sqr_classical_op, fmpz_polyxx, FMPZ_POLYXX_COND_S,
657 fmpz_poly_sqr_classical(to._poly(), from._poly()))
658 FLINT_DEFINE_UNARY_EXPR_COND(sqr_op, fmpz_polyxx, FMPZ_POLYXX_COND_S,
659 fmpz_poly_sqr(to._poly(), from._poly()))
660
661 #define FMPZ_POLYXX_DEFINE_SQRLOW(name) \
662 FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, fmpz_polyxx, \
663 FMPZ_POLYXX_COND_S, traits::fits_into_slong, \
664 fmpz_poly_##name(to._poly(), e1._poly(), e2))
665 FMPZ_POLYXX_DEFINE_SQRLOW(sqrlow_KS)
666 FMPZ_POLYXX_DEFINE_SQRLOW(sqrlow_karatsuba_n)
667 FMPZ_POLYXX_DEFINE_SQRLOW(sqrlow_classical)
668 FMPZ_POLYXX_DEFINE_SQRLOW(sqrlow)
669
670 #define FMPZ_POLYXX_DEFINE_POW(name) \
671 FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, fmpz_polyxx, \
672 FMPZ_POLYXX_COND_S, traits::is_unsigned_integer, \
673 fmpz_poly_##name(to._poly(), e1._poly(), e2))
674 FMPZ_POLYXX_DEFINE_POW(pow_multinomial)
675 FMPZ_POLYXX_DEFINE_POW(pow_binomial)
676 FMPZ_POLYXX_DEFINE_POW(pow_addchains)
677 FMPZ_POLYXX_DEFINE_POW(pow_binexp)
678 FMPZ_POLYXX_DEFINE_POW(pow)
679
680 FLINT_DEFINE_BINARY_EXPR_COND2(shift_left_op, fmpz_polyxx,
681 FMPZ_POLYXX_COND_S, traits::fits_into_slong,
682 fmpz_poly_shift_left(to._poly(), e1._poly(), e2))
683 FLINT_DEFINE_BINARY_EXPR_COND2(shift_right_op, fmpz_polyxx,
684 FMPZ_POLYXX_COND_S, traits::fits_into_slong,
685 fmpz_poly_shift_right(to._poly(), e1._poly(), e2))
686
687 FLINT_DEFINE_UNARY_EXPR_COND(height_op, fmpzxx, FMPZ_POLYXX_COND_S,
688 fmpz_poly_height(to._fmpz(), from._poly()))
689 FLINT_DEFINE_UNARY_EXPR_COND(twonorm_op, fmpzxx, FMPZ_POLYXX_COND_S,
690 fmpz_poly_2norm(to._fmpz(), from._poly()))
691
692 FMPZ_POLYXX_DEFINE_MUL(gcd)
693 FMPZ_POLYXX_DEFINE_MUL(gcd_subresultant)
694 FMPZ_POLYXX_DEFINE_MUL(gcd_heuristic)
695 FMPZ_POLYXX_DEFINE_MUL(gcd_modular)
696 FMPZ_POLYXX_DEFINE_MUL(lcm)
697
698 FLINT_DEFINE_BINARY_EXPR_COND2(resultant_op, fmpzxx,
699 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
700 fmpz_poly_resultant(to._fmpz(), e1._poly(), e2._poly()))
701
702 FLINT_DEFINE_UNARY_EXPR_COND(content_op, fmpzxx, FMPZ_POLYXX_COND_S,
703 fmpz_poly_content(to._fmpz(), from._poly()))
704 FLINT_DEFINE_UNARY_EXPR_COND(primitive_part_op, fmpz_polyxx, FMPZ_POLYXX_COND_S,
705 fmpz_poly_primitive_part(to._poly(), from._poly()))
706
707 FLINT_DEFINE_BINARY_EXPR_COND2(div_basecase_op, fmpz_polyxx,
708 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
709 fmpz_poly_div_basecase(to._poly(), e1._poly(), e2._poly()))
710 FLINT_DEFINE_BINARY_EXPR_COND2(div_divconquer_op, fmpz_polyxx,
711 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
712 fmpz_poly_div_divconquer(to._poly(), e1._poly(), e2._poly()))
713
714 FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpz_polyxx,
715 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
716 fmpz_poly_div(to._poly(), e1._poly(), e2._poly()))
717
718 FLINT_DEFINE_BINARY_EXPR_COND2(rem_basecase_op, fmpz_polyxx,
719 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
720 fmpz_poly_rem_basecase(to._poly(), e1._poly(), e2._poly()))
721 FLINT_DEFINE_BINARY_EXPR_COND2(modulo, fmpz_polyxx,
722 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
723 fmpz_poly_rem(to._poly(), e1._poly(), e2._poly()))
724
725 FLINT_DEFINE_BINARY_EXPR_COND2(div_root_op, fmpz_polyxx,
726 FMPZ_POLYXX_COND_S, FMPZXX_COND_S,
727 fmpz_poly_div_root(to._poly(), e1._poly(), e2._fmpz()))
728
729 FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_newton_op, fmpz_polyxx,
730 FMPZ_POLYXX_COND_S, traits::fits_into_slong,
731 fmpz_poly_inv_series_newton(to._poly(), e1._poly(), e2))
732 FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_op, fmpz_polyxx,
733 FMPZ_POLYXX_COND_S, traits::fits_into_slong,
734 fmpz_poly_inv_series(to._poly(), e1._poly(), e2))
735
736 FLINT_DEFINE_BINARY_EXPR_COND2(pseudo_rem_cohen_op, fmpz_polyxx,
737 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
738 fmpz_poly_pseudo_rem_cohen(to._poly(), e1._poly(), e2._poly()))
739
740 FLINT_DEFINE_UNARY_EXPR_COND(derivative_op, fmpz_polyxx, FMPZ_POLYXX_COND_S,
741 fmpz_poly_derivative(to._poly(), from._poly()))
742
743 FMPZ_POLYXX_DEFINE_MUL(compose)
744 FMPZ_POLYXX_DEFINE_MUL(compose_horner)
745 FMPZ_POLYXX_DEFINE_MUL(compose_divconquer)
746
747 FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, fmpzxx,
748 FMPZ_POLYXX_COND_S, FMPZXX_COND_S,
749 fmpz_poly_evaluate_fmpz(to._fmpz(), e1._poly(), e2._fmpz()))
750 FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_divconquer_op, fmpzxx,
751 FMPZ_POLYXX_COND_S, FMPZXX_COND_S,
752 fmpz_poly_evaluate_divconquer_fmpz(to._fmpz(), e1._poly(), e2._fmpz()))
753 FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_horner_op, fmpzxx,
754 FMPZ_POLYXX_COND_S, FMPZXX_COND_S,
755 fmpz_poly_evaluate_horner_fmpz(to._fmpz(), e1._poly(), e2._fmpz()))
756 FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, fmpz_vecxx,
757 FMPZ_POLYXX_COND_S, FMPZ_VECXX_COND_S,
758 fmpz_poly_evaluate_fmpz_vec(to._data().array, e1._poly(),
759 e2._data().array, e2.size()))
760
761 FLINT_DEFINE_BINARY_EXPR_COND2(fmpz_polyxx_interpolate_op, fmpz_polyxx,
762 FMPZ_VECXX_COND_S, FMPZ_VECXX_COND_S,
763 fmpz_poly_interpolate_fmpz_vec(to._poly(), e1._data().array,
764 e2._data().array, e2.size()))
765
766 FLINT_DEFINE_BINARY_EXPR_COND2(taylor_shift_horner_op, fmpz_polyxx,
767 FMPZ_POLYXX_COND_S, FMPZXX_COND_S,
768 fmpz_poly_taylor_shift_horner(to._poly(), e1._poly(), e2._fmpz()))
769 FLINT_DEFINE_BINARY_EXPR_COND2(taylor_shift_divconquer_op, fmpz_polyxx,
770 FMPZ_POLYXX_COND_S, FMPZXX_COND_S,
771 fmpz_poly_taylor_shift_divconquer(to._poly(), e1._poly(), e2._fmpz()))
772 FLINT_DEFINE_BINARY_EXPR_COND2(taylor_shift_op, fmpz_polyxx,
773 FMPZ_POLYXX_COND_S, FMPZXX_COND_S,
774 fmpz_poly_taylor_shift(to._poly(), e1._poly(), e2._fmpz()))
775
776 FMPZ_POLYXX_DEFINE_SQRLOW(revert_series)
777 FMPZ_POLYXX_DEFINE_SQRLOW(revert_series_newton)
778 FMPZ_POLYXX_DEFINE_SQRLOW(revert_series_lagrange_fast)
779 FMPZ_POLYXX_DEFINE_SQRLOW(revert_series_lagrange)
780
781 FLINT_DEFINE_UNARY_EXPR_COND(sqrt_op, fmpz_polyxx, FMPZ_POLYXX_COND_S,
782 execution_check(fmpz_poly_sqrt(to._poly(), from._poly()),
783 "sqrt", "fmpz_polyxx"))
784 FLINT_DEFINE_UNARY_EXPR_COND(sqrt_classical_op, fmpz_polyxx, FMPZ_POLYXX_COND_S,
785 execution_check(fmpz_poly_sqrt_classical(to._poly(), from._poly()),
786 "sqrt_classical", "fmpz_polyxx"))
787
788 FLINT_DEFINE_UNARY_EXPR_COND(fmpz_polyxx_product_roots_op, fmpz_polyxx,
789 FMPZ_VECXX_COND_S,
790 fmpz_poly_product_roots_fmpz_vec(to._poly(),
791 from._data().array, from.size()))
792
793 FLINT_DEFINE_BINARY_EXPR_COND2(fmpz_polyxx_get_coeff_op, fmpzxx,
794 FMPZ_POLYXX_COND_S, traits::is_integer,
795 fmpz_poly_get_coeff_fmpz(to._fmpz(), e1._poly(), e2))
796 FLINT_DEFINE_UNARY_EXPR_COND(fmpz_polyxx_lead_op, fmpzxx,
797 FMPZ_POLYXX_COND_S,
798 fmpz_set(to._fmpz(), fmpz_poly_lead(from._poly())))
799
800 FLINT_DEFINE_UNARY_EXPR_COND(bound_roots_op, fmpzxx, FMPZ_POLYXX_COND_S,
801 fmpz_poly_bound_roots(to._fmpz(), from._poly()))
802
803 namespace rdetail {
804 typedef make_ltuple<mp::make_tuple<fmpz_polyxx, fmpz_polyxx>::type>::type
805 fmpz_polyxx_pair;
806 typedef make_ltuple<mp::make_tuple<fmpzxx, fmpz_polyxx, fmpz_polyxx>::type>::type
807 fmpzxx_fmpz_polyxx_pair;
808 } // rdetail
809 #define FMPZ_POLYXX_DEFINE_DIVREM(name) \
810 FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, rdetail::fmpz_polyxx_pair, \
811 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, \
812 fmpz_poly_##name(to.template get<0>()._poly(), to.template get<1>()._poly(), \
813 e1._poly(), e2._poly()))
814 FMPZ_POLYXX_DEFINE_DIVREM(divrem_basecase)
815 FMPZ_POLYXX_DEFINE_DIVREM(divrem_divconquer)
816 FMPZ_POLYXX_DEFINE_DIVREM(divrem)
817 FMPZ_POLYXX_DEFINE_DIVREM(pseudo_divrem_cohen)
818
819 #define FMPZ_POLYXX_DEFINE_MULFUNC(name) \
820 FLINT_DEFINE_THREEARY_EXPR_COND3(name##_op, fmpz_polyxx, \
821 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, traits::fits_into_slong, \
822 fmpz_poly_##name(to._poly(), e1._poly(), e2._poly(), e3))
823
824 FMPZ_POLYXX_DEFINE_MULFUNC(mullow_classical)
825 FMPZ_POLYXX_DEFINE_MULFUNC(mulhigh_classical)
826 FMPZ_POLYXX_DEFINE_MULFUNC(mullow_karatsuba_n)
827 FMPZ_POLYXX_DEFINE_MULFUNC(mulhigh_karatsuba_n)
828 FMPZ_POLYXX_DEFINE_MULFUNC(mullow_KS)
829 FMPZ_POLYXX_DEFINE_MULFUNC(mullow_SS)
830 FMPZ_POLYXX_DEFINE_MULFUNC(mullow)
831 FMPZ_POLYXX_DEFINE_MULFUNC(mulhigh_n)
832
833 FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_op, rdetail::fmpzxx_fmpz_polyxx_pair,
834 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
835 fmpz_poly_xgcd(to.template get<0>()._fmpz(), to.template get<1>()._poly(),
836 to.template get<2>()._poly(), e1._poly(), e2._poly()))
837 FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_modular_op, rdetail::fmpzxx_fmpz_polyxx_pair,
838 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
839 fmpz_poly_xgcd_modular(to.template get<0>()._fmpz(),
840 to.template get<1>()._poly(),
841 to.template get<2>()._poly(), e1._poly(), e2._poly()))
842
843 FLINT_DEFINE_THREEARY_EXPR_COND3(pow_trunc_op, fmpz_polyxx,
844 FMPZ_POLYXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong,
845 fmpz_poly_pow_trunc(to._poly(), e1._poly(), e2, e3))
846
847 #define FMPZ_POLYXX_DEFINE_SERIES(name) \
848 FLINT_DEFINE_THREEARY_EXPR_COND3(name##_op, fmpz_polyxx, \
849 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, traits::fits_into_slong, \
850 fmpz_poly_##name(to._poly(), e1._poly(), e2._poly(), e3))
851 FMPZ_POLYXX_DEFINE_SERIES(div_series)
852 FMPZ_POLYXX_DEFINE_SERIES(compose_series_brent_kung)
853 FMPZ_POLYXX_DEFINE_SERIES(compose_series_horner)
854 FMPZ_POLYXX_DEFINE_SERIES(compose_series)
855
856 namespace rdetail {
857 typedef make_ltuple<mp::make_tuple<fmpz_polyxx, fmpz_polyxx, ulong>::type>::type
858 fmpz_polyxx_pair_ulong;
859 typedef make_ltuple<mp::make_tuple<fmpz_polyxx, ulong>::type>::type
860 fmpz_polyxx_ulong;
861 typedef make_ltuple<mp::make_tuple<bool, fmpz_polyxx>::type>::type
862 bool_fmpz_polyxx;
863 }
864 #define FMPZ_POLYXX_DEFINE_PSEUDO_DIVREM(name) \
865 FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, rdetail::fmpz_polyxx_pair_ulong, \
866 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, \
867 fmpz_poly_##name(to.template get<0>()._poly(), to.template get<1>()._poly(), \
868 &to.template get<2>(), e1._poly(), e2._poly()))
869 FMPZ_POLYXX_DEFINE_PSEUDO_DIVREM(pseudo_divrem_basecase)
870 FMPZ_POLYXX_DEFINE_PSEUDO_DIVREM(pseudo_divrem_divconquer)
871 FMPZ_POLYXX_DEFINE_PSEUDO_DIVREM(pseudo_divrem)
872
873 FLINT_DEFINE_BINARY_EXPR_COND2(pseudo_div_op, rdetail::fmpz_polyxx_ulong,
874 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
875 fmpz_poly_pseudo_div(to.template get<0>()._poly(), &to.template get<1>(),
876 e1._poly(), e2._poly()))
877 FLINT_DEFINE_BINARY_EXPR_COND2(pseudo_rem_op, rdetail::fmpz_polyxx_ulong,
878 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
879 fmpz_poly_pseudo_rem(to.template get<0>()._poly(), &to.template get<1>(),
880 e1._poly(), e2._poly()))
881
882 FLINT_DEFINE_BINARY_EXPR_COND2(divides_op, rdetail::bool_fmpz_polyxx,
883 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
884 to.template get<0> () =
885 fmpz_poly_divides(to.template get<1>()._poly(), e1._poly(), e2._poly()))
886
887 namespace rdetail {
888 typedef make_ltuple<mp::make_tuple<
889 fmpz_polyxx, fmpz_polyxx, fmpz_polyxx, fmpz_polyxx>::type>::type
890 fmpz_polyxx_quadruple;
891 }
892 FLINT_DEFINE_SEVENARY_EXPR_COND7(hensel_lift_op, rdetail::fmpz_polyxx_quadruple,
893 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
894 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
895 FMPZXX_COND_S, FMPZXX_COND_S,
896 fmpz_poly_hensel_lift(to.template get<0>()._poly(),
897 to.template get<1>()._poly(), to.template get<2>()._poly(),
898 to.template get<3>()._poly(),
899 e1._poly(), e2._poly(), e3._poly(), e4._poly(), e5._poly(),
900 e6._fmpz(), e7._fmpz()))
901 FLINT_DEFINE_SEVENARY_EXPR_COND7(hensel_lift_without_inverse_op,
902 rdetail::fmpz_polyxx_pair,
903 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
904 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
905 FMPZXX_COND_S, FMPZXX_COND_S,
906 fmpz_poly_hensel_lift_without_inverse(to.template get<0>()._poly(),
907 to.template get<1>()._poly(),
908 e1._poly(), e2._poly(), e3._poly(), e4._poly(), e5._poly(),
909 e6._fmpz(), e7._fmpz()))
910 FLINT_DEFINE_SIXARY_EXPR_COND6(hensel_lift_only_inverse_op,
911 rdetail::fmpz_polyxx_pair,
912 FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S,
913 FMPZ_POLYXX_COND_S,
914 FMPZXX_COND_S, FMPZXX_COND_S,
915 fmpz_poly_hensel_lift_only_inverse(to.template get<0>()._poly(),
916 to.template get<1>()._poly(),
917 e1._poly(), e2._poly(), e3._poly(), e4._poly(),
918 e5._fmpz(), e6._fmpz()))
919 } // rules
920
921 // immediate functions
922 // TODO make lazy when we have nmod class
923 template<class Poly>
924 inline typename mp::enable_all_fmpz_polyxx<mp_limb_t, Poly>::type
925 evaluate_mod(const Poly& p, mp_limb_t x, mp_limb_t n)
926 {
927 return fmpz_poly_evaluate_mod(p.evaluate()._poly(), x, n);
928 }
929
930 template<class Fmpz_poly>
931 int read_pretty(Fmpz_poly& f, char** x,
932 typename mp::enable_if<FMPZ_POLYXX_COND_T<Fmpz_poly> >::type* = 0)
933 {
934 return f.read_pretty(x);
935 }
936 template<class Fmpz_poly>
937 int read_pretty(FILE* fi, Fmpz_poly& f, char** x,
938 typename mp::enable_if<FMPZ_POLYXX_COND_T<Fmpz_poly> >::type* = 0)
939 {
940 return f.read_pretty(x, fi);
941 }
942 } // flint
943
944 #include "nmod_polyxx.h" // modular reconstruction code
945
946 #include "fmpz_poly_factorxx.h"
947
948 #endif
949