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_MATXX_H
13 #define FMPZ_POLY_MATXX_H FMPZ_POLY_MATXX_H
14
15 #include "fmpz_poly_mat.h"
16
17 #include "fmpz_matxx.h"
18 #include "fmpz_polyxx.h"
19 #include "permxx.h"
20
21 #include "flintxx/matrix.h"
22
23 namespace flint {
FLINT_DEFINE_UNOP(prod)24 FLINT_DEFINE_UNOP(prod)
25
26 namespace detail {
27 template<class Mat>
28 struct fmpz_poly_matxx_traits : matrices::generic_traits<Mat> { };
29 } // detail
30
31 template<class Operation, class Data>
32 class fmpz_poly_matxx_expression
33 : public expression<derived_wrapper<fmpz_poly_matxx_expression>, Operation, Data>
34 {
35 public:
36 typedef expression<derived_wrapper< ::flint::fmpz_poly_matxx_expression>,
37 Operation, Data> base_t;
38 typedef detail::fmpz_poly_matxx_traits<fmpz_poly_matxx_expression> traits_t;
39
40 FLINTXX_DEFINE_BASICS(fmpz_poly_matxx_expression)
FLINTXX_DEFINE_CTORS(fmpz_poly_matxx_expression)41 FLINTXX_DEFINE_CTORS(fmpz_poly_matxx_expression)
42 FLINTXX_DEFINE_C_REF(fmpz_poly_matxx_expression, fmpz_poly_mat_struct, _mat)
43
44 template<class Expr>
45 static evaluated_t create_temporary_rowscols(
46 const Expr&, slong rows, slong cols)
47 {
48 return evaluated_t(rows, cols);
49 }
FLINTXX_DEFINE_MATRIX_METHODS(traits_t)50 FLINTXX_DEFINE_MATRIX_METHODS(traits_t)
51
52 // static functions for fmpz_poly_matxx
53 template<class Fmpz_matxx>
54 static fmpz_poly_matxx_expression from_ground(const Fmpz_matxx& f)
55 {
56 return _from_ground(f.evaluate());
57 }
58 template<class Fmpz_matxx>
_from_ground(const Fmpz_matxx & f)59 static fmpz_poly_matxx_expression _from_ground(const Fmpz_matxx& f)
60 {
61 fmpz_poly_matxx_expression res(f.rows(), f.cols());
62 for(slong i = 0;i < f.rows();++i)
63 for(slong j = 0;j < f.rows();++j)
64 res.at(i, j).set_coeff(0, f.at(i, j));
65 return res;
66 }
67
randtest(slong rows,slong cols,frandxx & state,slong len,flint_bitcnt_t bits)68 static fmpz_poly_matxx_expression randtest(slong rows, slong cols,
69 frandxx& state, slong len, flint_bitcnt_t bits)
70 {
71 fmpz_poly_matxx_expression res(rows, cols);
72 res.set_randtest(state, len, bits);
73 return res;
74 }
randtest_unsigned(slong rows,slong cols,frandxx & state,slong len,flint_bitcnt_t bits)75 static fmpz_poly_matxx_expression randtest_unsigned(slong rows, slong cols,
76 frandxx& state, slong len, flint_bitcnt_t bits)
77 {
78 fmpz_poly_matxx_expression res(rows, cols);
79 res.set_randtest_unsigned(state, len, bits);
80 return res;
81 }
randtest_sparse(slong rows,slong cols,frandxx & state,slong len,flint_bitcnt_t bits,float density)82 static fmpz_poly_matxx_expression randtest_sparse(slong rows, slong cols,
83 frandxx& state, slong len, flint_bitcnt_t bits, float density)
84 {
85 fmpz_poly_matxx_expression res(rows, cols);
86 res.set_randtest_sparse(state, len, bits, density);
87 return res;
88 }
89
zero(slong rows,slong cols)90 static fmpz_poly_matxx_expression zero(slong rows, slong cols)
91 {return fmpz_poly_matxx_expression(rows, cols);}
one(slong rows,slong cols)92 static fmpz_poly_matxx_expression one(slong rows, slong cols)
93 {
94 fmpz_poly_matxx_expression res(rows, cols);
95 res.set_one();
96 return res;
97 }
98
99 // these only make sense with targets
set_randtest(frandxx & state,slong len,flint_bitcnt_t bits)100 void set_randtest(frandxx& state, slong len, flint_bitcnt_t bits)
101 {fmpz_poly_mat_randtest(_mat(), state._data(), len, bits);}
set_randtest_unsigned(frandxx & state,slong len,flint_bitcnt_t bits)102 void set_randtest_unsigned(frandxx& state, slong len, flint_bitcnt_t bits)
103 {fmpz_poly_mat_randtest_unsigned(_mat(), state._data(), len, bits);}
set_randtest_sparse(frandxx & state,slong len,flint_bitcnt_t bits,float density)104 void set_randtest_sparse(frandxx& state, slong len, flint_bitcnt_t bits,
105 float density)
106 {fmpz_poly_mat_randtest_sparse(_mat(), state._data(), len, bits, density);}
truncate(slong len)107 void truncate(slong len) {fmpz_poly_mat_truncate(_mat(), len);}
set_zero()108 void set_zero()
109 {fmpz_poly_mat_zero(_mat());}
set_one()110 void set_one()
111 {fmpz_poly_mat_one(_mat());}
112
113 // these cause evaluation
rank()114 slong rank() const {return fmpz_poly_mat_rank(this->evaluate()._mat());}
is_zero()115 bool is_zero() const
116 {return fmpz_poly_mat_is_zero(this->evaluate()._mat());}
is_one()117 bool is_one() const
118 {return fmpz_poly_mat_is_one(this->evaluate()._mat());}
is_empty()119 bool is_empty() const
120 {return fmpz_poly_mat_is_empty(this->evaluate()._mat());}
is_square()121 bool is_square() const
122 {return fmpz_poly_mat_is_square(this->evaluate()._mat());}
max_length()123 slong max_length() const
124 {return fmpz_poly_mat_max_length(this->evaluate()._mat());}
max_bits()125 slong max_bits() const
126 {return fmpz_poly_mat_max_bits(this->evaluate()._mat());}
find_pivot_any(slong start,slong end,slong c)127 slong find_pivot_any(slong start, slong end, slong c) const
128 {
129 return fmpz_poly_mat_find_pivot_any(
130 this->evaluate()._mat(), start, end, c);
131 }
find_pivot_partial(slong start,slong end,slong c)132 slong find_pivot_partial(slong start, slong end, slong c) const
133 {
134 return fmpz_poly_mat_find_pivot_partial(
135 this->evaluate()._mat(), start, end, c);
136 }
137
138 // forwarded lazy ops
139 FLINTXX_DEFINE_MEMBER_BINOP_(operator(), compeval)
140
141 FLINTXX_DEFINE_MEMBER_3OP(mullow)
142 FLINTXX_DEFINE_MEMBER_3OP(pow_trunc)
143
144 FLINTXX_DEFINE_MEMBER_BINOP(solve)
145 FLINTXX_DEFINE_MEMBER_BINOP(solve_fflu)
146 FLINTXX_DEFINE_MEMBER_BINOP(mul_KS)
147 FLINTXX_DEFINE_MEMBER_BINOP(mul_classical)
148 FLINTXX_DEFINE_MEMBER_BINOP(pow)
149 FLINTXX_DEFINE_MEMBER_BINOP(sqrlow)
150
151 FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpz_polyxx, det)
152 FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpz_polyxx, det_fflu)
153 FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpz_polyxx, det_interpolate)
154 FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpz_polyxx, trace)
155 FLINTXX_DEFINE_MEMBER_UNOP(sqr)
156 FLINTXX_DEFINE_MEMBER_UNOP(sqr_classical)
157 FLINTXX_DEFINE_MEMBER_UNOP(sqr_KS)
158 FLINTXX_DEFINE_MEMBER_UNOP(transpose)
159
160 //FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(nullspace) // TODO
161 //FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(???, inv) // TODO
162 //FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(???, rref) // TODO
163
164 FLINTXX_DEFINE_MEMBER_FFLU
165 };
166
167 namespace detail {
168 struct fmpz_poly_mat_data;
169 } // detail
170
171 typedef fmpz_poly_matxx_expression<operations::immediate,
172 detail::fmpz_poly_mat_data> fmpz_poly_matxx;
173 typedef fmpz_poly_matxx_expression<operations::immediate,
174 flint_classes::ref_data<fmpz_poly_matxx,
175 fmpz_poly_mat_struct> > fmpz_poly_matxx_ref;
176 typedef fmpz_poly_matxx_expression<operations::immediate,
177 flint_classes::srcref_data<
178 fmpz_poly_matxx, fmpz_poly_matxx_ref,
179 fmpz_poly_mat_struct> > fmpz_poly_matxx_srcref;
180
181 template<>
182 struct matrix_traits<fmpz_poly_matxx>
183 {
184 template<class M> static slong rows(const M& m)
185 {
186 return fmpz_poly_mat_nrows(m._mat());
187 }
188 template<class M> static slong cols(const M& m)
189 {
190 return fmpz_poly_mat_ncols(m._mat());
191 }
192
193 template<class M> static fmpz_polyxx_srcref at(const M& m, slong i, slong j)
194 {
195 return fmpz_polyxx_srcref::make(fmpz_poly_mat_entry(m._mat(), i, j));
196 }
197 template<class M> static fmpz_polyxx_ref at(M& m, slong i, slong j)
198 {
199 return fmpz_polyxx_ref::make(fmpz_poly_mat_entry(m._mat(), i, j));
200 }
201 };
202
203 namespace detail {
204 template<>
205 struct fmpz_poly_matxx_traits<fmpz_poly_matxx_srcref>
206 : matrices::generic_traits_srcref<fmpz_polyxx_srcref> { };
207 template<>
208 struct fmpz_poly_matxx_traits<fmpz_poly_matxx_ref>
209 : matrices::generic_traits_ref<fmpz_polyxx_ref> { };
210 template<> struct fmpz_poly_matxx_traits<fmpz_poly_matxx>
211 : matrices::generic_traits_nonref<fmpz_polyxx_ref, fmpz_polyxx_srcref> { };
212
213 struct fmpz_poly_mat_data
214 {
215 typedef fmpz_poly_mat_t& data_ref_t;
216 typedef const fmpz_poly_mat_t& data_srcref_t;
217
218 fmpz_poly_mat_t inner;
219
220 fmpz_poly_mat_data(slong m, slong n)
221 {
222 fmpz_poly_mat_init(inner, m, n);
223 }
224
225 fmpz_poly_mat_data(const fmpz_poly_mat_data& o)
226 {
227 fmpz_poly_mat_init_set(inner, o.inner);
228 }
229
230 fmpz_poly_mat_data(fmpz_poly_matxx_srcref o)
231 {
232 fmpz_poly_mat_init_set(inner, o._data().inner);
233 }
234
235 ~fmpz_poly_mat_data() {fmpz_poly_mat_clear(inner);}
236 };
237 } // detail
238
239 #define FMPZ_POLY_MATXX_COND_S FLINTXX_COND_S(fmpz_poly_matxx)
240 #define FMPZ_POLY_MATXX_COND_T FLINTXX_COND_T(fmpz_poly_matxx)
241
242 namespace matrices {
243 template<>
244 struct outsize<operations::mul_KS_op>
245 : outsize<operations::times> { };
246 template<>
247 struct outsize<operations::mullow_op>
248 : outsize<operations::times> { };
249 } // matrices
250
251 FLINTXX_DEFINE_TEMPORARY_RULES(fmpz_poly_matxx)
252
253 namespace rules {
254 FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_POLY_MATXX_COND_T, FMPZ_POLY_MATXX_COND_S,
255 fmpz_poly_mat_set(to._mat(), from._mat()))
256
257 FLINTXX_DEFINE_SWAP(fmpz_poly_matxx, fmpz_poly_mat_swap(e1._mat(), e2._mat()))
258
259 FLINTXX_DEFINE_EQUALS(fmpz_poly_matxx, fmpz_poly_mat_equal(e1._mat(), e2._mat()))
260
261 FLINT_DEFINE_PRINT_PRETTY_COND_2(FMPZ_POLY_MATXX_COND_S, const char*,
262 (fmpz_poly_mat_print(from._mat(), extra), 1))
263
264 FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpz_poly_matxx,
265 FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S,
266 fmpz_poly_mat_mul(to._mat(), e1._mat(), e2._mat()))
267 FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_poly_matxx,
268 FMPZ_POLY_MATXX_COND_S, FMPZXX_COND_S,
269 fmpz_poly_mat_scalar_mul_fmpz(to._mat(), e1._mat(), e2._fmpz()))
270 FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_poly_matxx,
271 FMPZ_POLY_MATXX_COND_S, FMPZ_POLYXX_COND_S,
272 fmpz_poly_mat_scalar_mul_fmpz_poly(to._mat(), e1._mat(), e2._poly()))
273
274 FLINT_DEFINE_BINARY_EXPR_COND2(plus, fmpz_poly_matxx,
275 FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S,
276 fmpz_poly_mat_add(to._mat(), e1._mat(), e2._mat()))
277 FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpz_poly_matxx,
278 FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S,
279 fmpz_poly_mat_sub(to._mat(), e1._mat(), e2._mat()))
280
281 FLINT_DEFINE_UNARY_EXPR_COND(negate, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S,
282 fmpz_poly_mat_neg(to._mat(), from._mat()))
283
284 FLINT_DEFINE_UNARY_EXPR_COND(transpose_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S,
285 fmpz_poly_mat_transpose(to._mat(), from._mat()))
286 FLINT_DEFINE_UNARY_EXPR_COND(trace_op, fmpz_polyxx, FMPZ_POLY_MATXX_COND_S,
287 fmpz_poly_mat_trace(to._poly(), from._mat()))
288
289 FLINT_DEFINE_THREEARY_EXPR_COND3(mat_at_op, fmpz_polyxx,
290 FMPZ_POLY_MATXX_COND_S, traits::fits_into_slong, traits::fits_into_slong,
291 fmpz_poly_set(to._poly(), fmpz_poly_mat_entry(e1._mat(), e2, e3)))
292
293 FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, fmpz_matxx,
294 FMPZ_POLY_MATXX_COND_S, FMPZXX_COND_S,
295 fmpz_poly_mat_evaluate_fmpz(to._mat(), e1._mat(), e2._fmpz()))
296
297 FLINT_DEFINE_BINARY_EXPR_COND2(mul_classical_op, fmpz_poly_matxx,
298 FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S,
299 fmpz_poly_mat_mul_classical(to._mat(), e1._mat(), e2._mat()))
300 FLINT_DEFINE_BINARY_EXPR_COND2(mul_KS_op, fmpz_poly_matxx,
301 FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S,
302 fmpz_poly_mat_mul_KS(to._mat(), e1._mat(), e2._mat()))
303
304 FLINT_DEFINE_THREEARY_EXPR_COND3(mullow_op, fmpz_poly_matxx,
305 FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S, traits::fits_into_slong,
306 fmpz_poly_mat_mullow(to._mat(), e1._mat(), e2._mat(), e3))
307
308 FLINT_DEFINE_UNARY_EXPR_COND(sqr_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S,
309 fmpz_poly_mat_sqr(to._mat(), from._mat()))
310 FLINT_DEFINE_UNARY_EXPR_COND(sqr_classical_op, fmpz_poly_matxx,
311 FMPZ_POLY_MATXX_COND_S,
312 fmpz_poly_mat_sqr_classical(to._mat(), from._mat()))
313 FLINT_DEFINE_UNARY_EXPR_COND(sqr_KS_op, fmpz_poly_matxx,
314 FMPZ_POLY_MATXX_COND_S,
315 fmpz_poly_mat_sqr_KS(to._mat(), from._mat()))
316 FLINT_DEFINE_BINARY_EXPR_COND2(sqrlow_op, fmpz_poly_matxx,
317 FMPZ_POLY_MATXX_COND_S, traits::fits_into_slong,
318 fmpz_poly_mat_sqrlow(to._mat(), e1._mat(), e2))
319
320 FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, fmpz_poly_matxx,
321 FMPZ_POLY_MATXX_COND_S, traits::is_unsigned_integer,
322 fmpz_poly_mat_pow(to._mat(), e1._mat(), e2))
323
324 FLINT_DEFINE_THREEARY_EXPR_COND3(pow_trunc_op, fmpz_poly_matxx,
325 FMPZ_POLY_MATXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong,
326 fmpz_poly_mat_pow_trunc(to._mat(), e1._mat(), e2, e3))
327
328 FLINT_DEFINE_UNARY_EXPR_COND(det_op, fmpz_polyxx, FMPZ_POLY_MATXX_COND_S,
329 fmpz_poly_mat_det(to._poly(), from._mat()))
330 FLINT_DEFINE_UNARY_EXPR_COND(det_fflu_op, fmpz_polyxx, FMPZ_POLY_MATXX_COND_S,
331 fmpz_poly_mat_det_fflu(to._poly(), from._mat()))
332 FLINT_DEFINE_UNARY_EXPR_COND(det_interpolate_op, fmpz_polyxx,
333 FMPZ_POLY_MATXX_COND_S,
334 fmpz_poly_mat_det_interpolate(to._poly(), from._mat()))
335
336 namespace rdetail {
337 typedef make_ltuple<mp::make_tuple<bool, fmpz_poly_matxx, fmpz_polyxx>::type >::type
338 fmpz_poly_mat_inv_rt;
339
340 typedef make_ltuple<mp::make_tuple<slong, fmpz_poly_matxx>::type >::type
341 fmpz_poly_mat_nullspace_rt;
342 }
343 FLINT_DEFINE_UNARY_EXPR_COND(inv_op, rdetail::fmpz_poly_mat_inv_rt,
344 FMPZ_POLY_MATXX_COND_S,
345 to.template get<0>() = fmpz_poly_mat_inv(to.template get<1>()._mat(),
346 to.template get<2>()._poly(), from._mat()))
347 FLINT_DEFINE_UNARY_EXPR_COND(nullspace_op, rdetail::fmpz_poly_mat_nullspace_rt,
348 FMPZ_POLY_MATXX_COND_S, to.template get<0>() = fmpz_poly_mat_nullspace(
349 to.template get<1>()._mat(), from._mat()))
350
351 FLINT_DEFINE_BINARY_EXPR_COND2(solve_op, rdetail::fmpz_poly_mat_inv_rt,
352 FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S,
353 to.template get<0>() = fmpz_poly_mat_solve(to.template get<1>()._mat(),
354 to.template get<2>()._poly(), e1._mat(), e2._mat()))
355 FLINT_DEFINE_BINARY_EXPR_COND2(solve_fflu_op, rdetail::fmpz_poly_mat_inv_rt,
356 FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S,
357 to.template get<0>() = fmpz_poly_mat_solve_fflu(
358 to.template get<1>()._mat(),
359 to.template get<2>()._poly(), e1._mat(), e2._mat()))
360
361 namespace rdetail {
362 typedef make_ltuple<mp::make_tuple<slong, fmpz_poly_matxx, fmpz_polyxx>::type>::type
363 fmpz_poly_matxx_fflu_rt;
364 } // rdetail
365
366 FLINT_DEFINE_THREEARY_EXPR_COND3(fflu_op, rdetail::fmpz_poly_matxx_fflu_rt,
367 FMPZ_POLY_MATXX_COND_S, traits::is_maybe_perm, tools::is_bool,
368 to.template get<0>() = fmpz_poly_mat_fflu(to.template get<1>()._mat(),
369 to.template get<2>()._poly(), maybe_perm_data(e2), e1._mat(), e3))
370
371 FLINT_DEFINE_UNARY_EXPR_COND(rref_op, rdetail::fmpz_poly_matxx_fflu_rt,
372 FMPZ_POLY_MATXX_COND_S,
373 to.template get<0>() = fmpz_poly_mat_rref(to.template get<1>()._mat(),
374 to.template get<2>()._poly(), from._mat()))
375
376 FLINT_DEFINE_THREEARY_EXPR_COND3(solve_fflu_precomp_op, fmpz_poly_matxx,
377 traits::is_permxx, FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S,
378 fmpz_poly_mat_solve_fflu_precomp(to._mat(), e1._data(),
379 e2._mat(), e3._mat()))
380 } // rules
381
382
383 ////////////////////////////////////////////////////////////////////////////
384 // fmpz_poly_mat_vecxx and prod
385 ////////////////////////////////////////////////////////////////////////////
386 namespace detail {
387 struct fmpz_poly_mat_vector_data
388 {
389 slong size;
390 fmpz_poly_mat_t* array;
391
392 fmpz_poly_mat_vector_data(slong n, slong rows, slong cols)
393 : size(n)
394 {
395 array = new fmpz_poly_mat_t[n];
396 for(slong i = 0; i < n; ++i)
397 fmpz_poly_mat_init(array[i], rows, cols);
398 }
399
400 ~fmpz_poly_mat_vector_data()
401 {
402 for(slong i = 0; i < size; ++i)
403 fmpz_poly_mat_clear(array[i]);
404 delete[] array;
405 }
406
407 fmpz_poly_mat_vector_data(const fmpz_poly_mat_vector_data& o)
408 : size(o.size)
409 {
410 array = new fmpz_poly_mat_t[size];
411 for(slong i = 0; i < size; ++i)
412 fmpz_poly_mat_init_set(array[i], o.array[i]);
413 }
414
415 fmpz_poly_matxx_ref at(slong i)
416 {return fmpz_poly_matxx_ref::make(array[i]);}
417 fmpz_poly_matxx_srcref at(slong i) const
418 {return fmpz_poly_matxx_srcref::make(array[i]);}
419
420 bool equals(const fmpz_poly_mat_vector_data& o) const
421 {
422 if(size != o.size)
423 return false;
424 for(slong i = 0; i < size; ++i)
425 if(!fmpz_poly_mat_equal(array[i], o.array[i]))
426 return false;
427 return true;
428 }
429 };
430 } // detail
431 // TODO temporary allocation
432
433 typedef vector_expression<
434 detail::wrapped_vector_traits<fmpz_poly_matxx, slong,
435 fmpz_poly_matxx_ref, fmpz_poly_matxx_srcref, fmpz_poly_mat_t>,
436 operations::immediate,
437 detail::fmpz_poly_mat_vector_data> fmpz_poly_mat_vecxx;
438 // TODO references
439
440 template<>
441 struct enable_vector_rules<fmpz_poly_mat_vecxx> : mp::false_ { };
442
443 namespace matrices {
444 template<>
445 struct outsize<operations::prod_op>
446 {
447 template<class Mat>
448 static slong rows(const Mat& m)
449 {
450 return m._data().head[0].rows();
451 }
452 template<class Mat>
453 static slong cols(const Mat& m)
454 {
455 return m._data().head[0].cols();
456 }
457 };
458 }
459
460 namespace rules {
461 // TODO hack to make code look like references are implemented
462 template<class T> struct FMPZ_POLY_MAT_VECXX_COND_S
463 : mp::equal_types<T, fmpz_poly_mat_vecxx> { };
464 #define FMPZ_POLY_MAT_VECXX_COND_T FMPZ_POLY_MAT_VECXX_COND_S
465
466 // TODO references
467 FLINT_DEFINE_GET(equals, bool, fmpz_poly_mat_vecxx, e1._data().equals(e2._data()))
468
469 FLINT_DEFINE_UNARY_EXPR_COND(prod_op, fmpz_poly_matxx,
470 FMPZ_POLY_MAT_VECXX_COND_S,
471 fmpz_poly_mat_prod(to._mat(), (fmpz_poly_mat_t * const) from._array(), from.size()))
472 } // rules
473
474 } // flint
475
476 #endif
477