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_POLY_QXX_H
13 #define FMPZ_POLY_QXX_H FMPZ_POLY_QXX_H
14 
15 #include <cstdlib>
16 #include <string>
17 
18 #include "flint.h"
19 #include "fmpz_poly_q.h"
20 
21 #include "fmpz_polyxx.h"
22 #include "fmpqxx.h"
23 
24 #include "flintxx/expression.h"
25 #include "flintxx/flint_classes.h"
26 
27 namespace flint {
28 FLINT_DEFINE_UNOP(fmpz_poly_qxx_num)
FLINT_DEFINE_UNOP(fmpz_poly_qxx_den)29 FLINT_DEFINE_UNOP(fmpz_poly_qxx_den)
30 
31 namespace detail {
32 template<class Polyq>
33 struct fmpz_poly_q_traits
34 {
35     typedef FLINT_UNOP_BUILD_RETTYPE(
36                 fmpz_poly_qxx_num, fmpz_polyxx, Polyq) num_ref_t;
37     typedef FLINT_UNOP_BUILD_RETTYPE(
38                 fmpz_poly_qxx_den, fmpz_polyxx, Polyq) den_ref_t;
39     typedef num_ref_t num_srcref_t;
40     typedef den_ref_t den_srcref_t;
41     static num_ref_t num(const Polyq& p) {return fmpz_poly_qxx_num(p);}
42     static den_ref_t den(const Polyq& p) {return fmpz_poly_qxx_den(p);}
43 };
44 } // detail
45 
46 template<class Operation, class Data>
47 class fmpz_poly_qxx_expression
48     : public expression<derived_wrapper<fmpz_poly_qxx_expression>,
49                             Operation, Data>
50 {
51 public:
52     typedef expression<derived_wrapper< ::flint::fmpz_poly_qxx_expression>,
53               Operation, Data> base_t;
54     typedef detail::fmpz_poly_q_traits<fmpz_poly_qxx_expression> poly_traits_t;
55     typedef typename poly_traits_t::num_ref_t num_ref_t;
56     typedef typename poly_traits_t::num_srcref_t num_srcref_t;
57     typedef typename poly_traits_t::den_ref_t den_ref_t;
58     typedef typename poly_traits_t::den_srcref_t den_srcref_t;
59 
60     FLINTXX_DEFINE_BASICS(fmpz_poly_qxx_expression)
FLINTXX_DEFINE_CTORS(fmpz_poly_qxx_expression)61     FLINTXX_DEFINE_CTORS(fmpz_poly_qxx_expression)
62     FLINTXX_DEFINE_C_REF(fmpz_poly_qxx_expression, fmpz_poly_q_struct, _polyq)
63 
64     // static methods which only make sense with fmpq_polyxx
65     static fmpz_poly_qxx_expression randtest(frandxx& state,
66             slong len1, flint_bitcnt_t bits1, slong len2, flint_bitcnt_t bits2)
67     {
68         fmpz_poly_qxx_expression res;
69         fmpz_poly_q_randtest(res._polyq(), state._data(),
70                 len1, bits1, len2, bits2);
71         return res;
72     }
randtest_not_zero(frandxx & state,slong len1,flint_bitcnt_t bits1,slong len2,flint_bitcnt_t bits2)73     static fmpz_poly_qxx_expression randtest_not_zero(frandxx& state,
74             slong len1, flint_bitcnt_t bits1, slong len2, flint_bitcnt_t bits2)
75     {
76         fmpz_poly_qxx_expression res;
77         fmpz_poly_q_randtest_not_zero(res._polyq(), state._data(),
78                 len1, bits1, len2, bits2);
79         return res;
80     }
81 
zero()82     static fmpz_poly_qxx_expression zero(){return fmpz_poly_qxx_expression();}
one()83     static fmpz_poly_qxx_expression one()
84     {
85         fmpz_poly_qxx_expression res;
86         res.set_one();
87         return res;
88     }
89 
90     // Numerator and denominator access
num()91     num_ref_t num() {return poly_traits_t::num(*this);}
num()92     num_srcref_t num() const {return poly_traits_t::num(*this);}
den()93     den_ref_t den() {return poly_traits_t::den(*this);}
den()94     den_srcref_t den() const {return poly_traits_t::den(*this);}
is_canonical()95     bool is_canonical() const {return fmpz_poly_q_is_canonical(_polyq());}
96 
97     // these only make sense with target immediates
canonicalise()98     void canonicalise() {fmpz_poly_q_canonicalise(_polyq());}
set_zero()99     void set_zero() {fmpz_poly_q_zero(_polyq());}
set_one()100     void set_one() {fmpz_poly_q_one(_polyq());}
101 
102     // These cause evaluation
pretty(const char * x)103     std::string pretty(const char* x) const
104     {
105         char* str = fmpz_poly_q_get_str_pretty(this->evaluate()._polyq(), x);
106         std::string res(str);
107         flint_free(str);
108         return res;
109     }
is_one()110     bool is_one() const {return fmpz_poly_q_is_one(this->evaluate()._polyq());}
is_zero()111     bool is_zero() const {return fmpz_poly_q_is_zero(this->evaluate()._polyq());}
112 
113     // forwarded lazy member functions
114     FLINTXX_DEFINE_MEMBER_UNOP(inv)
115     FLINTXX_DEFINE_MEMBER_BINOP(pow)
116     FLINTXX_DEFINE_MEMBER_UNOP(derivative)
117 };
118 
119 namespace detail {
120 struct fmpz_poly_q_data;
121 }
122 
123 typedef fmpz_poly_qxx_expression<operations::immediate, detail::fmpz_poly_q_data>
124            fmpz_poly_qxx;
125 typedef fmpz_poly_qxx_expression<operations::immediate,
126             flint_classes::ref_data<fmpz_poly_qxx, fmpz_poly_q_struct> >
127            fmpz_poly_qxx_ref;
128 typedef fmpz_poly_qxx_expression<operations::immediate,
129             flint_classes::srcref_data<
130                 fmpz_poly_qxx, fmpz_poly_qxx_ref, fmpz_poly_q_struct> >
131            fmpz_poly_qxx_srcref;
132 
133 namespace detail {
134 template<>
135 struct fmpz_poly_q_traits<fmpz_poly_qxx_srcref>
136 {
137     typedef fmpz_polyxx_srcref num_ref_t;
138     typedef fmpz_polyxx_srcref num_srcref_t;
139     typedef fmpz_polyxx_srcref den_ref_t;
140     typedef fmpz_polyxx_srcref den_srcref_t;
141     template<class P> static num_srcref_t num(const P& p)
142         {return num_srcref_t::make(fmpz_poly_q_numref(p._polyq()));}
143     template<class P> static den_srcref_t den(const P& p)
144         {return num_srcref_t::make(fmpz_poly_q_denref(p._polyq()));}
145 };
146 template<>
147 struct fmpz_poly_q_traits<fmpz_poly_qxx_ref>
148 {
149     typedef fmpz_polyxx_ref num_ref_t;
150     typedef fmpz_polyxx_ref den_ref_t;
151     typedef fmpz_polyxx_ref num_srcref_t;
152     typedef fmpz_polyxx_ref den_srcref_t;
153     template<class P> static num_ref_t num(P p)
154         {return num_ref_t::make(fmpz_poly_q_numref(p._polyq()));}
155     template<class P> static den_ref_t den(P p)
156         {return num_ref_t::make(fmpz_poly_q_denref(p._polyq()));}
157 };
158 template<>
159 struct fmpz_poly_q_traits<fmpz_poly_qxx>
160 {
161     typedef fmpz_polyxx_ref num_ref_t;
162     typedef fmpz_polyxx_ref den_ref_t;
163     typedef fmpz_polyxx_srcref num_srcref_t;
164     typedef fmpz_polyxx_srcref den_srcref_t;
165     template<class P> static num_ref_t num(P& p)
166         {return num_ref_t::make(fmpz_poly_q_numref(p._polyq()));}
167     template<class P> static den_ref_t den(P& p)
168         {return num_ref_t::make(fmpz_poly_q_denref(p._polyq()));}
169     template<class P> static num_srcref_t num(const P& p)
170         {return num_srcref_t::make(fmpz_poly_q_numref(p._polyq()));}
171     template<class P> static den_srcref_t den(const P& p)
172         {return num_srcref_t::make(fmpz_poly_q_denref(p._polyq()));}
173 };
174 
175 struct fmpz_poly_q_data
176 {
177     fmpz_poly_q_t inner;
178     typedef fmpz_poly_q_t& data_ref_t;
179     typedef const fmpz_poly_q_t& data_srcref_t;
180 
181     fmpz_poly_q_data() {fmpz_poly_q_init(inner);}
182     ~fmpz_poly_q_data() {fmpz_poly_q_clear(inner);}
183 
184     fmpz_poly_q_data(const fmpz_poly_q_data& o)
185     {
186         fmpz_poly_q_init(inner);
187         fmpz_poly_q_set(inner, o.inner);
188     }
189 
190     fmpz_poly_q_data(fmpz_poly_qxx_srcref r)
191     {
192         fmpz_poly_q_init(inner);
193         fmpz_poly_q_set(inner, r._polyq());
194     }
195 
196     fmpz_poly_q_data(const char* str)
197     {
198         fmpz_poly_q_init(inner);
199         execution_check(!fmpz_poly_q_set_str(inner, str),
200                 "construct from string", "fmpz_poly_qxx");
201     }
202 };
203 } // detail
204 
205 namespace rules {
206 #define FMPZ_POLY_QXX_COND_S FLINTXX_COND_S(fmpz_poly_qxx)
207 #define FMPZ_POLY_QXX_COND_T FLINTXX_COND_T(fmpz_poly_qxx)
208 
209 FLINTXX_DEFINE_TO_STR(fmpz_poly_qxx, fmpz_poly_q_get_str(from._polyq()))
210 FLINTXX_DEFINE_SWAP(fmpz_poly_qxx, fmpz_poly_q_swap(e1._polyq(), e2._polyq()))
211 
212 FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_POLY_QXX_COND_T, FMPZ_POLY_QXX_COND_S,
213         fmpz_poly_q_set(to._polyq(), from._polyq()))
214 FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_POLY_QXX_COND_T,
215         traits::fits_into_slong, fmpz_poly_q_set_si(to._polyq(), from))
216 
217 FLINTXX_DEFINE_ASSIGN_STR(fmpz_poly_qxx, execution_check(
218             !fmpz_poly_q_set_str(to._polyq(), from),
219             "assign string", "fmpz_poly_qxx"))
220 
221 FLINT_DEFINE_PRINT_COND(FMPZ_POLY_QXX_COND_S, fmpz_poly_q_print(from._polyq()))
222 FLINT_DEFINE_PRINT_PRETTY_COND_2(FMPZ_POLY_QXX_COND_S, const char*,
223         fmpz_poly_q_print_pretty(from._polyq(), extra))
224 
225 FLINTXX_DEFINE_EQUALS(fmpz_poly_qxx, fmpz_poly_q_equal(e1._polyq(), e2._polyq()))
226 
227 FLINT_DEFINE_UNARY_EXPR_COND(negate, fmpz_poly_qxx, FMPZ_POLY_QXX_COND_S,
228         fmpz_poly_q_neg(to._polyq(), from._polyq()))
229 FLINT_DEFINE_UNARY_EXPR_COND(inv_op, fmpz_poly_qxx, FMPZ_POLY_QXX_COND_S,
230         fmpz_poly_q_inv(to._polyq(), from._polyq()))
231 
232 FLINT_DEFINE_BINARY_EXPR_COND2(plus, fmpz_poly_qxx,
233         FMPZ_POLY_QXX_COND_S, FMPZ_POLY_QXX_COND_S,
234         fmpz_poly_q_add(to._polyq(), e1._polyq(), e2._polyq()))
235 FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpz_poly_qxx,
236         FMPZ_POLY_QXX_COND_S, FMPZ_POLY_QXX_COND_S,
237         fmpz_poly_q_sub(to._polyq(), e1._polyq(), e2._polyq()))
238 
239 FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_poly_qxx,
240         FMPZ_POLY_QXX_COND_S, traits::fits_into_slong,
241         fmpz_poly_q_scalar_mul_si(to._polyq(), e1._polyq(), e2))
242 FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpz_poly_qxx,
243         FMPZ_POLY_QXX_COND_S, traits::fits_into_slong,
244         fmpz_poly_q_scalar_div_si(to._polyq(), e1._polyq(), e2))
245 
246 FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpz_poly_qxx,
247         FMPZ_POLY_QXX_COND_S, FMPZ_POLY_QXX_COND_S,
248         fmpz_poly_q_mul(to._polyq(), e1._polyq(), e2._polyq()))
249 FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpz_poly_qxx,
250         FMPZ_POLY_QXX_COND_S, FMPZ_POLY_QXX_COND_S,
251         fmpz_poly_q_div(to._polyq(), e1._polyq(), e2._polyq()))
252 
253 FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, fmpz_poly_qxx,
254         FMPZ_POLY_QXX_COND_S, traits::is_unsigned_integer,
255         fmpz_poly_q_pow(to._polyq(), e1._polyq(), e2))
256 
257 FLINT_DEFINE_UNARY_EXPR_COND(derivative_op, fmpz_poly_qxx, FMPZ_POLY_QXX_COND_S,
258         fmpz_poly_q_derivative(to._polyq(), from._polyq()))
259 
260 FLINT_DEFINE_UNARY_EXPR_COND(fmpz_poly_qxx_num_op, fmpz_polyxx,
261         FMPZ_POLY_QXX_COND_S,
262         fmpz_poly_set(to._poly(), fmpz_poly_q_numref(from._polyq())))
263 FLINT_DEFINE_UNARY_EXPR_COND(fmpz_poly_qxx_den_op, fmpz_polyxx,
264         FMPZ_POLY_QXX_COND_S,
265         fmpz_poly_set(to._poly(), fmpz_poly_q_denref(from._polyq())))
266 
267 // XXX these should really be in fmpz_poly_q.h ...
268 #if 0
269 FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_poly_qxx,
270         FMPZ_POLY_QXX_COND_S, FMPZXX_COND_S,
271         to.numref() = e1.numref()*e2;to.denref() = e1.denref();to.canonicalise())
272 FLINT_DEFINE_CBINARY_EXPR_COND2(divided_by, fmpz_poly_qxx,
273         FMPZ_POLY_QXX_COND_S, FMPZXX_COND_S,
274         to.denref() = e1.denref()*e2;to.numref() = e1.numref();to.canonicalise())
275 FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_poly_qxx,
276         FMPZ_POLY_QXX_COND_S, FMPQXX_COND_S,
277         to.numref() = e1.numref()*e2.num();to.denref() = e1.denref()*e2.den();
278         to.canonicalise())
279 FLINT_DEFINE_CBINARY_EXPR_COND2(divided_by, fmpz_poly_qxx,
280         FMPZ_POLY_QXX_COND_S, FMPQXX_COND_S,
281         to.numref() = e1.numref()*e2.den();to.denref() = e1.denref()*e2.num();
282         to.canonicalise())
283 #endif
284 } // rules
285 // NB: addmul is not actually optimised currently
286 } // flint
287 
288 #endif
289