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 PADIC_POLYXX_H
13 #define PADIC_POLYXX_H
14 
15 #include "padic_poly.h"
16 
17 #include "padicxx.h"
18 #include "fmpz_polyxx.h"
19 #include "fmpq_polyxx.h"
20 
21 #include "flintxx/stdmath.h"
22 
23 // TODO input and output
24 
25 namespace flint {
26 FLINT_DEFINE_BINOP(padic_polyxx_get_coeff)
FLINT_DEFINE_BINOP(compose_pow)27 FLINT_DEFINE_BINOP(compose_pow)
28 
29 namespace detail {
30 template<class Padic>
31 struct padic_poly_traits
32 {
33     typedef slong prec_ref_t;
34     typedef slong prec_srcref_t;
35 
36     typedef slong val_ref_t;
37     typedef slong val_srcref_t;
38 
39     static slong prec(const Padic& p) {return tools::padic_output_prec(p);}
40     static slong val(const Padic& p) {return padic_poly_val(p.evaluate()._poly());}
41 };
42 } //detail
43 
44 template<class Operation, class Data>
45 class padic_polyxx_expression
46     : public expression<derived_wrapper<padic_polyxx_expression>, Operation, Data>
47 {
48 public:
49     typedef expression<derived_wrapper< ::flint::padic_polyxx_expression>,
50               Operation, Data> base_t;
51 
52     FLINTXX_DEFINE_BASICS(padic_polyxx_expression)
53     FLINTXX_DEFINE_CTORS(padic_polyxx_expression)
54     FLINTXX_DEFINE_C_REF(padic_polyxx_expression, padic_poly_struct, _poly)
55 
56 public:
57     typedef detail::padic_poly_traits<padic_polyxx_expression> traits_t;
58 
59     PADICXX_DEFINE_STD
60 
zero(padicxx_ctx_srcref ctx)61     static padic_polyxx_expression zero(padicxx_ctx_srcref ctx)
62         {return padic_polyxx_expression(ctx);}
zero(padicxx_ctx_srcref ctx,slong N)63     static padic_polyxx_expression zero(padicxx_ctx_srcref ctx, slong N)
64         {return padic_polyxx_expression(ctx, N);}
one(padicxx_ctx_srcref ctx)65     static padic_polyxx_expression one(padicxx_ctx_srcref ctx)
66     {
67         padic_polyxx_expression res(ctx);
68         res.set_one();
69         return res;
70     }
one(padicxx_ctx_srcref ctx,slong N)71     static padic_polyxx_expression one(padicxx_ctx_srcref ctx, slong N)
72     {
73         padic_polyxx_expression res(ctx, N);
74         res.set_one();
75         return res;
76     }
77 
78     template<class T>
79     static padic_polyxx_expression from_QQ(const T& q, padicxx_ctx_srcref ctx,
80             typename mp::enable_if<mp::or_<traits::is_fmpqxx<T>,
81                 traits::is_fmpzxx<T>, traits::is_integer<T> > >::type* = 0)
82     {
83         padic_polyxx_expression res(ctx);
84         res = q;
85         return res;
86     }
87     template<class T>
88     static padic_polyxx_expression from_QQ(const T& q, padicxx_ctx_srcref ctx,
89             slong N,
90             typename mp::enable_if<mp::or_<traits::is_fmpqxx<T>,
91                 traits::is_fmpzxx<T>, traits::is_integer<T> > >::type* = 0)
92     {
93         padic_polyxx_expression res(ctx, N);
94         res = q;
95         return res;
96     }
97     template<class T>
98     static padic_polyxx_expression from_QQX(const T& q, padicxx_ctx_srcref ctx,
99             typename mp::enable_if<mp::or_<traits::is_fmpq_polyxx<T>,
100                 traits::is_fmpz_polyxx<T> > >::type* = 0)
101     {
102         padic_polyxx_expression res(ctx);
103         res = q;
104         return res;
105     }
106     template<class T>
107     static padic_polyxx_expression from_QQX(const T& q, padicxx_ctx_srcref ctx,
108             slong N,
109             typename mp::enable_if<mp::or_<traits::is_fmpq_polyxx<T>,
110                 traits::is_fmpz_polyxx<T> > >::type* = 0)
111     {
112         padic_polyxx_expression res(ctx, N);
113         res = q;
114         return res;
115     }
116     template<class T>
_from_ground(const T & q)117     static padic_polyxx_expression _from_ground(const T& q)
118     {
119         padic_polyxx_expression res(q.get_ctx(), q.prec());
120         res = q;
121         return res;
122     }
123     template<class T>
124     static padic_polyxx_expression from_ground(const T& q,
125             typename mp::enable_if<traits::is_padicxx<T> >::type* = 0)
126     {
127         return _from_ground(q.evaluate());
128     }
129 
130     // Create a temporary. The context will be estimated, and the precision
131     // will be the maximum of all subexpressions.
create_temporary()132     evaluated_t create_temporary() const
133     {
134         return evaluated_t(estimate_ctx(), prec());
135     }
136 
137     // static methods which only make sense with padicxx
138     static padic_polyxx_expression randtest(frandxx& state,
139             slong len,
140             padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC)
141     {
142         padic_polyxx_expression res(ctx, prec);
143         padic_poly_randtest(res._poly(), state._data(), len, ctx._ctx());
144         return res;
145     }
146     static padic_polyxx_expression randtest_not_zero(frandxx& state,
147             slong len,
148             padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC)
149     {
150         padic_polyxx_expression res(ctx, prec);
151         padic_poly_randtest_not_zero(res._poly(), state._data(), len, ctx._ctx());
152         return res;
153     }
154     static padic_polyxx_expression randtest_val(frandxx& state,
155             slong val, slong len,
156             padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC)
157     {
158         padic_polyxx_expression res(ctx, prec);
159         padic_poly_randtest_val(res._poly(), state._data(), val, len, ctx._ctx());
160         return res;
161     }
162 
163     // These only make sense with immediates
reduce()164     void reduce() {padic_poly_reduce(_poly(), _ctx());}
realloc(slong alloc)165     void realloc(slong alloc) {padic_poly_realloc(_poly(), alloc);}
fit_length(slong len)166     void fit_length(slong len) {padic_poly_fit_length(_poly(), len);}
_normalise()167     void _normalise() {_padic_poly_normalise(_poly());}
_set_length(slong len)168     void _set_length(slong len) {_padic_poly_set_length(_poly(), len);}
set_zero()169     void set_zero() {padic_poly_zero(_poly());}
set_one()170     void set_one() {padic_poly_one(_poly());}
truncate(slong n)171     void truncate(slong n) {fmpz_poly_truncate(_poly(), n);}
canonicalise()172     void canonicalise() {padic_poly_canonicalise(_poly());}
is_canonical()173     bool is_canonical() const {return padic_poly_is_canonical(_poly());}
is_reduced()174     bool is_reduced() const {return padic_poly_is_reduced(_poly());}
175 
176     template<class Padic>
177     void set_coeff(slong n, const Padic& p,
178             typename mp::enable_if<traits::is_padicxx<Padic> >::type* = 0)
179         {padic_poly_set_coeff_padic(_poly(), n, p._padic(), _ctx());}
180 
181     // these cause evaluation
is_zero()182     bool is_zero() const {return padic_poly_is_zero(this->evaluate()._poly());}
is_one()183     bool is_one() const {return padic_poly_is_one(this->evaluate()._poly());}
length()184     slong length() const {return padic_poly_length(this->evaluate()._poly());}
degree()185     slong degree() const {return padic_poly_degree(this->evaluate()._poly());}
186 
187     // forwarding of lazy functions
188     FLINTXX_DEFINE_MEMBER_BINOP_(get_coeff, padic_polyxx_get_coeff)
189     FLINTXX_DEFINE_MEMBER_BINOP_(operator(), compeval)
190     FLINTXX_DEFINE_MEMBER_BINOP(pow)
191     FLINTXX_DEFINE_MEMBER_BINOP(compose_pow)
192     FLINTXX_DEFINE_MEMBER_BINOP(inv_series)
193     FLINTXX_DEFINE_MEMBER_BINOP(shift_left)
194     FLINTXX_DEFINE_MEMBER_BINOP(shift_right)
195     FLINTXX_DEFINE_MEMBER_UNOP(derivative)
196 };
197 
198 namespace detail {
199 struct padic_poly_data;
200 }
201 
202 typedef padic_polyxx_expression<operations::immediate,
203             detail::padic_poly_data> padic_polyxx;
204 typedef padic_polyxx_expression<operations::immediate,
205             flint_classes::ref_data<padic_polyxx, padic_poly_struct> >
206                 padic_polyxx_ref;
207 typedef padic_polyxx_expression<operations::immediate, flint_classes::srcref_data<
208     padic_polyxx, padic_polyxx_ref, padic_poly_struct> > padic_polyxx_srcref;
209 
210 namespace traits {
211 template<> struct has_padicxx_ctx<padic_polyxx> : mp::true_ { };
212 template<> struct has_padicxx_ctx<padic_polyxx_ref> : mp::true_ { };
213 template<> struct has_padicxx_ctx<padic_polyxx_srcref> : mp::true_ { };
214 } // traits
215 
216 namespace detail {
217 template<>
218 struct padic_poly_traits<padic_polyxx_srcref>
219 {
220     typedef slong prec_ref_t;
221     typedef slong prec_srcref_t;
222 
223     typedef slong val_ref_t;
224     typedef slong val_srcref_t;
225 
226     template<class P>
227     static slong prec(P p) {return p._data().N;}
228     template<class P>
229     static slong val(P p) {return padic_poly_val(p._poly());}
230 };
231 
232 template<>
233 struct padic_poly_traits<padic_polyxx_ref>
234     : padic_poly_traits<padic_polyxx_srcref>
235 {
236     typedef slong& prec_ref_t;
237     typedef slong& val_ref_t;
238 
239     template<class P>
240     static slong& prec(P& p) {return padic_poly_prec(p._poly());}
241     template<class P>
242     static slong prec(const P& p) {return padic_poly_prec(p._poly());}
243 
244     template<class P>
245     static slong& val(P& p) {return padic_poly_val(p._poly());}
246     template<class P>
247     static slong val(const P& p) {return padic_poly_val(p._poly());}
248 };
249 template<>
250 struct padic_poly_traits<padic_polyxx>
251     : padic_poly_traits<padic_polyxx_ref> { };
252 } // detail
253 
254 PADICXX_DEFINE_REF_STRUCTS(padic_polyxx, padic_poly_struct, padic_poly_prec)
255 
256 namespace detail {
257 struct padic_poly_data
258 {
259     typedef padic_poly_t& data_ref_t;
260     typedef const padic_poly_t& data_srcref_t;
261 
262     padicxx_ctx_srcref ctx;
263     padic_poly_t inner;
264 
265     padic_poly_data(padicxx_ctx_srcref c)
266         : ctx(c)
267     {
268         padic_poly_init(inner);
269     }
270 
271     padic_poly_data(padicxx_ctx_srcref c, slong N, slong alloc = 0)
272         : ctx(c)
273     {
274         padic_poly_init2(inner, alloc, N);
275     }
276 
277     padic_poly_data(const padic_poly_data& o)
278         : ctx(o.ctx)
279     {
280         padic_poly_init2(inner, padic_poly_length(o.inner),
281                 padic_poly_prec(o.inner));
282         padic_poly_set(inner, o.inner, ctx._ctx());
283     }
284 
285     ~padic_poly_data() {padic_poly_clear(inner);}
286 
287     padic_poly_data(padic_polyxx_srcref c)
288         : ctx(c.get_ctx())
289     {
290         padic_poly_init2(inner, c.length(), c.prec());
291         padic_poly_set(inner, c._poly(), ctx._ctx());
292     }
293 };
294 } // detail
295 
296 #define PADIC_POLYXX_COND_S FLINTXX_COND_S(padic_polyxx)
297 #define PADIC_POLYXX_COND_T FLINTXX_COND_T(padic_polyxx)
298 
299 namespace rules {
300 FLINT_DEFINE_DOIT_COND2(assignment, PADIC_POLYXX_COND_T, PADIC_POLYXX_COND_S,
301         padic_poly_set(to._poly(), from._poly(), to._ctx()))
302 FLINT_DEFINE_DOIT_COND2(assignment, PADIC_POLYXX_COND_T, PADICXX_COND_S,
303         padic_poly_set_padic(to._poly(), from._padic(), to._ctx()))
304 FLINT_DEFINE_DOIT_COND2(assignment, PADIC_POLYXX_COND_T, traits::is_signed_integer,
305         padic_poly_set_si(to._poly(), from, to._ctx()))
306 FLINT_DEFINE_DOIT_COND2(assignment, PADIC_POLYXX_COND_T, traits::is_unsigned_integer,
307         padic_poly_set_ui(to._poly(), from, to._ctx()))
308 FLINT_DEFINE_DOIT_COND2(assignment, PADIC_POLYXX_COND_T, FMPZXX_COND_S,
309         padic_poly_set_fmpz(to._poly(), from._fmpz(), to._ctx()))
310 FLINT_DEFINE_DOIT_COND2(assignment, PADIC_POLYXX_COND_T, FMPQXX_COND_S,
311         padic_poly_set_fmpq(to._poly(), from._fmpq(), to._ctx()))
312 FLINT_DEFINE_DOIT_COND2(assignment, PADIC_POLYXX_COND_T, FMPZ_POLYXX_COND_S,
313         padic_poly_set_fmpz_poly(to._poly(), from._poly(), to._ctx()))
314 FLINT_DEFINE_DOIT_COND2(assignment, PADIC_POLYXX_COND_T, FMPQ_POLYXX_COND_S,
315         padic_poly_set_fmpq_poly(to._poly(), from._poly(), to._ctx()))
316 
317 FLINTXX_DEFINE_SWAP(padic_polyxx, padic_poly_swap(e1._poly(), e2._poly()))
318 
319 FLINTXX_DEFINE_EQUALS(padic_polyxx, padic_poly_equal(e1._poly(), e2._poly()))
320 
321 FLINT_DEFINE_PRINT_COND(PADIC_POLYXX_COND_S,
322         padic_poly_fprint(to, from._poly(), from._ctx()))
323 FLINT_DEFINE_PRINT_PRETTY_COND_2(PADIC_POLYXX_COND_S, const char*,
324         padic_poly_fprint_pretty(to, from._poly(), extra, from._ctx()))
325 
326 FLINTXX_DEFINE_CONVERSION_TMP(fmpz_polyxx, padic_polyxx,
327         execution_check(padic_poly_get_fmpz_poly(
328                 to._poly(), from._poly(), from._ctx()),
329             "to<fmpz_polyxx>", "padic_polyxx"))
330 FLINTXX_DEFINE_CONVERSION_TMP(fmpq_polyxx, padic_polyxx,
331         padic_poly_get_fmpq_poly(to._poly(), from._poly(), from._ctx()))
332 
333 FLINT_DEFINE_BINARY_EXPR_COND2(padic_polyxx_get_coeff_op, padicxx,
334         PADIC_POLYXX_COND_S, traits::fits_into_slong,
335         padic_poly_get_coeff_padic(to._padic(), e1._poly(), e2, to._ctx()))
336 
337 FLINT_DEFINE_CBINARY_EXPR_COND2(plus, padic_polyxx,
338         PADIC_POLYXX_COND_S, PADIC_POLYXX_COND_S,
339         padic_poly_add(to._poly(), e1._poly(), e2._poly(), to._ctx()))
340 FLINT_DEFINE_BINARY_EXPR_COND2(minus, padic_polyxx,
341         PADIC_POLYXX_COND_S, PADIC_POLYXX_COND_S,
342         padic_poly_sub(to._poly(), e1._poly(), e2._poly(), to._ctx()))
343 FLINT_DEFINE_UNARY_EXPR_COND(negate, padic_polyxx, PADIC_POLYXX_COND_S,
344         padic_poly_neg(to._poly(), from._poly(), to._ctx()))
345 
346 FLINT_DEFINE_CBINARY_EXPR_COND2(times, padic_polyxx,
347         PADIC_POLYXX_COND_S, PADICXX_COND_S,
348         padic_poly_scalar_mul_padic(to._poly(), e1._poly(), e2._padic(), to._ctx()))
349 FLINT_DEFINE_CBINARY_EXPR_COND2(times, padic_polyxx,
350         PADIC_POLYXX_COND_S, PADIC_POLYXX_COND_S,
351         padic_poly_mul(to._poly(), e1._poly(), e2._poly(), to._ctx()))
352 
353 FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, padic_polyxx, PADIC_POLYXX_COND_S,
354         traits::is_unsigned_integer,
355         padic_poly_pow(to._poly(), e1._poly(), e2, to._ctx()))
356 
357 FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_op, padic_polyxx,
358         PADIC_POLYXX_COND_S, traits::fits_into_slong,
359         padic_poly_inv_series(to._poly(), e1._poly(), e2, to._ctx()))
360 
361 FLINT_DEFINE_UNARY_EXPR_COND(derivative_op, padic_polyxx, PADIC_POLYXX_COND_S,
362         padic_poly_derivative(to._poly(), from._poly(), to._ctx()))
363 
364 FLINT_DEFINE_BINARY_EXPR_COND2(shift_left_op, padic_polyxx,
365         PADIC_POLYXX_COND_S, traits::fits_into_slong,
366         padic_poly_shift_left(to._poly(), e1._poly(), e2, to._ctx()))
367 FLINT_DEFINE_BINARY_EXPR_COND2(shift_right_op, padic_polyxx,
368         PADIC_POLYXX_COND_S, traits::fits_into_slong,
369         padic_poly_shift_right(to._poly(), e1._poly(), e2, to._ctx()))
370 
371 FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, padicxx,
372         PADIC_POLYXX_COND_S, PADICXX_COND_S,
373         padic_poly_evaluate_padic(to._padic(), e1._poly(), e2._padic(), to._ctx()))
374 
375 FLINT_DEFINE_BINARY_EXPR_COND2(compose_op, padic_polyxx,
376         PADIC_POLYXX_COND_S, PADIC_POLYXX_COND_S,
377         padic_poly_compose(to._poly(), e1._poly(), e2._poly(), to._ctx()))
378 FLINT_DEFINE_BINARY_EXPR_COND2(compose_pow_op, padic_polyxx,
379         PADIC_POLYXX_COND_S, traits::fits_into_slong,
380         padic_poly_compose_pow(to._poly(), e1._poly(), e2, to._ctx()))
381 } // rules
382 } // flint
383 
384 #endif
385