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 <https://www.gnu.org/licenses/>.
10 */
11
12 #ifndef NMOD_POLYXX_H
13 #define NMOD_POLYXX_H
14
15 #include <cstdlib>
16 #include <vector>
17
18 #include "nmod_poly.h"
19
20 #include "fmpzxx.h"
21 #include "nmod_vecxx.h"
22 #include "fmpz_polyxx.h"
23 #include "fmpq_polyxx.h"
24
25 #include "flintxx/expression.h"
26 #include "flintxx/ltuple.h"
27 #include "flintxx/flint_classes.h"
28 #include "flintxx/flint_exception.h"
29 #include "flintxx/frandxx.h"
30 #include "flintxx/stdmath.h"
31 #include "flintxx/traits.h"
32
33 // TODO exhibit this as a specialisation of a generic poly<nmodxx>
34 // TODO input
35 // TODO automatic mulmod, powmod etc?
36 // TODO use underscore function versions?
37 // TODO nmod_series class?
38 // TODO subproduct trees?
39
40 namespace flint {
41 FLINT_DEFINE_BINOP(div_newton)
FLINT_DEFINE_BINOP(divrem_newton)42 FLINT_DEFINE_BINOP(divrem_newton)
43 FLINT_DEFINE_BINOP(evaluate_fast)
44 FLINT_DEFINE_BINOP(evaluate_iter)
45 FLINT_DEFINE_BINOP(exp_series_basecase)
46 FLINT_DEFINE_BINOP(gcd_euclidean)
47 FLINT_DEFINE_BINOP(gcd_hgcd)
48 FLINT_DEFINE_BINOP(inv_series_basecase)
49 FLINT_DEFINE_BINOP(nmod_polyxx_get_coeff)
50 FLINT_DEFINE_BINOP(deflate)
51 FLINT_DEFINE_BINOP(inflate)
52 FLINT_DEFINE_BINOP(resultant_euclidean)
53 FLINT_DEFINE_BINOP(taylor_shift_convolution)
54 FLINT_DEFINE_BINOP(xgcd_euclidean)
55 FLINT_DEFINE_BINOP(xgcd_hgcd)
56
57 FLINT_DEFINE_THREEARY(compose_mod)
58 FLINT_DEFINE_THREEARY(compose_mod_brent_kung)
59 FLINT_DEFINE_THREEARY(compose_mod_horner)
60 FLINT_DEFINE_THREEARY(div_newton_n_preinv)
61 FLINT_DEFINE_THREEARY(divrem_newton_n_preinv)
62 FLINT_DEFINE_THREEARY(exp_series_monomial)
63 FLINT_DEFINE_THREEARY(log_series_monomial)
64 FLINT_DEFINE_THREEARY(mulmod)
65 FLINT_DEFINE_THREEARY(powmod_binexp)
66
67 FLINT_DEFINE_BINOP(nmod_polyxx_interpolate)
68 FLINT_DEFINE_BINOP(nmod_polyxx_interpolate_barycentric)
69 FLINT_DEFINE_BINOP(nmod_polyxx_interpolate_fast)
70 FLINT_DEFINE_BINOP(nmod_polyxx_interpolate_newton)
71 FLINT_DEFINE_UNOP(nmod_polyxx_product_roots)
72
73 FLINT_DEFINE_FOURARY(compose_mod_brent_kung_preinv)
74 FLINT_DEFINE_FOURARY(mulmod_preinv)
75 FLINT_DEFINE_FOURARY(powmod_binexp_preinv)
76
77 template<class Operation, class Data>
78 class nmod_polyxx_expression
79 : public expression<derived_wrapper<nmod_polyxx_expression>,
80 Operation, Data>
81 {
82 public:
83 typedef expression<derived_wrapper< ::flint::nmod_polyxx_expression>,
84 Operation, Data> base_t;
85
86 FLINTXX_DEFINE_BASICS(nmod_polyxx_expression)
87 FLINTXX_DEFINE_CTORS(nmod_polyxx_expression)
88 FLINTXX_DEFINE_C_REF(nmod_polyxx_expression, nmod_poly_struct, _poly)
89
90 // static functions for nmod_polyxx
91 template<class Nmod_vec1, class Nmod_vec2>
92 static FLINT_BINOP_ENABLE_RETTYPE(nmod_polyxx_interpolate,
93 Nmod_vec1, Nmod_vec2)
94 interpolate(const Nmod_vec1& xs, const Nmod_vec2& ys)
95 {
96 return nmod_polyxx_interpolate(xs, ys);
97 }
98 template<class Nmod_vec1, class Nmod_vec2>
99 static FLINT_BINOP_ENABLE_RETTYPE(nmod_polyxx_interpolate_fast,
100 Nmod_vec1, Nmod_vec2)
101 interpolate_fast(const Nmod_vec1& xs, const Nmod_vec2& ys)
102 {
103 return nmod_polyxx_interpolate_fast(xs, ys);
104 }
105 template<class Nmod_vec1, class Nmod_vec2>
106 static FLINT_BINOP_ENABLE_RETTYPE(nmod_polyxx_interpolate_newton,
107 Nmod_vec1, Nmod_vec2)
108 interpolate_newton(const Nmod_vec1& xs, const Nmod_vec2& ys)
109 {
110 return nmod_polyxx_interpolate_newton(xs, ys);
111 }
112 template<class Nmod_vec1, class Nmod_vec2>
113 static FLINT_BINOP_ENABLE_RETTYPE(nmod_polyxx_interpolate_barycentric,
114 Nmod_vec1, Nmod_vec2)
115 interpolate_barycentric(const Nmod_vec1& xs, const Nmod_vec2& ys)
116 {
117 return nmod_polyxx_interpolate_barycentric(xs, ys);
118 }
119
120 template<class Nmod_vec>
121 static FLINT_UNOP_ENABLE_RETTYPE(nmod_polyxx_product_roots, Nmod_vec)
122 product_roots(const Nmod_vec& xs)
123 {
124 return nmod_polyxx_product_roots(xs);
125 }
126
127 // XXX this is difficult to make lazy
128 template<class Fmpz>
129 static typename mp::enable_if<traits::is_fmpzxx<Fmpz>,
130 nmod_polyxx_expression>::type
131 bit_unpack(const Fmpz& a, flint_bitcnt_t bits, nmodxx_ctx_srcref modulus)
132 {
133 nmod_polyxx_expression res(modulus);
134 nmod_poly_bit_unpack(res._poly(), a.evaluate()._fmpz(), bits);
135 return res;
136 }
137
138 FLINTXX_DEFINE_FORWARD_STATIC(from_ground)
139 FLINTXX_DEFINE_FORWARD_STATIC(reduce)
140
141 static nmod_polyxx_expression zero(mp_limb_t n)
142 {return nmod_polyxx_expression(n);}
143 static nmod_polyxx_expression one(mp_limb_t n)
144 {
145 nmod_polyxx_expression res(n);
146 res.set_one();
147 return res;
148 }
149
150 static nmod_polyxx_expression randtest(mp_limb_t n,
151 frandxx& state, slong len)
152 {
153 nmod_polyxx_expression res(n);
154 res.set_randtest(state, len);
155 return res;
156 }
157
158 static nmod_polyxx_expression randtest_irreducible(mp_limb_t n,
159 frandxx& state, slong len)
160 {
161 nmod_polyxx_expression res(n);
162 res.set_randtest_irreducible(state, len);
163 return res;
164 }
165
166 // these only make sense with immediates
167 void realloc(slong alloc) {nmod_poly_realloc(_poly(), alloc);}
168 void fit_length(slong len) {nmod_poly_fit_length(_poly(), len);}
169 void _normalise() {_nmod_poly_normalise(_poly());}
170 nmodxx_ctx_srcref _ctx() const
171 {return nmodxx_ctx_srcref::make(_poly()->mod);}
172 void set_zero() {nmod_poly_zero(_poly());}
173 void set_one() {nmod_poly_one(_poly());}
174
175 // These only make sense with target immediates
176 void set_coeff(slong n, ulong c) {nmod_poly_set_coeff_ui(_poly(), n, c);}
177 template<class Nmod>
178 typename mp::enable_if<traits::is_nmodxx<Nmod> >::type
179 set_coeff(slong j, const Nmod& c)
180 {
181 // TODO this does not need reduction
182 nmod_poly_set_coeff_ui(_poly(), j, c.template to<mp_limb_t>());
183 }
184 void truncate(slong n) {nmod_poly_truncate(_poly(), n);}
185
186 void set_randtest(frandxx& state, slong len)
187 {nmod_poly_randtest(_poly(), state._data(), len);}
188 void set_randtest_irreducible(frandxx& state, slong len)
189 {nmod_poly_randtest_irreducible(_poly(), state._data(), len);}
190
191 template<class Poly>
192 slong remove(const Poly& p)
193 {
194 return nmod_poly_remove(_poly(), p.evaluate()._poly());
195 }
196
197 // These work on any expression without evaluation
198 nmodxx_ctx_srcref estimate_ctx() const;
199 mp_limb_t modulus() const {return estimate_ctx().n();}
200
201 evaluated_t create_temporary() const
202 {
203 return evaluated_t(estimate_ctx());
204 }
205
206 // These cause evaluation
207 slong length() const {return nmod_poly_length(this->evaluate()._poly());}
208 slong degree() const {return nmod_poly_degree(this->evaluate()._poly());}
209 bool is_one() const {return nmod_poly_is_one(this->evaluate()._poly());}
210 bool is_zero() const {return nmod_poly_is_zero(this->evaluate()._poly());}
211 bool is_squarefree() const
212 {return nmod_poly_is_squarefree(this->evaluate()._poly());}
213 bool is_irreducible() const
214 {return nmod_poly_is_irreducible(this->evaluate()._poly());}
215 slong max_bits() const {return nmod_poly_max_bits(this->evaluate()._poly());}
216 ulong deflation() const
217 {return nmod_poly_deflation(this->evaluate()._poly());}
218
219 // Lazy members
220 FLINTXX_DEFINE_MEMBER_BINOP_(get_coeff, nmod_polyxx_get_coeff)
221 FLINTXX_DEFINE_MEMBER_BINOP_(operator(), compeval)
222 FLINTXX_DEFINE_MEMBER_BINOP(inflate)
223 FLINTXX_DEFINE_MEMBER_BINOP(deflate)
224
225 FLINTXX_DEFINE_MEMBER_BINOP(compose_divconquer)
226 FLINTXX_DEFINE_MEMBER_BINOP(compose_horner)
227 FLINTXX_DEFINE_MEMBER_BINOP(div_basecase)
228 FLINTXX_DEFINE_MEMBER_BINOP(div_divconquer)
229 FLINTXX_DEFINE_MEMBER_BINOP(div_newton)
230 FLINTXX_DEFINE_MEMBER_BINOP(divrem)
231 FLINTXX_DEFINE_MEMBER_BINOP(divrem_basecase)
232 FLINTXX_DEFINE_MEMBER_BINOP(divrem_divconquer)
233 FLINTXX_DEFINE_MEMBER_BINOP(divrem_newton)
234 FLINTXX_DEFINE_MEMBER_BINOP(div_root)
235 FLINTXX_DEFINE_MEMBER_BINOP(evaluate_fast)
236 FLINTXX_DEFINE_MEMBER_BINOP(evaluate_iter)
237 FLINTXX_DEFINE_MEMBER_BINOP(gcd)
238 FLINTXX_DEFINE_MEMBER_BINOP(gcd_euclidean)
239 FLINTXX_DEFINE_MEMBER_BINOP(gcd_hgcd)
240 FLINTXX_DEFINE_MEMBER_BINOP(inv_series)
241 FLINTXX_DEFINE_MEMBER_BINOP(inv_series_basecase)
242 FLINTXX_DEFINE_MEMBER_BINOP(inv_series_newton)
243 FLINTXX_DEFINE_MEMBER_BINOP(invsqrt_series)
244 FLINTXX_DEFINE_MEMBER_BINOP(mul_classical)
245 FLINTXX_DEFINE_MEMBER_BINOP(mul_KS)
246 FLINTXX_DEFINE_MEMBER_BINOP(shift_left)
247 FLINTXX_DEFINE_MEMBER_BINOP(shift_right)
248 FLINTXX_DEFINE_MEMBER_BINOP(pow)
249 FLINTXX_DEFINE_MEMBER_BINOP(pow_binexp)
250 FLINTXX_DEFINE_MEMBER_BINOP(rem_basecase)
251 FLINTXX_DEFINE_MEMBER_BINOP(resultant)
252 FLINTXX_DEFINE_MEMBER_BINOP(resultant_euclidean)
253 FLINTXX_DEFINE_MEMBER_BINOP(reverse)
254 FLINTXX_DEFINE_MEMBER_BINOP(revert_series)
255 FLINTXX_DEFINE_MEMBER_BINOP(revert_series_lagrange)
256 FLINTXX_DEFINE_MEMBER_BINOP(revert_series_lagrange_fast)
257 FLINTXX_DEFINE_MEMBER_BINOP(revert_series_newton)
258 FLINTXX_DEFINE_MEMBER_BINOP(sqrt_series)
259 FLINTXX_DEFINE_MEMBER_BINOP(taylor_shift)
260 FLINTXX_DEFINE_MEMBER_BINOP(taylor_shift_convolution)
261 FLINTXX_DEFINE_MEMBER_BINOP(taylor_shift_horner)
262 FLINTXX_DEFINE_MEMBER_BINOP(xgcd)
263 FLINTXX_DEFINE_MEMBER_BINOP(xgcd_euclidean)
264 FLINTXX_DEFINE_MEMBER_BINOP(xgcd_hgcd)
265 FLINTXX_DEFINE_MEMBER_BINOP(log_series)
266 FLINTXX_DEFINE_MEMBER_BINOP(exp_series)
267 FLINTXX_DEFINE_MEMBER_BINOP(exp_series_basecase)
268 FLINTXX_DEFINE_MEMBER_BINOP(atan_series)
269 FLINTXX_DEFINE_MEMBER_BINOP(atanh_series)
270 FLINTXX_DEFINE_MEMBER_BINOP(asin_series)
271 FLINTXX_DEFINE_MEMBER_BINOP(asinh_series)
272 FLINTXX_DEFINE_MEMBER_BINOP(sin_series)
273 FLINTXX_DEFINE_MEMBER_BINOP(cos_series)
274 FLINTXX_DEFINE_MEMBER_BINOP(tan_series)
275 FLINTXX_DEFINE_MEMBER_BINOP(sinh_series)
276 FLINTXX_DEFINE_MEMBER_BINOP(cosh_series)
277 FLINTXX_DEFINE_MEMBER_BINOP(tanh_series)
278
279 FLINTXX_DEFINE_MEMBER_BINOP(bit_pack)
280
281 FLINTXX_DEFINE_MEMBER_UNOP(derivative)
282 FLINTXX_DEFINE_MEMBER_UNOP(integral)
283 FLINTXX_DEFINE_MEMBER_UNOP(make_monic)
284 FLINTXX_DEFINE_MEMBER_UNOP(sqrt)
285
286 FLINTXX_DEFINE_MEMBER_3OP(compose_mod)
287 FLINTXX_DEFINE_MEMBER_3OP(compose_mod_horner)
288 FLINTXX_DEFINE_MEMBER_3OP(compose_mod_brent_kung)
289 FLINTXX_DEFINE_MEMBER_3OP(compose_series)
290 FLINTXX_DEFINE_MEMBER_3OP(compose_series_brent_kung)
291 FLINTXX_DEFINE_MEMBER_3OP(compose_series_divconquer)
292 FLINTXX_DEFINE_MEMBER_3OP(compose_series_horner)
293 FLINTXX_DEFINE_MEMBER_3OP(div_newton_n_preinv)
294 FLINTXX_DEFINE_MEMBER_3OP(divrem_newton_n_preinv)
295 FLINTXX_DEFINE_MEMBER_3OP(div_series)
296 FLINTXX_DEFINE_MEMBER_3OP(mulhigh)
297 FLINTXX_DEFINE_MEMBER_3OP(mulhigh_classical)
298 FLINTXX_DEFINE_MEMBER_3OP(mullow)
299 FLINTXX_DEFINE_MEMBER_3OP(mullow_classical)
300 FLINTXX_DEFINE_MEMBER_3OP(mullow_KS)
301 FLINTXX_DEFINE_MEMBER_3OP(mulmod)
302 FLINTXX_DEFINE_MEMBER_3OP(powmod_binexp)
303 FLINTXX_DEFINE_MEMBER_3OP(pow_trunc)
304 FLINTXX_DEFINE_MEMBER_3OP(pow_trunc_binexp)
305
306 FLINTXX_DEFINE_MEMBER_4OP(compose_mod_brent_kung_preinv)
307 FLINTXX_DEFINE_MEMBER_4OP(mulmod_preinv)
308 FLINTXX_DEFINE_MEMBER_4OP(powmod_binexp_preinv)
309 };
310
311 namespace detail {
312 struct nmod_poly_data;
313 }
314
315 typedef nmod_polyxx_expression<operations::immediate, detail::nmod_poly_data>
316 nmod_polyxx;
317 typedef nmod_polyxx_expression<operations::immediate,
318 flint_classes::ref_data<nmod_polyxx, nmod_poly_struct> >
319 nmod_polyxx_ref;
320 typedef nmod_polyxx_expression<operations::immediate,
321 flint_classes::srcref_data<
322 nmod_polyxx, nmod_polyxx_ref, nmod_poly_struct> >
323 nmod_polyxx_srcref;
324
325 namespace detail {
326 struct nmod_poly_data
327 {
328 nmod_poly_t inner;
329 typedef nmod_poly_t& data_ref_t;
330 typedef const nmod_poly_t& data_srcref_t;
331
nmod_poly_datanmod_poly_data332 nmod_poly_data(mp_limb_t n) {nmod_poly_init(inner, n);}
nmod_poly_datanmod_poly_data333 nmod_poly_data(nmodxx_ctx_srcref c)
334 {
335 nmod_poly_init_preinv(inner, c.n(), c._nmod().ninv);
336 }
nmod_poly_datanmod_poly_data337 nmod_poly_data(mp_limb_t n, slong alloc) {nmod_poly_init2(inner, n, alloc);}
nmod_poly_datanmod_poly_data338 nmod_poly_data(nmodxx_ctx_srcref c, slong alloc)
339 {
340 nmod_poly_init2_preinv(inner, c.n(), c._nmod().ninv, alloc);
341 }
~nmod_poly_datanmod_poly_data342 ~nmod_poly_data() {nmod_poly_clear(inner);}
343
nmod_poly_datanmod_poly_data344 nmod_poly_data(const nmod_poly_data& o)
345 {
346 nmod_poly_init2_preinv(inner, o.inner->mod.n,
347 o.inner->mod.ninv, o.inner->length);
348 nmod_poly_set(inner, o.inner);
349 }
350
nmod_poly_datanmod_poly_data351 nmod_poly_data(nmod_polyxx_srcref r)
352 {
353 nmod_poly_init2_preinv(inner, r.modulus(),
354 r._poly()->mod.ninv, r.length());
355 nmod_poly_set(inner, r._poly());
356 }
357
nmod_poly_datanmod_poly_data358 nmod_poly_data(const char* str)
359 {
360 mp_limb_t n;slong length;
361 execution_check(flint_sscanf(str, "%wd %wu", &length, &n) == 2
362 && (nmod_poly_init2(inner, n, length), nmod_poly_set_str(inner, str)),
363 "construct from string", "nmod_polyxx");
364 }
365
366 template<class Nmod>
367 static nmod_poly_data from_ground(const Nmod& x,
368 typename mp::enable_if<traits::is_nmodxx<Nmod> >::type* = 0)
369 {
370 nmod_poly_data res(x.estimate_ctx());
371 nmod_poly_set_coeff_ui(res.inner, 0, x.template to<mp_limb_t>());
372 return res;
373 }
from_groundnmod_poly_data374 static nmod_poly_data from_ground(mp_limb_t x, nmodxx_ctx_srcref c)
375 {
376 nmod_poly_data res(c);
377 nmod_poly_set_coeff_ui(res.inner, 0, x);
378 return res;
379 }
380
381 // TODO maybe make these lazy
382 template<class Fmpz_poly>
383 static nmod_poly_data reduce(const Fmpz_poly& p, nmodxx_ctx_srcref c,
384 typename mp::enable_if<traits::is_fmpz_polyxx<Fmpz_poly> >::type* = 0)
385 {
386 nmod_poly_data res(c);
387 fmpz_poly_get_nmod_poly(res.inner, p.evaluate()._poly());
388 return res;
389 }
390 template<class Fmpz_poly>
391 static nmod_poly_data reduce(const Fmpz_poly& p, mp_limb_t m,
392 typename mp::enable_if<traits::is_fmpz_polyxx<Fmpz_poly> >::type* = 0)
393 {
394 nmod_poly_data res(m);
395 fmpz_poly_get_nmod_poly(res.inner, p.evaluate()._poly());
396 return res;
397 }
398
399 template<class Fmpq_poly>
400 static nmod_poly_data reduce_(const Fmpq_poly& p, nmodxx_ctx_srcref c,
401 typename mp::enable_if<traits::is_fmpq_polyxx<Fmpq_poly> >::type* = 0)
402 {
403 nmod_poly_data res(c, p.length());
404 for(slong i = 0;i < p.length();++i)
405 nmod_poly_set_coeff_ui(res. inner, i,
406 nmodxx::red(p.get_coeff(i), c).template to<mp_limb_t>());
407 return res;
408 }
409 template<class Fmpq_poly>
410 static nmod_poly_data reduce(const Fmpq_poly& p, nmodxx_ctx_srcref c,
411 typename mp::enable_if<traits::is_fmpq_polyxx<Fmpq_poly> >::type* = 0)
412 {
413 return reduce_(p.evaluate(), c);
414 }
415 template<class Fmpq_poly>
416 static nmod_poly_data reduce(const Fmpq_poly& p, mp_limb_t m,
417 typename mp::enable_if<traits::is_fmpq_polyxx<Fmpq_poly> >::type* = 0)
418 {
419 return reduce_(p.evaluate(), nmodxx_ctx(m));
420 }
421 };
422 } // detail
423 namespace traits {
424 template<> struct has_nmodxx_ctx<nmod_polyxx> : mp::true_ { };
425 template<> struct has_nmodxx_ctx<nmod_polyxx_ref> : mp::true_ { };
426 template<> struct has_nmodxx_ctx<nmod_polyxx_srcref> : mp::true_ { };
427
428 template<class T> struct is_nmod_polyxx : mp::or_<
429 traits::is_T_expr<T, nmod_polyxx>,
430 flint_classes::is_source<nmod_polyxx, T> > { };
431 } // traits
432 template<class Operation, class Data>
433 inline nmodxx_ctx_srcref
434 nmod_polyxx_expression<Operation, Data>::estimate_ctx() const
435 {
436 return tools::find_nmodxx_ctx(*this);
437 }
438
439 namespace rules {
440 #define NMOD_POLYXX_COND_S FLINTXX_COND_S(nmod_polyxx)
441 #define NMOD_POLYXX_COND_T FLINTXX_COND_T(nmod_polyxx)
442
443 NMODXX_DEFINE_INSTANTIATE_TEMPORARIES(nmod_polyxx)
444
445 FLINT_DEFINE_DOIT_COND2(assignment, NMOD_POLYXX_COND_T, NMOD_POLYXX_COND_S,
446 nmod_poly_set(to._poly(), from._poly()))
447
448 FLINTXX_DEFINE_ASSIGN_STR(nmod_polyxx, execution_check(
449 nmod_poly_set_str(to._poly(), from), "assign string", "nmod_polyxx"))
450
451 FLINT_DEFINE_PRINT_COND(NMOD_POLYXX_COND_S, nmod_poly_fprint(to, from._poly()))
452 FLINT_DEFINE_READ_COND(NMOD_POLYXX_COND_T, nmod_poly_fread(from, to._poly()))
453
454 FLINTXX_DEFINE_EQUALS(nmod_polyxx, nmod_poly_equal(e1._poly(), e2._poly()))
455 FLINTXX_DEFINE_TO_STR(nmod_polyxx, nmod_poly_get_str(from._poly()))
456 FLINTXX_DEFINE_SWAP(nmod_polyxx, nmod_poly_swap(e1._poly(), e2._poly()))
457
458 FLINT_DEFINE_BINARY_EXPR_COND2(nmod_polyxx_get_coeff_op, nmodxx,
459 NMOD_POLYXX_COND_S, traits::fits_into_slong,
460 to.set_nored(nmod_poly_get_coeff_ui(e1._poly(), e2)))
461
462 FLINT_DEFINE_BINARY_EXPR_COND2(plus, nmod_polyxx,
463 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
464 nmod_poly_add(to._poly(), e1._poly(), e2._poly()))
465 FLINT_DEFINE_BINARY_EXPR_COND2(minus, nmod_polyxx,
466 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
467 nmod_poly_sub(to._poly(), e1._poly(), e2._poly()))
468
469 FLINT_DEFINE_UNARY_EXPR_COND(negate, nmod_polyxx, NMOD_POLYXX_COND_S,
470 nmod_poly_neg(to._poly(), from._poly()))
471
472 FLINT_DEFINE_BINARY_EXPR_COND2(reverse_op, nmod_polyxx,
473 NMOD_POLYXX_COND_S, traits::fits_into_slong,
474 nmod_poly_reverse(to._poly(), e1._poly(), e2))
475
476 FLINT_DEFINE_BINARY_EXPR_COND2(shift_left_op, nmod_polyxx,
477 NMOD_POLYXX_COND_S, traits::fits_into_slong,
478 nmod_poly_shift_left(to._poly(), e1._poly(), e2))
479 FLINT_DEFINE_BINARY_EXPR_COND2(shift_right_op, nmod_polyxx,
480 NMOD_POLYXX_COND_S, traits::fits_into_slong,
481 nmod_poly_shift_right(to._poly(), e1._poly(), e2))
482
483 FLINT_DEFINE_CBINARY_EXPR_COND2(times, nmod_polyxx,
484 NMOD_POLYXX_COND_S, NMODXX_COND_S,
485 nmod_poly_scalar_mul_nmod(to._poly(), e1._poly(), e2._limb()))
486 FLINT_DEFINE_UNARY_EXPR_COND(make_monic_op, nmod_polyxx, NMOD_POLYXX_COND_S,
487 nmod_poly_make_monic(to._poly(), from._poly()))
488
489 FLINT_DEFINE_BINARY_EXPR_COND2(bit_pack_op, fmpzxx,
490 NMOD_POLYXX_COND_S, traits::fits_into_flint_bitcnt_t,
491 nmod_poly_bit_pack(to._fmpz(), e1._poly(), e2))
492
493 FLINT_DEFINE_BINARY_EXPR_COND2(times, nmod_polyxx,
494 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
495 nmod_poly_mul(to._poly(), e1._poly(), e2._poly()))
496 FLINT_DEFINE_BINARY_EXPR_COND2(mul_classical_op, nmod_polyxx,
497 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
498 nmod_poly_mul_classical(to._poly(), e1._poly(), e2._poly()))
499 FLINT_DEFINE_BINARY_EXPR_COND2(mul_KS_op, nmod_polyxx,
500 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
501 nmod_poly_mul_KS(to._poly(), e1._poly(), e2._poly(), 0 /* TODO */))
502
503 #define NMOD_POLYXX_DEFINE_MULFUNC(name) \
504 FLINT_DEFINE_THREEARY_EXPR_COND3(name##_op, nmod_polyxx, \
505 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, traits::fits_into_slong, \
506 nmod_poly_##name(to._poly(), e1._poly(), e2._poly(), e3))
507 NMOD_POLYXX_DEFINE_MULFUNC(mullow_classical)
508 NMOD_POLYXX_DEFINE_MULFUNC(mullow)
509 NMOD_POLYXX_DEFINE_MULFUNC(mulhigh_classical)
510 NMOD_POLYXX_DEFINE_MULFUNC(mulhigh)
511
512 FLINT_DEFINE_THREEARY_EXPR_COND3(mullow_KS_op, nmod_polyxx,
513 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, traits::fits_into_slong,
514 nmod_poly_mullow_KS(to._poly(), e1._poly(), e2._poly(), 0 /* TODO */, e3))
515
516 FLINT_DEFINE_THREEARY_EXPR_COND3(mulmod_op, nmod_polyxx,
517 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
518 nmod_poly_mulmod(to._poly(), e1._poly(), e2._poly(), e3._poly()))
519
520 FLINT_DEFINE_FOURARY_EXPR_COND4(mulmod_preinv_op, nmod_polyxx,
521 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
522 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
523 nmod_poly_mulmod_preinv(to._poly(), e1._poly(), e2._poly(),
524 e3._poly(), e4._poly()))
525
526 FLINT_DEFINE_BINARY_EXPR_COND2(pow_binexp_op, nmod_polyxx,
527 NMOD_POLYXX_COND_S, traits::is_unsigned_integer,
528 nmod_poly_pow_binexp(to._poly(), e1._poly(), e2))
529 FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, nmod_polyxx,
530 NMOD_POLYXX_COND_S, traits::is_unsigned_integer,
531 nmod_poly_pow(to._poly(), e1._poly(), e2))
532
533 FLINT_DEFINE_THREEARY_EXPR_COND3(powmod_binexp_op, nmod_polyxx,
534 NMOD_POLYXX_COND_S, traits::is_unsigned_integer, NMOD_POLYXX_COND_S,
535 nmod_poly_powmod_ui_binexp(to._poly(), e1._poly(), e2, e3._poly()))
536
537 FLINT_DEFINE_FOURARY_EXPR_COND4(powmod_binexp_preinv_op, nmod_polyxx,
538 NMOD_POLYXX_COND_S, traits::is_unsigned_integer,
539 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
540 nmod_poly_powmod_ui_binexp_preinv(to._poly(), e1._poly(), e2,
541 e3._poly(), e4._poly()))
542
543 FLINT_DEFINE_THREEARY_EXPR_COND3(pow_trunc_op, nmod_polyxx,
544 NMOD_POLYXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong,
545 nmod_poly_pow_trunc(to._poly(), e1._poly(), e2, e3))
546 FLINT_DEFINE_THREEARY_EXPR_COND3(pow_trunc_binexp_op, nmod_polyxx,
547 NMOD_POLYXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong,
548 nmod_poly_pow_trunc_binexp(to._poly(), e1._poly(), e2, e3))
549
550 FLINT_DEFINE_UNARY_EXPR_COND(derivative_op, nmod_polyxx, NMOD_POLYXX_COND_S,
551 nmod_poly_derivative(to._poly(), from._poly()))
552 FLINT_DEFINE_UNARY_EXPR_COND(integral_op, nmod_polyxx, NMOD_POLYXX_COND_S,
553 nmod_poly_integral(to._poly(), from._poly()))
554
555 FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, nmodxx,
556 NMOD_POLYXX_COND_S, NMODXX_COND_S,
557 to.set_nored(nmod_poly_evaluate_nmod(e1._poly(), e2._limb())))
558
559 FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, nmod_vecxx,
560 NMOD_POLYXX_COND_S, NMOD_VECXX_COND_S,
561 nmod_poly_evaluate_nmod_vec(to._array(), e1._poly(), e2._array(),
562 to.size()))
563 FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_fast_op, nmod_vecxx,
564 NMOD_POLYXX_COND_S, NMOD_VECXX_COND_S,
565 nmod_poly_evaluate_nmod_vec_fast(to._array(), e1._poly(), e2._array(),
566 to.size()))
567 FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_iter_op, nmod_vecxx,
568 NMOD_POLYXX_COND_S, NMOD_VECXX_COND_S,
569 nmod_poly_evaluate_nmod_vec_iter(to._array(), e1._poly(), e2._array(),
570 to.size()))
571
572 namespace rdetail {
573 typedef make_ltuple<mp::make_tuple<nmod_polyxx, nmod_polyxx>::type>::type
574 nmod_polyxx_pair;
575 } // rdetail
576 #define NMOD_POLYXX_DEFINE_DIVREM(name) \
577 FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, rdetail::nmod_polyxx_pair, \
578 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, \
579 nmod_poly_##name(to.template get<0>()._poly(), to.template get<1>()._poly(), \
580 e1._poly(), e2._poly()))
581 NMOD_POLYXX_DEFINE_DIVREM(divrem_basecase)
582 NMOD_POLYXX_DEFINE_DIVREM(divrem_divconquer)
583 NMOD_POLYXX_DEFINE_DIVREM(divrem_newton)
584 NMOD_POLYXX_DEFINE_DIVREM(divrem)
585
586 FLINT_DEFINE_BINARY_EXPR_COND2(div_basecase_op, nmod_polyxx,
587 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
588 nmod_poly_div_basecase(to._poly(), e1._poly(), e2._poly()))
589 FLINT_DEFINE_BINARY_EXPR_COND2(div_divconquer_op, nmod_polyxx,
590 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
591 nmod_poly_div_divconquer(to._poly(), e1._poly(), e2._poly()))
592 FLINT_DEFINE_BINARY_EXPR_COND2(div_newton_op, nmod_polyxx,
593 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
594 nmod_poly_div_newton(to._poly(), e1._poly(), e2._poly()))
595 FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, nmod_polyxx,
596 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
597 nmod_poly_div_divconquer(to._poly(), e1._poly(), e2._poly()))
598
599 FLINT_DEFINE_THREEARY_EXPR_COND3(div_newton_n_preinv_op, nmod_polyxx,
600 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
601 nmod_poly_div_newton_n_preinv(to._poly(),
602 e1._poly(), e2._poly(), e3._poly()))
603 FLINT_DEFINE_THREEARY_EXPR_COND3(divrem_newton_n_preinv_op,
604 rdetail::nmod_polyxx_pair,
605 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
606 nmod_poly_divrem_newton_n_preinv(to.template get<0>()._poly(),
607 to.template get<1>()._poly(), e1._poly(), e2._poly(), e3._poly()))
608
609 FLINT_DEFINE_BINARY_EXPR_COND2(rem_basecase_op, nmod_polyxx,
610 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
611 nmod_poly_rem_basecase(to._poly(), e1._poly(), e2._poly()))
612 FLINT_DEFINE_BINARY_EXPR_COND2(modulo, nmod_polyxx,
613 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
614 nmod_poly_rem(to._poly(), e1._poly(), e2._poly()))
615
616 FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_newton_op, nmod_polyxx,
617 NMOD_POLYXX_COND_S, traits::fits_into_slong,
618 nmod_poly_inv_series_newton(to._poly(), e1._poly(), e2))
619 FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_op, nmod_polyxx,
620 NMOD_POLYXX_COND_S, traits::fits_into_slong,
621 nmod_poly_inv_series(to._poly(), e1._poly(), e2))
622 FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_basecase_op, nmod_polyxx,
623 NMOD_POLYXX_COND_S, traits::fits_into_slong,
624 nmod_poly_inv_series_basecase(to._poly(), e1._poly(), e2))
625
626 #define NMOD_POLYXX_DEFINE_SERIES(name) \
627 FLINT_DEFINE_THREEARY_EXPR_COND3(name##_op, nmod_polyxx, \
628 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, traits::fits_into_slong, \
629 nmod_poly_##name(to._poly(), e1._poly(), e2._poly(), e3))
630 NMOD_POLYXX_DEFINE_SERIES(div_series)
631
632 FLINT_DEFINE_BINARY_EXPR_COND2(compose_op, nmod_polyxx,
633 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
634 nmod_poly_compose(to._poly(), e1._poly(), e2._poly()))
635 FLINT_DEFINE_BINARY_EXPR_COND2(compose_divconquer_op, nmod_polyxx,
636 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
637 nmod_poly_compose_divconquer(to._poly(), e1._poly(), e2._poly()))
638 FLINT_DEFINE_BINARY_EXPR_COND2(compose_horner_op, nmod_polyxx,
639 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
640 nmod_poly_compose_horner(to._poly(), e1._poly(), e2._poly()))
641
642 FLINT_DEFINE_BINARY_EXPR_COND2(div_root_op, nmod_polyxx,
643 NMOD_POLYXX_COND_S, NMODXX_COND_S,
644 nmod_poly_div_root(to._poly(), e1._poly(), e2._limb()))
645
646 FLINT_DEFINE_BINARY_EXPR_COND2(nmod_polyxx_interpolate_op, nmod_polyxx,
647 NMOD_VECXX_COND_S, NMOD_VECXX_COND_S,
648 nmod_poly_interpolate_nmod_vec(to._poly(), e1._data().array,
649 e2._data().array, e2.size()))
650 FLINT_DEFINE_BINARY_EXPR_COND2(nmod_polyxx_interpolate_fast_op, nmod_polyxx,
651 NMOD_VECXX_COND_S, NMOD_VECXX_COND_S,
652 nmod_poly_interpolate_nmod_vec_fast(to._poly(), e1._data().array,
653 e2._data().array, e2.size()))
654 FLINT_DEFINE_BINARY_EXPR_COND2(nmod_polyxx_interpolate_newton_op, nmod_polyxx,
655 NMOD_VECXX_COND_S, NMOD_VECXX_COND_S,
656 nmod_poly_interpolate_nmod_vec_newton(to._poly(), e1._data().array,
657 e2._data().array, e2.size()))
658 FLINT_DEFINE_BINARY_EXPR_COND2(nmod_polyxx_interpolate_barycentric_op, nmod_polyxx,
659 NMOD_VECXX_COND_S, NMOD_VECXX_COND_S,
660 nmod_poly_interpolate_nmod_vec_barycentric(to._poly(), e1._data().array,
661 e2._data().array, e2.size()))
662
663 FLINT_DEFINE_BINARY_EXPR_COND2(taylor_shift_horner_op, nmod_polyxx,
664 NMOD_POLYXX_COND_S, NMODXX_COND_S,
665 nmod_poly_taylor_shift_horner(to._poly(), e1._poly(), e2._limb()))
666 FLINT_DEFINE_BINARY_EXPR_COND2(taylor_shift_convolution_op, nmod_polyxx,
667 NMOD_POLYXX_COND_S, NMODXX_COND_S,
668 nmod_poly_taylor_shift_convolution(to._poly(), e1._poly(), e2._limb()))
669 FLINT_DEFINE_BINARY_EXPR_COND2(taylor_shift_op, nmod_polyxx,
670 NMOD_POLYXX_COND_S, NMODXX_COND_S,
671 nmod_poly_taylor_shift(to._poly(), e1._poly(), e2._limb()))
672
673 FLINT_DEFINE_THREEARY_EXPR_COND3(compose_mod_op, nmod_polyxx,
674 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
675 nmod_poly_compose_mod(to._poly(), e1._poly(), e2._poly(), e3._poly()))
676 FLINT_DEFINE_THREEARY_EXPR_COND3(compose_mod_horner_op, nmod_polyxx,
677 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
678 nmod_poly_compose_mod_horner(
679 to._poly(), e1._poly(), e2._poly(), e3._poly()))
680 FLINT_DEFINE_THREEARY_EXPR_COND3(compose_mod_brent_kung_op, nmod_polyxx,
681 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
682 nmod_poly_compose_mod_brent_kung(
683 to._poly(), e1._poly(), e2._poly(), e3._poly()))
684 FLINT_DEFINE_FOURARY_EXPR_COND4(compose_mod_brent_kung_preinv_op, nmod_polyxx,
685 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
686 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
687 nmod_poly_compose_mod_brent_kung_preinv(
688 to._poly(), e1._poly(), e2._poly(), e3._poly(), e4._poly()))
689
690 FLINT_DEFINE_BINARY_EXPR_COND2(gcd_op, nmod_polyxx,
691 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
692 nmod_poly_gcd(to._poly(), e1._poly(), e2._poly()))
693 FLINT_DEFINE_BINARY_EXPR_COND2(gcd_hgcd_op, nmod_polyxx,
694 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
695 nmod_poly_gcd_hgcd(to._poly(), e1._poly(), e2._poly()))
696 FLINT_DEFINE_BINARY_EXPR_COND2(gcd_euclidean_op, nmod_polyxx,
697 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
698 nmod_poly_gcd_euclidean(to._poly(), e1._poly(), e2._poly()))
699
700 namespace rdetail {
701 typedef make_ltuple<mp::make_tuple<nmod_polyxx, nmod_polyxx, nmod_polyxx>::type>::type
702 nmod_polyxx_triple;
703 } // rdetail
704 FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_op, rdetail::nmod_polyxx_triple,
705 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
706 nmod_poly_xgcd(to.template get<0>()._poly(), to.template get<1>()._poly(),
707 to.template get<2>()._poly(), e1._poly(), e2._poly()))
708 FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_hgcd_op, rdetail::nmod_polyxx_triple,
709 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
710 nmod_poly_xgcd_hgcd(to.template get<0>()._poly(),
711 to.template get<1>()._poly(),
712 to.template get<2>()._poly(), e1._poly(), e2._poly()))
713 FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_euclidean_op, rdetail::nmod_polyxx_triple,
714 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
715 nmod_poly_xgcd_euclidean(to.template get<0>()._poly(),
716 to.template get<1>()._poly(),
717 to.template get<2>()._poly(), e1._poly(), e2._poly()))
718
719 FLINT_DEFINE_BINARY_EXPR_COND2(resultant_op, nmodxx,
720 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
721 to.set_nored(nmod_poly_resultant(e1._poly(), e2._poly())))
722 FLINT_DEFINE_BINARY_EXPR_COND2(resultant_euclidean_op, nmodxx,
723 NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S,
724 to.set_nored(nmod_poly_resultant_euclidean(e1._poly(), e2._poly())))
725
726 NMOD_POLYXX_DEFINE_SERIES(compose_series)
727 NMOD_POLYXX_DEFINE_SERIES(compose_series_horner)
728 NMOD_POLYXX_DEFINE_SERIES(compose_series_brent_kung)
729 NMOD_POLYXX_DEFINE_SERIES(compose_series_divconquer)
730
731 #define NMOD_POLYXX_DEFINE_SERIESUN(name) \
732 FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, nmod_polyxx, \
733 NMOD_POLYXX_COND_S, traits::fits_into_slong, \
734 nmod_poly_##name(to._poly(), e1._poly(), e2))
735 NMOD_POLYXX_DEFINE_SERIESUN(revert_series)
736 NMOD_POLYXX_DEFINE_SERIESUN(revert_series_newton)
737 NMOD_POLYXX_DEFINE_SERIESUN(revert_series_lagrange_fast)
738 NMOD_POLYXX_DEFINE_SERIESUN(revert_series_lagrange)
739
740 #define NMOD_POLYXX_DEFINE_SERIES_F(name) \
741 FLINT_DEFINE_BINARY_EXPR_COND2(name##_series_op, nmod_polyxx, \
742 NMOD_POLYXX_COND_S, traits::fits_into_slong, \
743 nmod_poly_##name##_series(to._poly(), e1._poly(), e2))
744 NMOD_POLYXX_DEFINE_SERIES_F(sqrt)
745 NMOD_POLYXX_DEFINE_SERIES_F(invsqrt)
746 NMOD_POLYXX_DEFINE_SERIES_F(log)
747 NMOD_POLYXX_DEFINE_SERIES_F(exp)
748 NMOD_POLYXX_DEFINE_SERIES_F(atan)
749 NMOD_POLYXX_DEFINE_SERIES_F(atanh)
750 NMOD_POLYXX_DEFINE_SERIES_F(asin)
751 NMOD_POLYXX_DEFINE_SERIES_F(asinh)
752 NMOD_POLYXX_DEFINE_SERIES_F(sin)
753 NMOD_POLYXX_DEFINE_SERIES_F(cos)
754 NMOD_POLYXX_DEFINE_SERIES_F(tan)
755 NMOD_POLYXX_DEFINE_SERIES_F(sinh)
756 NMOD_POLYXX_DEFINE_SERIES_F(cosh)
757 NMOD_POLYXX_DEFINE_SERIES_F(tanh)
758
759 FLINT_DEFINE_BINARY_EXPR_COND2(exp_series_basecase_op, nmod_polyxx,
760 NMOD_POLYXX_COND_S, traits::fits_into_slong,
761 nmod_poly_exp_series_basecase(to._poly(), e1._poly(), e2))
762
763 FLINT_DEFINE_THREEARY_EXPR_COND3(log_series_monomial_op, nmod_polyxx,
764 NMODXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong,
765 nmod_poly_log_series_monomial_ui(to._poly(), e1._limb(), e2, e3))
766 FLINT_DEFINE_THREEARY_EXPR_COND3(exp_series_monomial_op, nmod_polyxx,
767 NMODXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong,
768 nmod_poly_exp_series_monomial_ui(to._poly(), e1._limb(), e2, e3))
769
770 FLINT_DEFINE_UNARY_EXPR_COND(sqrt_op, nmod_polyxx, NMOD_POLYXX_COND_S,
771 execution_check(nmod_poly_sqrt(to._poly(), from._poly()),
772 "sqrt", "nmod_polyxx"))
773
774 FLINT_DEFINE_UNARY_EXPR_COND(nmod_polyxx_product_roots_op, nmod_polyxx,
775 NMOD_VECXX_COND_S,
776 nmod_poly_product_roots_nmod_vec(to._poly(),
777 from._data().array, from.size()))
778
779 FLINT_DEFINE_BINARY_EXPR_COND2(deflate_op, nmod_polyxx,
780 NMOD_POLYXX_COND_S, traits::is_unsigned_integer,
781 nmod_poly_deflate(to._poly(), e1._poly(), e2))
782 FLINT_DEFINE_BINARY_EXPR_COND2(inflate_op, nmod_polyxx,
783 NMOD_POLYXX_COND_S, traits::is_unsigned_integer,
784 nmod_poly_inflate(to._poly(), e1._poly(), e2))
785 } // rules
786
787
788 //////////////////////////////////////////////////////////////////////////////
789 // FACTORISATION
790 //////////////////////////////////////////////////////////////////////////////
791
792 class nmod_poly_factorxx
793 {
794 private:
795 nmod_poly_factor_t inner;
796
797 public:
798 nmod_poly_factorxx() {nmod_poly_factor_init(inner);}
799 ~nmod_poly_factorxx() {nmod_poly_factor_clear(inner);}
800
801 nmod_poly_factorxx(const nmod_poly_factorxx& o)
802 {
803 nmod_poly_factor_init(inner);
804 nmod_poly_factor_set(inner, o.inner);
805 }
806
807 bool operator==(const nmod_poly_factorxx& o)
808 {
809 if(o.size() != size())
810 return false;
811 for(slong i = 0;i < size();++i)
812 if(p(i) != o.p(i) || exp(i) != o.exp(i))
813 return false;
814 return true;
815 }
816
817 nmod_poly_factorxx& operator=(const nmod_poly_factorxx& o)
818 {
819 nmod_poly_factor_set(inner, o.inner);
820 return *this;
821 }
822
823 slong size() const {return inner->num;}
824 slong exp(slong i) const {return inner->exp[i];}
825 slong& exp(slong i) {return inner->exp[i];}
826 nmod_polyxx_srcref p(slong i) const
827 {return nmod_polyxx_srcref::make(inner->p + i);}
828 nmod_polyxx_ref p(slong i) {return nmod_polyxx_ref::make(inner->p + i);}
829
830 nmod_poly_factor_t& _data() {return inner;}
831 const nmod_poly_factor_t& _data() const {return inner;}
832
833 void realloc(slong a) {nmod_poly_factor_realloc(inner, a);}
834 void fit_length(slong a) {nmod_poly_factor_fit_length(inner, a);}
835
836 void print() const {nmod_poly_factor_print(inner);}
837
838 template<class Nmod_poly>
839 void insert(const Nmod_poly& p, slong e,
840 typename mp::enable_if<traits::is_nmod_polyxx<Nmod_poly> >::type* = 0)
841 {nmod_poly_factor_insert(_data(), p.evaluate()._poly(), e);}
842
843 void concat(const nmod_poly_factorxx& o)
844 {nmod_poly_factor_concat(_data(), o._data());}
845
846 void pow(slong exp) {nmod_poly_factor_pow(_data(), exp);}
847
848 #define NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(name) \
849 template<class Nmod_poly> \
850 void set_##name(const Nmod_poly& p, \
851 typename mp::enable_if<traits::is_nmod_polyxx<Nmod_poly> >::type* = 0) \
852 {nmod_poly_##name(_data(), p.evaluate()._poly());}
853
854 NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor)
855 NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_squarefree)
856 NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_cantor_zassenhaus)
857 NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_berlekamp)
858 NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_kaltofen_shoup)
859 NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_with_cantor_zassenhaus)
860 NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_with_berlekamp)
861 NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_with_kaltofen_shoup)
862
863 template<class Nmod_poly>
864 bool set_factor_equal_deg_probab(frandxx& state, const Nmod_poly& p, slong d,
865 typename mp::enable_if<traits::is_nmod_polyxx<Nmod_poly> >::type* = 0)
866 {
867 return nmod_poly_factor_equal_deg_prob(_data(), state._data(),
868 p.evaluate()._poly(), d);
869 }
870 template<class Nmod_poly>
871 void set_factor_equal_deg(const Nmod_poly& p, slong d,
872 typename mp::enable_if<traits::is_nmod_polyxx<Nmod_poly> >::type* = 0)
873 {
874 nmod_poly_factor_equal_deg(_data(), p.evaluate()._poly(), d);
875 }
876
877 template<class Nmod_poly>
878 void set_factor_distinct_deg(const Nmod_poly& p, std::vector<slong>& degs,
879 typename mp::enable_if<traits::is_nmod_polyxx<Nmod_poly> >::type* = 0)
880 {
881 slong* dgs = °s.front();
882 nmod_poly_factor_distinct_deg(_data(), p.evaluate()._poly(), &dgs);
883 }
884 };
885
886 #define NMOD_POLY_FACTORXX_DEFINE_FACTOR(name) \
887 template<class Nmod_poly> \
888 nmod_poly_factorxx name(const Nmod_poly& p, \
889 typename mp::enable_if<traits::is_nmod_polyxx<Nmod_poly> >::type* = 0) \
890 { \
891 nmod_poly_factorxx res; \
892 res.set_##name(p); \
893 return res; \
894 }
895 NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor)
896 NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_squarefree)
897 NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_cantor_zassenhaus)
898 NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_berlekamp)
899 NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_kaltofen_shoup)
900 NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_with_cantor_zassenhaus)
901 NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_with_berlekamp)
902 NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_with_kaltofen_shoup)
903
904 // TODO do we want global versions of factor_distinct_deg etc?
905
906 inline void print(const nmod_poly_factorxx& f)
907 {
908 f.print();
909 }
910
911
912 // CRT stuff
913 // Here for circular dependency reasons
914 namespace rules {
915 FLINT_DEFINE_FOURARY_EXPR_COND4(CRT_op, fmpz_polyxx,
916 FMPZ_POLYXX_COND_T, FMPZXX_COND_S, NMOD_POLYXX_COND_S, tools::is_bool,
917 fmpz_poly_CRT_ui(to._poly(), e1._poly(), e2._fmpz(), e3._poly(), e4))
918 } // rules
919 } // flint
920
921 #endif
922