/*============================================================================= This file is part of FLINT. FLINT is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. FLINT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLINT; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =============================================================================*/ /****************************************************************************** Copyright (C) 2013 Tom Bachmann ******************************************************************************/ #ifndef FMPZ_POLY_MATXX_H #define FMPZ_POLY_MATXX_H FMPZ_POLY_MATXX_H #include "fmpz_poly_mat.h" #include "fmpz_matxx.h" #include "fmpz_polyxx.h" #include "permxx.h" #include "flintxx/matrix.h" namespace flint { FLINT_DEFINE_UNOP(prod) namespace detail { template struct fmpz_poly_matxx_traits : matrices::generic_traits { }; } // detail template class fmpz_poly_matxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; typedef detail::fmpz_poly_matxx_traits traits_t; FLINTXX_DEFINE_BASICS(fmpz_poly_matxx_expression) FLINTXX_DEFINE_CTORS(fmpz_poly_matxx_expression) FLINTXX_DEFINE_C_REF(fmpz_poly_matxx_expression, fmpz_poly_mat_struct, _mat) template static evaluated_t create_temporary_rowscols( const Expr&, slong rows, slong cols) { return evaluated_t(rows, cols); } FLINTXX_DEFINE_MATRIX_METHODS(traits_t) // static functions for fmpz_poly_matxx template static fmpz_poly_matxx_expression from_ground(const Fmpz_matxx& f) { return _from_ground(f.evaluate()); } template static fmpz_poly_matxx_expression _from_ground(const Fmpz_matxx& f) { fmpz_poly_matxx_expression res(f.rows(), f.cols()); for(slong i = 0;i < f.rows();++i) for(slong j = 0;j < f.rows();++j) res.at(i, j).set_coeff(0, f.at(i, j)); return res; } static fmpz_poly_matxx_expression randtest(slong rows, slong cols, frandxx& state, slong len, mp_bitcnt_t bits) { fmpz_poly_matxx_expression res(rows, cols); res.set_randtest(state, len, bits); return res; } static fmpz_poly_matxx_expression randtest_unsigned(slong rows, slong cols, frandxx& state, slong len, mp_bitcnt_t bits) { fmpz_poly_matxx_expression res(rows, cols); res.set_randtest_unsigned(state, len, bits); return res; } static fmpz_poly_matxx_expression randtest_sparse(slong rows, slong cols, frandxx& state, slong len, mp_bitcnt_t bits, float density) { fmpz_poly_matxx_expression res(rows, cols); res.set_randtest_sparse(state, len, bits, density); return res; } static fmpz_poly_matxx_expression zero(slong rows, slong cols) {return fmpz_poly_matxx_expression(rows, cols);} static fmpz_poly_matxx_expression one(slong rows, slong cols) { fmpz_poly_matxx_expression res(rows, cols); res.set_one(); return res; } // these only make sense with targets void set_randtest(frandxx& state, slong len, mp_bitcnt_t bits) {fmpz_poly_mat_randtest(_mat(), state._data(), len, bits);} void set_randtest_unsigned(frandxx& state, slong len, mp_bitcnt_t bits) {fmpz_poly_mat_randtest_unsigned(_mat(), state._data(), len, bits);} void set_randtest_sparse(frandxx& state, slong len, mp_bitcnt_t bits, float density) {fmpz_poly_mat_randtest_sparse(_mat(), state._data(), len, bits, density);} void truncate(slong len) {fmpz_poly_mat_truncate(_mat(), len);} void set_zero() {fmpz_poly_mat_zero(_mat());} void set_one() {fmpz_poly_mat_one(_mat());} // these cause evaluation slong rank() const {return fmpz_poly_mat_rank(this->evaluate()._mat());} bool is_zero() const {return fmpz_poly_mat_is_zero(this->evaluate()._mat());} bool is_one() const {return fmpz_poly_mat_is_one(this->evaluate()._mat());} bool is_empty() const {return fmpz_poly_mat_is_empty(this->evaluate()._mat());} bool is_square() const {return fmpz_poly_mat_is_square(this->evaluate()._mat());} slong max_length() const {return fmpz_poly_mat_max_length(this->evaluate()._mat());} slong max_bits() const {return fmpz_poly_mat_max_bits(this->evaluate()._mat());} slong find_pivot_any(slong start, slong end, slong c) const { return fmpz_poly_mat_find_pivot_any( this->evaluate()._mat(), start, end, c); } slong find_pivot_partial(slong start, slong end, slong c) const { return fmpz_poly_mat_find_pivot_partial( this->evaluate()._mat(), start, end, c); } // forwarded lazy ops FLINTXX_DEFINE_MEMBER_BINOP_(operator(), compeval) FLINTXX_DEFINE_MEMBER_3OP(mullow) FLINTXX_DEFINE_MEMBER_3OP(pow_trunc) FLINTXX_DEFINE_MEMBER_BINOP(solve) FLINTXX_DEFINE_MEMBER_BINOP(solve_fflu) FLINTXX_DEFINE_MEMBER_BINOP(mul_KS) FLINTXX_DEFINE_MEMBER_BINOP(mul_classical) FLINTXX_DEFINE_MEMBER_BINOP(pow) FLINTXX_DEFINE_MEMBER_BINOP(sqrlow) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpz_polyxx, det) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpz_polyxx, det_fflu) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpz_polyxx, det_interpolate) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpz_polyxx, trace) FLINTXX_DEFINE_MEMBER_UNOP(sqr) FLINTXX_DEFINE_MEMBER_UNOP(sqr_classical) FLINTXX_DEFINE_MEMBER_UNOP(sqr_KS) FLINTXX_DEFINE_MEMBER_UNOP(transpose) //FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(nullspace) // TODO //FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(???, inv) // TODO //FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(???, rref) // TODO FLINTXX_DEFINE_MEMBER_FFLU }; namespace detail { struct fmpz_poly_mat_data; } // detail typedef fmpz_poly_matxx_expression fmpz_poly_matxx; typedef fmpz_poly_matxx_expression > fmpz_poly_matxx_ref; typedef fmpz_poly_matxx_expression > fmpz_poly_matxx_srcref; template<> struct matrix_traits { template static slong rows(const M& m) { return fmpz_poly_mat_nrows(m._mat()); } template static slong cols(const M& m) { return fmpz_poly_mat_ncols(m._mat()); } template static fmpz_polyxx_srcref at(const M& m, slong i, slong j) { return fmpz_polyxx_srcref::make(fmpz_poly_mat_entry(m._mat(), i, j)); } template static fmpz_polyxx_ref at(M& m, slong i, slong j) { return fmpz_polyxx_ref::make(fmpz_poly_mat_entry(m._mat(), i, j)); } }; namespace detail { template<> struct fmpz_poly_matxx_traits : matrices::generic_traits_srcref { }; template<> struct fmpz_poly_matxx_traits : matrices::generic_traits_ref { }; template<> struct fmpz_poly_matxx_traits : matrices::generic_traits_nonref { }; struct fmpz_poly_mat_data { typedef fmpz_poly_mat_t& data_ref_t; typedef const fmpz_poly_mat_t& data_srcref_t; fmpz_poly_mat_t inner; fmpz_poly_mat_data(slong m, slong n) { fmpz_poly_mat_init(inner, m, n); } fmpz_poly_mat_data(const fmpz_poly_mat_data& o) { fmpz_poly_mat_init_set(inner, o.inner); } fmpz_poly_mat_data(fmpz_poly_matxx_srcref o) { fmpz_poly_mat_init_set(inner, o._data().inner); } ~fmpz_poly_mat_data() {fmpz_poly_mat_clear(inner);} }; } // detail #define FMPZ_POLY_MATXX_COND_S FLINTXX_COND_S(fmpz_poly_matxx) #define FMPZ_POLY_MATXX_COND_T FLINTXX_COND_T(fmpz_poly_matxx) namespace matrices { template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; } // matrices FLINTXX_DEFINE_TEMPORARY_RULES(fmpz_poly_matxx) namespace rules { FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_POLY_MATXX_COND_T, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_set(to._mat(), from._mat())) FLINTXX_DEFINE_SWAP(fmpz_poly_matxx, fmpz_poly_mat_swap(e1._mat(), e2._mat())) FLINTXX_DEFINE_EQUALS(fmpz_poly_matxx, fmpz_poly_mat_equal(e1._mat(), e2._mat())) FLINT_DEFINE_PRINT_PRETTY_COND_2(FMPZ_POLY_MATXX_COND_S, const char*, (fmpz_poly_mat_print(from._mat(), extra), 1)) FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_mul(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, FMPZXX_COND_S, fmpz_poly_mat_scalar_mul_fmpz(to._mat(), e1._mat(), e2._fmpz())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_mat_scalar_mul_fmpz_poly(to._mat(), e1._mat(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(plus, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_add(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_sub(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_UNARY_EXPR_COND(negate, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_neg(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(transpose_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_transpose(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(trace_op, fmpz_polyxx, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_trace(to._poly(), from._mat())) FLINT_DEFINE_THREEARY_EXPR_COND3(mat_at_op, fmpz_polyxx, FMPZ_POLY_MATXX_COND_S, traits::fits_into_slong, traits::fits_into_slong, fmpz_poly_set(to._poly(), fmpz_poly_mat_entry(e1._mat(), e2, e3))) FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, fmpz_matxx, FMPZ_POLY_MATXX_COND_S, FMPZXX_COND_S, fmpz_poly_mat_evaluate_fmpz(to._mat(), e1._mat(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(mul_classical_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_mul_classical(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(mul_KS_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_mul_KS(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_THREEARY_EXPR_COND3(mullow_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S, traits::fits_into_slong, fmpz_poly_mat_mullow(to._mat(), e1._mat(), e2._mat(), e3)) FLINT_DEFINE_UNARY_EXPR_COND(sqr_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_sqr(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(sqr_classical_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_sqr_classical(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(sqr_KS_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_sqr_KS(to._mat(), from._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(sqrlow_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, traits::fits_into_slong, fmpz_poly_mat_sqrlow(to._mat(), e1._mat(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, traits::is_unsigned_integer, fmpz_poly_mat_pow(to._mat(), e1._mat(), e2)) FLINT_DEFINE_THREEARY_EXPR_COND3(pow_trunc_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong, fmpz_poly_mat_pow_trunc(to._mat(), e1._mat(), e2, e3)) FLINT_DEFINE_UNARY_EXPR_COND(det_op, fmpz_polyxx, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_det(to._poly(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(det_fflu_op, fmpz_polyxx, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_det_fflu(to._poly(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(det_interpolate_op, fmpz_polyxx, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_det_interpolate(to._poly(), from._mat())) namespace rdetail { typedef make_ltuple::type >::type fmpz_poly_mat_inv_rt; typedef make_ltuple::type >::type fmpz_poly_mat_nullspace_rt; } FLINT_DEFINE_UNARY_EXPR_COND(inv_op, rdetail::fmpz_poly_mat_inv_rt, FMPZ_POLY_MATXX_COND_S, to.template get<0>() = fmpz_poly_mat_inv(to.template get<1>()._mat(), to.template get<2>()._poly(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(nullspace_op, rdetail::fmpz_poly_mat_nullspace_rt, FMPZ_POLY_MATXX_COND_S, to.template get<0>() = fmpz_poly_mat_nullspace( to.template get<1>()._mat(), from._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(solve_op, rdetail::fmpz_poly_mat_inv_rt, FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S, to.template get<0>() = fmpz_poly_mat_solve(to.template get<1>()._mat(), to.template get<2>()._poly(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(solve_fflu_op, rdetail::fmpz_poly_mat_inv_rt, FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S, to.template get<0>() = fmpz_poly_mat_solve_fflu( to.template get<1>()._mat(), to.template get<2>()._poly(), e1._mat(), e2._mat())) namespace rdetail { typedef make_ltuple::type>::type fmpz_poly_matxx_fflu_rt; } // rdetail FLINT_DEFINE_THREEARY_EXPR_COND3(fflu_op, rdetail::fmpz_poly_matxx_fflu_rt, FMPZ_POLY_MATXX_COND_S, traits::is_maybe_perm, tools::is_bool, to.template get<0>() = fmpz_poly_mat_fflu(to.template get<1>()._mat(), to.template get<2>()._poly(), maybe_perm_data(e2), e1._mat(), e3)) FLINT_DEFINE_UNARY_EXPR_COND(rref_op, rdetail::fmpz_poly_matxx_fflu_rt, FMPZ_POLY_MATXX_COND_S, to.template get<0>() = fmpz_poly_mat_rref(to.template get<1>()._mat(), to.template get<2>()._poly(), from._mat())) FLINT_DEFINE_THREEARY_EXPR_COND3(solve_fflu_precomp_op, fmpz_poly_matxx, traits::is_permxx, FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_solve_fflu_precomp(to._mat(), e1._data(), e2._mat(), e3._mat())) } // rules //////////////////////////////////////////////////////////////////////////// // fmpz_poly_mat_vecxx and prod //////////////////////////////////////////////////////////////////////////// namespace detail { struct fmpz_poly_mat_vector_data { slong size; fmpz_poly_mat_t* array; fmpz_poly_mat_vector_data(slong n, slong rows, slong cols) : size(n) { array = new fmpz_poly_mat_t[n]; for(slong i = 0; i < n; ++i) fmpz_poly_mat_init(array[i], rows, cols); } ~fmpz_poly_mat_vector_data() { for(slong i = 0; i < size; ++i) fmpz_poly_mat_clear(array[i]); delete[] array; } fmpz_poly_mat_vector_data(const fmpz_poly_mat_vector_data& o) : size(o.size) { array = new fmpz_poly_mat_t[size]; for(slong i = 0; i < size; ++i) fmpz_poly_mat_init_set(array[i], o.array[i]); } fmpz_poly_matxx_ref at(slong i) {return fmpz_poly_matxx_ref::make(array[i]);} fmpz_poly_matxx_srcref at(slong i) const {return fmpz_poly_matxx_srcref::make(array[i]);} bool equals(const fmpz_poly_mat_vector_data& o) const { if(size != o.size) return false; for(slong i = 0; i < size; ++i) if(!fmpz_poly_mat_equal(array[i], o.array[i])) return false; return true; } }; } // detail // TODO temporary allocation typedef vector_expression< detail::wrapped_vector_traits, operations::immediate, detail::fmpz_poly_mat_vector_data> fmpz_poly_mat_vecxx; // TODO references template<> struct enable_vector_rules : mp::false_ { }; namespace matrices { template<> struct outsize { template static slong rows(const Mat& m) { return m._data().head[0].rows(); } template static slong cols(const Mat& m) { return m._data().head[0].cols(); } }; } namespace rules { // TODO hack to make code look like references are implemented template struct FMPZ_POLY_MAT_VECXX_COND_S : mp::equal_types { }; #define FMPZ_POLY_MAT_VECXX_COND_T FMPZ_POLY_MAT_VECXX_COND_S // TODO references FLINT_DEFINE_GET(equals, bool, fmpz_poly_mat_vecxx, e1._data().equals(e2._data())) FLINT_DEFINE_UNARY_EXPR_COND(prod_op, fmpz_poly_matxx, FMPZ_POLY_MAT_VECXX_COND_S, fmpz_poly_mat_prod(to._mat(), (fmpz_poly_mat_t * const) from._array(), from.size())) } // rules } // flint #endif