/*============================================================================= 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 FMPQ_MATXX_H #define FMPQ_MATXX_H FMPQ_MATXX_H #include "fmpq_mat.h" #include "fmpqxx.h" #include "fmpz_matxx.h" #include "fmpz_vecxx.h" #include "flintxx/ltuple.h" #include "flintxx/matrix.h" // TODO wrap entry_num, entry_den? // TODO numden_rowwise_2 // TODO rref members namespace flint { FLINT_DEFINE_BINOP(hilbert_matrix) FLINT_DEFINE_BINOP(mul_direct) FLINT_DEFINE_BINOP(mul_cleared) FLINT_DEFINE_BINOP(solve_fraction_free) FLINT_DEFINE_UNOP(numden_colwise) FLINT_DEFINE_UNOP(numden_entrywise) FLINT_DEFINE_UNOP(numden_matwise) FLINT_DEFINE_UNOP(numden_rowwise) FLINT_DEFINE_UNOP(num_rowwise) FLINT_DEFINE_UNOP(num_colwise) FLINT_DEFINE_UNOP(rref_classical) FLINT_DEFINE_UNOP(rref_fraction_free) namespace detail { template struct fmpq_matxx_traits : matrices::generic_traits { }; typedef make_ltuple::type>::type fmpq_matxx_numden_entrywise_rt; typedef make_ltuple::type>::type fmpq_matxx_numden_matwise_rt; typedef make_ltuple::type>::type fmpq_matxx_numden_rowwise_rt; typedef fmpq_matxx_numden_rowwise_rt fmpq_matxx_numden_colwise_rt; } // detail template class fmpq_matxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; typedef detail::fmpq_matxx_traits traits_t; FLINTXX_DEFINE_BASICS(fmpq_matxx_expression) FLINTXX_DEFINE_CTORS(fmpq_matxx_expression) FLINTXX_DEFINE_C_REF(fmpq_matxx_expression, fmpq_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) template static fmpq_matxx_expression reconstruct(const Fmpz_mat& mat, const Fmpz& mod, typename mp::enable_if >::type* = 0, typename mp::enable_if >::type* = 0) { fmpq_matxx_expression res(mat.rows(), mat.cols()); res.set_reconstruct(mat, mod); return res; } template static fmpq_matxx_expression frac(const Fmpz_mat& num, const Fmpz& den, typename mp::enable_if >::type* = 0, typename mp::enable_if >::type* = 0) { fmpq_matxx_expression res(num.rows(), num.cols()); res.set_frac(num, den); return res; } template static fmpq_matxx_expression integer_matrix(const Fmpz_mat& mat, typename mp::enable_if >::type* = 0) { fmpq_matxx_expression res(mat.rows(), mat.cols()); res = mat; return res; } static fmpq_matxx_expression randbits(slong rows, slong cols, frandxx& state, mp_bitcnt_t bits) { fmpq_matxx_expression res(rows, cols); res.set_randbits(state, bits); return res; } static fmpq_matxx_expression randtest(slong rows, slong cols, frandxx& state, mp_bitcnt_t bits) { fmpq_matxx_expression res(rows, cols); res.set_randtest(state, bits); return res; } static fmpq_matxx_expression zero(slong rows, slong cols) {return fmpq_matxx_expression(rows, cols);} static fmpq_matxx_expression one(slong rows, slong cols) { fmpq_matxx_expression res(rows, cols); res.set_one(); return res; } // these only make sense with targets void set_randbits(frandxx& state, mp_bitcnt_t bits) {fmpq_mat_randbits(_mat(), state._data(), bits);} void set_randtest(frandxx& state, mp_bitcnt_t bits) {fmpq_mat_randtest(_mat(), state._data(), bits);} void set_hilbert_matrix() {fmpq_mat_hilbert_matrix(_mat());} void set_zero() {fmpq_mat_zero(_mat());} void set_one() {fmpq_mat_one(_mat());} template void set_frac(const Fmpz_mat& num, const Fmpz& den, typename mp::enable_if >::type* = 0, typename mp::enable_if >::type* = 0) { fmpq_mat_set_fmpz_mat_div_fmpz(num.evaluate()._mat(), den.evaluate()._fmpz()); } template void set_reconstruct(const Fmpz_mat& mat, const Fmpz& mod, typename mp::enable_if >::type* = 0, typename mp::enable_if >::type* = 0) { execution_check(fmpq_mat_set_fmpz_mat_mod_fmpz( _mat(), mat.evaluate()._mat(), mod.evaluate()._fmpz()), "reconstruct", "fmpq_matxx"); } bool pivot(slong r, slong c, permxx* perm = 0) {return fmpq_mat_pivot(maybe_perm_data(perm), _mat(), r, c);} // these cause evaluation slong rank() const {return fmpq_mat_rank(this->evaluate()._mat());} bool is_zero() const {return fmpq_mat_is_zero(this->evaluate()._mat());} bool is_empty() const {return fmpq_mat_is_empty(this->evaluate()._mat());} bool is_square() const {return fmpq_mat_is_square(this->evaluate()._mat());} bool is_integral() const {return fmpq_mat_is_integral(this->evaluate()._mat());} // forwarded lazy ops FLINTXX_DEFINE_MEMBER_UNOP(inv) FLINTXX_DEFINE_MEMBER_UNOP(transpose) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpqxx, det) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpqxx, trace) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(detail::fmpq_matxx_numden_entrywise_rt, numden_entrywise) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(detail::fmpq_matxx_numden_matwise_rt, numden_matwise) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(detail::fmpq_matxx_numden_rowwise_rt, numden_rowwise) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(detail::fmpq_matxx_numden_colwise_rt, numden_colwise) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE_(fmpz_matxx, num_rowwise, num_rowwise) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE_(fmpz_matxx, num_colwise, num_colwise) FLINTXX_DEFINE_MEMBER_BINOP(mul_cleared) FLINTXX_DEFINE_MEMBER_BINOP(mul_direct) FLINTXX_DEFINE_MEMBER_BINOP(solve_dixon) FLINTXX_DEFINE_MEMBER_BINOP(solve_fraction_free) }; namespace detail { struct fmpq_mat_data; } // detail typedef fmpq_matxx_expression fmpq_matxx; typedef fmpq_matxx_expression > fmpq_matxx_ref; typedef fmpq_matxx_expression > fmpq_matxx_srcref; template<> struct matrix_traits { template static slong rows(const M& m) { return fmpq_mat_nrows(m._mat()); } template static slong cols(const M& m) { return fmpq_mat_ncols(m._mat()); } template static fmpqxx_srcref at(const M& m, slong i, slong j) { return fmpqxx_srcref::make(fmpq_mat_entry(m._mat(), i, j)); } template static fmpqxx_ref at(M& m, slong i, slong j) { return fmpqxx_ref::make(fmpq_mat_entry(m._mat(), i, j)); } }; namespace detail { template<> struct fmpq_matxx_traits : matrices::generic_traits_srcref { }; template<> struct fmpq_matxx_traits : matrices::generic_traits_ref { }; template<> struct fmpq_matxx_traits : matrices::generic_traits_nonref { }; struct fmpq_mat_data { typedef fmpq_mat_t& data_ref_t; typedef const fmpq_mat_t& data_srcref_t; fmpq_mat_t inner; fmpq_mat_data(slong m, slong n) { fmpq_mat_init(inner, m, n); } fmpq_mat_data(const fmpq_mat_data& o) { fmpq_mat_init(inner, fmpq_mat_nrows(o.inner), fmpq_mat_ncols(o.inner)); fmpq_mat_set(inner, o.inner); } fmpq_mat_data(fmpq_matxx_srcref o) { fmpq_mat_init(inner, o.rows(), o.cols()); fmpq_mat_set(inner, o._data().inner); } ~fmpq_mat_data() {fmpq_mat_clear(inner);} }; } // detail #define FMPQ_MATXX_COND_S FLINTXX_COND_S(fmpq_matxx) #define FMPQ_MATXX_COND_T FLINTXX_COND_T(fmpq_matxx) namespace traits { template struct is_fmpq_matxx : flint_classes::is_Base { }; } // traits namespace mp { template struct all_fmpq_matxx : mp::and_, all_fmpq_matxx > { }; template struct all_fmpq_matxx : traits::is_fmpq_matxx { }; template struct enable_all_fmpq_matxx : mp::enable_if, Out> { }; } // mp namespace matrices { template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize { template static slong rows(const Expr& e) {return e._data().first();} template static slong cols(const Expr& e) {return e._data().second();} }; template<> struct outsize { template static slong rows(const Expr& e) {return e._data().first().rows();} template static slong cols(const Expr& e) {return e._data().first().cols();} }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; } // matrices namespace vectors { template<> struct outsize { template static unsigned get(const Expr& e) { return e._data().first().rows(); } }; template<> struct outsize { template static unsigned get(const Expr& e) { return e._data().first().cols(); } }; } // vectors // temporary instantiation stuff FLINTXX_DEFINE_TEMPORARY_RULES(fmpq_matxx) namespace rules { FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_MATXX_COND_T, FMPQ_MATXX_COND_S, fmpq_mat_set(to._mat(), from._mat())) FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_MATXX_COND_T, FMPZ_MATXX_COND_S, fmpq_mat_set_fmpz_mat(to._mat(), from._mat())) FLINTXX_DEFINE_SWAP(fmpq_matxx, fmpq_mat_swap(e1._mat(), e2._mat())) FLINTXX_DEFINE_EQUALS(fmpq_matxx, fmpq_mat_equal(e1._mat(), e2._mat())) FLINT_DEFINE_PRINT_COND(FMPQ_MATXX_COND_S, (fmpq_mat_print(from._mat()), 1)) FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpq_matxx, FMPQ_MATXX_COND_S, FMPQ_MATXX_COND_S, fmpq_mat_mul(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpq_matxx, FMPZ_MATXX_COND_S, FMPQ_MATXX_COND_S, fmpq_mat_mul_r_fmpz_mat(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpq_matxx, FMPQ_MATXX_COND_S, FMPZ_MATXX_COND_S, fmpq_mat_mul_fmpz_mat(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpq_matxx, FMPQ_MATXX_COND_S, FMPZXX_COND_S, fmpq_mat_scalar_mul_fmpz(to._mat(), e1._mat(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpq_matxx, FMPQ_MATXX_COND_S, FMPZXX_COND_S, fmpq_mat_scalar_div_fmpz(to._mat(), e1._mat(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(mul_direct_op, fmpq_matxx, FMPQ_MATXX_COND_S, FMPQ_MATXX_COND_S, fmpq_mat_mul_direct(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(mul_cleared_op, fmpq_matxx, FMPQ_MATXX_COND_S, FMPQ_MATXX_COND_S, fmpq_mat_mul_cleared(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(plus, fmpq_matxx, FMPQ_MATXX_COND_S, FMPQ_MATXX_COND_S, fmpq_mat_add(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpq_matxx, FMPQ_MATXX_COND_S, FMPQ_MATXX_COND_S, fmpq_mat_sub(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_UNARY_EXPR_COND(negate, fmpq_matxx, FMPQ_MATXX_COND_S, fmpq_mat_neg(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(transpose_op, fmpq_matxx, FMPQ_MATXX_COND_S, fmpq_mat_transpose(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(trace_op, fmpqxx, FMPQ_MATXX_COND_S, fmpq_mat_trace(to._fmpq(), from._mat())) FLINT_DEFINE_THREEARY_EXPR_COND3(mat_at_op, fmpqxx, FMPQ_MATXX_COND_S, traits::fits_into_slong, traits::fits_into_slong, fmpq_set(to._fmpq(), fmpq_mat_entry(e1._mat(), e2, e3))) FLINT_DEFINE_BINARY_EXPR_COND2(hilbert_matrix_op, fmpq_matxx, traits::fits_into_slong, traits::fits_into_slong, to.set_hilbert_matrix()) FLINT_DEFINE_UNARY_EXPR_COND(det_op, fmpqxx, FMPQ_MATXX_COND_S, fmpq_mat_det(to._fmpq(), from._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(solve_fraction_free_op, fmpq_matxx, FMPQ_MATXX_COND_S, FMPQ_MATXX_COND_S, execution_check(fmpq_mat_solve_fraction_free( to._mat(), e1._mat(), e2._mat()), "solve", "fmpq_mat")) FLINT_DEFINE_BINARY_EXPR_COND2(solve_dixon_op, fmpq_matxx, FMPQ_MATXX_COND_S, FMPQ_MATXX_COND_S, execution_check(fmpq_mat_solve_dixon(to._mat(), e1._mat(), e2._mat()), "solve", "fmpq_mat")) FLINT_DEFINE_UNARY_EXPR_COND(inv_op, fmpq_matxx, FMPQ_MATXX_COND_S, execution_check(fmpq_mat_inv(to._mat(), from._mat()), "inv", "fmpq_mat")) FLINT_DEFINE_UNARY_EXPR_COND(num_rowwise_op, fmpz_matxx, FMPQ_MATXX_COND_S, fmpq_mat_get_fmpz_mat_rowwise(to._mat(), 0, from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(num_colwise_op, fmpz_matxx, FMPQ_MATXX_COND_S, fmpq_mat_get_fmpz_mat_colwise(to._mat(), 0, from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(numden_entrywise_op, detail::fmpq_matxx_numden_entrywise_rt, FMPQ_MATXX_COND_S, fmpq_mat_get_fmpz_mat_entrywise(to.template get<0>()._mat(), to.template get<1>()._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(numden_matwise_op, detail::fmpq_matxx_numden_matwise_rt, FMPQ_MATXX_COND_S, fmpq_mat_get_fmpz_mat_matwise(to.template get<0>()._mat(), to.template get<1>()._fmpz(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(numden_rowwise_op, detail::fmpq_matxx_numden_rowwise_rt, FMPQ_MATXX_COND_S, fmpq_mat_get_fmpz_mat_rowwise(to.template get<0>()._mat(), to.template get<1>()._array(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(numden_colwise_op, detail::fmpq_matxx_numden_colwise_rt, FMPQ_MATXX_COND_S, fmpq_mat_get_fmpz_mat_colwise(to.template get<0>()._mat(), to.template get<1>()._array(), from._mat())) namespace rdetail { typedef make_ltuple::type>::type fmpq_matxx_rref_rt; } FLINT_DEFINE_UNARY_EXPR_COND(rref_op, rdetail::fmpq_matxx_rref_rt, FMPQ_MATXX_COND_S, to.template get<0>() = fmpq_mat_rref(to.template get<1>()._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(rref_classical_op, rdetail::fmpq_matxx_rref_rt, FMPQ_MATXX_COND_S, to.template get<0>() = fmpq_mat_rref_classical(to.template get<1>()._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(rref_fraction_free_op, rdetail::fmpq_matxx_rref_rt, FMPQ_MATXX_COND_S, to.template get<0>() = fmpq_mat_rref_fraction_free(to.template get<1>()._mat(), from._mat())) } // rules } // flint #endif