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_MATXX_H
13 #define PADIC_MATXX_H
14 
15 #include "padic_mat.h"
16 
17 #include "padicxx.h"
18 #include "fmpq_matxx.h"
19 
20 #include "flintxx/matrix.h"
21 
22 // TODO input and output
23 
24 namespace flint {
FLINT_DEFINE_THREEARY(padic_matxx_get_entry)25 FLINT_DEFINE_THREEARY(padic_matxx_get_entry)
26 
27 namespace detail {
28 template<class Padic>
29 struct padic_mat_traits
30     : matrices::generic_traits<Padic>
31 {
32     typedef slong prec_ref_t;
33     typedef slong prec_srcref_t;
34 
35     typedef slong val_ref_t;
36     typedef slong val_srcref_t;
37 
38     static slong prec(const Padic& p) {return tools::padic_output_prec(p);}
39     static slong val(const Padic& p) {return padic_mat_val(p.evaluate()._mat());}
40 };
41 } //detail
42 
43 template<class Operation, class Data>
44 class padic_matxx_expression
45     : public expression<derived_wrapper<padic_matxx_expression>, Operation, Data>
46 {
47 public:
48     typedef expression<derived_wrapper< ::flint::padic_matxx_expression>,
49               Operation, Data> base_t;
50 
51     FLINTXX_DEFINE_BASICS(padic_matxx_expression)
52     FLINTXX_DEFINE_CTORS(padic_matxx_expression)
53     FLINTXX_DEFINE_C_REF(padic_matxx_expression, padic_mat_struct, _mat)
54 
55 public:
56     typedef detail::padic_mat_traits<padic_matxx_expression> traits_t;
57 
58     PADICXX_DEFINE_STD
59 
zero(padicxx_ctx_srcref ctx,slong rows,slong cols)60     static padic_matxx_expression zero(padicxx_ctx_srcref ctx,
61             slong rows, slong cols)
62         {return padic_matxx_expression(ctx, rows, cols);}
zero(padicxx_ctx_srcref ctx,slong rows,slong cols,slong N)63     static padic_matxx_expression zero(padicxx_ctx_srcref ctx,
64             slong rows, slong cols, slong N)
65         {return padic_matxx_expression(ctx, rows, cols, N);}
66 
one(padicxx_ctx_srcref ctx,slong rows,slong cols)67     static padic_matxx_expression one(padicxx_ctx_srcref ctx,
68             slong rows, slong cols)
69     {
70         padic_matxx_expression res(ctx, rows, cols);
71         res.set_one();
72         return res;
73     }
one(padicxx_ctx_srcref ctx,slong rows,slong cols,slong N)74     static padic_matxx_expression one(padicxx_ctx_srcref ctx,
75             slong rows, slong cols, slong N)
76     {
77         padic_matxx_expression res(ctx, rows, cols, N);
78         res.set_one();
79         return res;
80     }
81 
82     template<class T>
83     static padic_matxx_expression from_QQ(const T& q, padicxx_ctx_srcref ctx,
84             typename mp::enable_if<traits::is_fmpq_matxx<T> >::type* = 0)
85     {
86         padic_matxx_expression res(ctx, q.rows(), q.cols());
87         res = q;
88         return res;
89     }
90     template<class T>
91     static padic_matxx_expression from_QQ(const T& q, padicxx_ctx_srcref ctx,
92             slong N,
93             typename mp::enable_if<traits::is_fmpq_matxx<T> >::type* = 0)
94     {
95         padic_matxx_expression res(ctx, q.rows(), q.cols(), N);
96         res = q;
97         return res;
98     }
99 
100     template<class Expr>
create_temporary_rowscols(const Expr & e,slong rows,slong cols)101     static evaluated_t create_temporary_rowscols(
102             const Expr& e, slong rows, slong cols)
103     {
104         return evaluated_t(tools::find_padicxx_ctx(e),
105                 rows, cols, tools::padic_output_prec(e));
106     }
FLINTXX_DEFINE_MATRIX_METHODS(traits_t)107     FLINTXX_DEFINE_MATRIX_METHODS(traits_t)
108 
109     // static methods which only make sense with padicxx
110     static padic_matxx_expression randtest(slong rows, slong cols,
111             frandxx& state,
112             padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC)
113     {
114         padic_matxx_expression res(ctx, rows, cols, prec);
115         padic_mat_randtest(res._mat(), state._data(), ctx._ctx());
116         return res;
117     }
118 
119     // These only make sense with immediates
reduce()120     void reduce() {padic_mat_reduce(_mat(), _ctx());}
set_zero()121     void set_zero() {padic_mat_zero(_mat());}
set_one()122     void set_one() {padic_mat_one(_mat());}
truncate(slong n)123     void truncate(slong n) {fmpz_poly_truncate(_mat(), n);}
canonicalise()124     void canonicalise() {padic_mat_canonicalise(_mat());}
is_canonical()125     bool is_canonical() const {return padic_mat_is_canonical(_mat());}
is_reduced()126     bool is_reduced() const {return padic_mat_is_reduced(_mat());}
127 
128     template<class Padic>
129     void set_entry(slong i, slong j, const Padic& p,
130             typename mp::enable_if<traits::is_padicxx<Padic> >::type* = 0)
131     {
132         padic_mat_set_entry_padic(_mat(), i, j, p.evaluate()._padic(), _ctx());
133     }
134 
135     // these cause evaluation
is_zero()136     bool is_zero() const {return padic_mat_is_zero(this->evaluate()._mat());}
is_empty()137     bool is_empty() const {return padic_mat_is_empty(this->evaluate()._mat());}
is_square()138     bool is_square() const {return padic_mat_is_square(this->evaluate()._mat());}
139 
140     // forwarding of lazy functions
141     FLINTXX_DEFINE_MEMBER_UNOP(transpose)
142     FLINTXX_DEFINE_MEMBER_3OP_(get_entry, padic_matxx_get_entry)
143 };
144 
145 namespace detail {
146 struct padic_mat_data;
147 }
148 
149 typedef padic_matxx_expression<operations::immediate,
150             detail::padic_mat_data> padic_matxx;
151 typedef padic_matxx_expression<operations::immediate,
152             flint_classes::ref_data<padic_matxx, padic_mat_struct> >
153                 padic_matxx_ref;
154 typedef padic_matxx_expression<operations::immediate, flint_classes::srcref_data<
155     padic_matxx, padic_matxx_ref, padic_mat_struct> > padic_matxx_srcref;
156 
157 template<>
158 struct matrix_traits<padic_matxx>
159 {
160     template<class M> static slong rows(const M& m)
161     {
162         return padic_mat_nrows(m._mat());
163     }
164     template<class M> static slong cols(const M& m)
165     {
166         return padic_mat_ncols(m._mat());
167     }
168 
169     template<class M> static fmpzxx_srcref at(const M& m, slong i, slong j)
170     {
171         return fmpzxx_srcref::make(padic_mat_entry(m._mat(), i, j));
172     }
173     template<class M> static fmpzxx_ref at(M& m, slong i, slong j)
174     {
175         return fmpzxx_ref::make(padic_mat_entry(m._mat(), i, j));
176     }
177 };
178 
179 namespace traits {
180 template<> struct has_padicxx_ctx<padic_matxx> : mp::true_ { };
181 template<> struct has_padicxx_ctx<padic_matxx_ref> : mp::true_ { };
182 template<> struct has_padicxx_ctx<padic_matxx_srcref> : mp::true_ { };
183 } // traits
184 
185 namespace detail {
186 struct padic_matxx_srcref_traits_no_std_matrix
187 {
188     typedef slong prec_ref_t;
189     typedef slong prec_srcref_t;
190 
191     typedef slong val_ref_t;
192     typedef slong val_srcref_t;
193 
194     template<class P>
195     static slong prec(P p) {return p._data().N;}
196     template<class P>
197     static slong val(P p) {return padic_mat_val(p._mat());}
198 };
199 struct padic_matxx_ref_traits_no_std_matrix
200     : padic_matxx_srcref_traits_no_std_matrix
201 {
202     typedef slong& prec_ref_t;
203     typedef slong& val_ref_t;
204 
205     template<class P>
206     static slong& prec(P& p) {return padic_mat_prec(p._mat());}
207     template<class P>
208     static slong prec(const P& p) {return padic_mat_prec(p._mat());}
209 
210     template<class P>
211     static slong& val(P& p) {return padic_mat_val(p._mat());}
212     template<class P>
213     static slong val(const P& p) {return padic_mat_val(p._mat());}
214 };
215 template<>
216 struct padic_mat_traits<padic_matxx_srcref>
217     : matrices::generic_traits_srcref<fmpzxx_srcref>,
218       padic_matxx_srcref_traits_no_std_matrix { };
219 template<>
220 struct padic_mat_traits<padic_matxx_ref>
221     : matrices::generic_traits_ref<fmpzxx_ref>,
222       padic_matxx_ref_traits_no_std_matrix { };
223 template<>
224 struct padic_mat_traits<padic_matxx>
225     : matrices::generic_traits_nonref<fmpzxx_ref, fmpzxx_srcref>,
226       padic_matxx_ref_traits_no_std_matrix { };
227 } // detail
228 
229 PADICXX_DEFINE_REF_STRUCTS(padic_matxx, padic_mat_struct, padic_mat_prec)
230 
231 namespace detail {
232 struct padic_mat_data
233 {
234     typedef padic_mat_t& data_ref_t;
235     typedef const padic_mat_t& data_srcref_t;
236 
237     padicxx_ctx_srcref ctx;
238     padic_mat_t inner;
239 
240     padic_mat_data(padicxx_ctx_srcref c, slong rows, slong cols)
241         : ctx(c)
242     {
243         padic_mat_init(inner, rows, cols);
244     }
245 
246     padic_mat_data(padicxx_ctx_srcref c, slong rows, slong cols, slong N)
247         : ctx(c)
248     {
249         padic_mat_init2(inner, rows, cols, N);
250     }
251 
252     padic_mat_data(const padic_mat_data& o)
253         : ctx(o.ctx)
254     {
255         padic_mat_init2(inner, padic_mat_nrows(o.inner),
256                 padic_mat_ncols(o.inner), padic_mat_prec(o.inner));
257         padic_mat_set(inner, o.inner, ctx._ctx());
258     }
259 
260     ~padic_mat_data() {padic_mat_clear(inner);}
261 
262     padic_mat_data(padic_matxx_srcref c)
263         : ctx(c.get_ctx())
264     {
265         padic_mat_init2(inner, c.rows(), c.cols(), c.prec());
266         padic_mat_set(inner, c._mat(), ctx._ctx());
267     }
268 };
269 } // detail
270 
271 // matrix temporary stuff
272 FLINTXX_DEFINE_TEMPORARY_RULES(padic_matxx)
273 
274 #define PADIC_MATXX_COND_S FLINTXX_COND_S(padic_matxx)
275 #define PADIC_MATXX_COND_T FLINTXX_COND_T(padic_matxx)
276 
277 namespace rules {
278 FLINT_DEFINE_DOIT_COND2(assignment, PADIC_MATXX_COND_T, PADIC_MATXX_COND_S,
279         padic_mat_set(to._mat(), from._mat(), to._ctx()))
280 FLINT_DEFINE_DOIT_COND2(assignment, PADIC_MATXX_COND_T, FMPQ_MATXX_COND_S,
281         padic_mat_set_fmpq_mat(to._mat(), from._mat(), to._ctx()))
282 
283 FLINTXX_DEFINE_SWAP(padic_matxx, padic_mat_swap(e1._mat(), e2._mat()))
284 
285 FLINTXX_DEFINE_EQUALS(padic_matxx, padic_mat_equal(e1._mat(), e2._mat()))
286 
287 FLINT_DEFINE_PRINT_COND(PADIC_MATXX_COND_S,
288         padic_mat_fprint(to, from._mat(), from._ctx()))
289 FLINT_DEFINE_PRINT_PRETTY_COND(PADIC_MATXX_COND_S,
290         padic_mat_fprint_pretty(to, from._mat(), from._ctx()))
291 
292 template<class T>
293 struct conversion<fmpq_matxx, T,
294     typename mp::enable_if< PADIC_MATXX_COND_S<T> >::type>
295 {
296     static fmpq_matxx get(const T& from)
297     {
298         fmpq_matxx to(from.rows(), from.cols());
299         padic_mat_get_fmpq_mat(to._mat(), from._mat(), from._ctx());
300         return to;
301     }
302 };
303 
304 FLINT_DEFINE_THREEARY_EXPR_COND3(padic_matxx_get_entry_op, padicxx,
305         PADIC_MATXX_COND_S, traits::fits_into_slong, traits::fits_into_slong,
306         padic_mat_get_entry_padic(to._padic(), e1._mat(), e2, e3, to._ctx()))
307 
308 FLINT_DEFINE_UNARY_EXPR_COND(transpose_op, padic_matxx, PADIC_MATXX_COND_S,
309         padic_mat_transpose(to._mat(), from._mat()))
310 
311 FLINT_DEFINE_CBINARY_EXPR_COND2(plus, padic_matxx,
312         PADIC_MATXX_COND_S, PADIC_MATXX_COND_S,
313         padic_mat_add(to._mat(), e1._mat(), e2._mat(), to._ctx()))
314 FLINT_DEFINE_BINARY_EXPR_COND2(minus, padic_matxx,
315         PADIC_MATXX_COND_S, PADIC_MATXX_COND_S,
316         padic_mat_sub(to._mat(), e1._mat(), e2._mat(), to._ctx()))
317 FLINT_DEFINE_UNARY_EXPR_COND(negate, padic_matxx, PADIC_MATXX_COND_S,
318         padic_mat_neg(to._mat(), from._mat(), to._ctx()))
319 
320 FLINT_DEFINE_CBINARY_EXPR_COND2(times, padic_matxx,
321         PADIC_MATXX_COND_S, PADICXX_COND_S,
322         padic_mat_scalar_mul_padic(to._mat(), e1._mat(), e2._padic(), to._ctx()))
323 FLINT_DEFINE_CBINARY_EXPR_COND2(times, padic_matxx,
324         PADIC_MATXX_COND_S, FMPZXX_COND_S,
325         padic_mat_scalar_mul_fmpz(to._mat(), e1._mat(), e2._fmpz(), to._ctx()))
326 FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, padic_matxx,
327         PADIC_MATXX_COND_S, FMPZXX_COND_S,
328         padic_mat_scalar_div_fmpz(to._mat(), e1._mat(), e2._fmpz(), to._ctx()))
329 FLINT_DEFINE_CBINARY_EXPR_COND2(times, padic_matxx,
330         PADIC_MATXX_COND_S, PADIC_MATXX_COND_S,
331         padic_mat_mul(to._mat(), e1._mat(), e2._mat(), to._ctx()))
332 } // rules
333 }
334 
335 #endif
336