X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fmatrix.cpp;h=0bedb6bb1a1e506fc0017ea3243d66c64ed3797a;hp=1f2e0ea8c655f80968c9096ea392f7ec0de00e71;hb=274c1632d78ec31575c4b3b328d75ad95a7855aa;hpb=c5ca06e3a25226684028dec4bd8cba0833998be6 diff --git a/ginac/matrix.cpp b/ginac/matrix.cpp index 1f2e0ea8..0bedb6bb 100644 --- a/ginac/matrix.cpp +++ b/ginac/matrix.cpp @@ -20,6 +20,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include #include @@ -35,7 +36,6 @@ #include "print.h" #include "archive.h" #include "utils.h" -#include "debugmsg.h" namespace GiNaC { @@ -48,8 +48,7 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(matrix, basic) /** Default ctor. Initializes to 1 x 1-dimensional zero-matrix. */ matrix::matrix() : inherited(TINFO_matrix), row(1), col(1) { - debugmsg("matrix default ctor",LOGLEVEL_CONSTRUCT); - m.push_back(_ex0()); + m.push_back(_ex0); } void matrix::copy(const matrix & other) @@ -75,18 +74,14 @@ DEFAULT_DESTROY(matrix) matrix::matrix(unsigned r, unsigned c) : inherited(TINFO_matrix), row(r), col(c) { - debugmsg("matrix ctor from unsigned,unsigned",LOGLEVEL_CONSTRUCT); - m.resize(r*c, _ex0()); + m.resize(r*c, _ex0); } // protected /** Ctor from representation, for internal use only. */ matrix::matrix(unsigned r, unsigned c, const exvector & m2) - : inherited(TINFO_matrix), row(r), col(c), m(m2) -{ - debugmsg("matrix ctor from unsigned,unsigned,exvector",LOGLEVEL_CONSTRUCT); -} + : inherited(TINFO_matrix), row(r), col(c), m(m2) {} /** Construct matrix from (flat) list of elements. If the list has fewer * elements than the matrix, the remaining matrix elements are set to zero. @@ -95,8 +90,7 @@ matrix::matrix(unsigned r, unsigned c, const exvector & m2) matrix::matrix(unsigned r, unsigned c, const lst & l) : inherited(TINFO_matrix), row(r), col(c) { - debugmsg("matrix ctor from unsigned,unsigned,lst",LOGLEVEL_CONSTRUCT); - m.resize(r*c, _ex0()); + m.resize(r*c, _ex0); for (unsigned i=0; i(c)) { inherited::print(c, level); } else { + if (is_a(c)) + c.s << class_name() << '('; + c.s << "["; for (unsigned y=0; y(c)) + c.s << ')'; + } } @@ -198,21 +195,9 @@ ex & matrix::let_op(int i) return m[i]; } -/** expands the elements of a matrix entry by entry. */ -ex matrix::expand(unsigned options) const -{ - exvector tmp(row*col); - for (unsigned i=0; ibasic::subs(ls, lr, no_pattern); + return matrix(row, col, m2).basic::subs(ls, lr, no_pattern); } // protected int matrix::compare_same_type(const basic & other) const { - GINAC_ASSERT(is_exactly_of_type(other, matrix)); - const matrix & o = static_cast(const_cast(other)); + GINAC_ASSERT(is_exactly_a(other)); + const matrix &o = static_cast(other); // compare number of rows if (row != o.rows()) @@ -293,11 +254,21 @@ int matrix::compare_same_type(const basic & other) const return 0; } +bool matrix::match_same_type(const basic & other) const +{ + GINAC_ASSERT(is_exactly_a(other)); + const matrix & o = static_cast(other); + + // The number of rows and columns must be the same. This is necessary to + // prevent a 2x3 matrix from matching a 3x2 one. + return row == o.rows() && col == o.cols(); +} + /** Automatic symbolic evaluation of an indexed matrix. */ ex matrix::eval_indexed(const basic & i) const { - GINAC_ASSERT(is_of_type(i, indexed)); - GINAC_ASSERT(is_ex_of_type(i.op(0), matrix)); + GINAC_ASSERT(is_a(i)); + GINAC_ASSERT(is_a(i.op(0))); bool all_indices_unsigned = static_cast(i).all_index_values_are(info_flags::nonnegint); @@ -308,7 +279,7 @@ ex matrix::eval_indexed(const basic & i) const if (row != 1 && col != 1) throw (std::runtime_error("matrix::eval_indexed(): vector must have exactly 1 index")); - const idx & i1 = ex_to_idx(i.op(1)); + const idx & i1 = ex_to(i.op(1)); if (col == 1) { @@ -318,7 +289,7 @@ ex matrix::eval_indexed(const basic & i) const // Index numeric -> return vector element if (all_indices_unsigned) { - unsigned n1 = ex_to_numeric(i1.get_value()).to_int(); + unsigned n1 = ex_to(i1.get_value()).to_int(); if (n1 >= row) throw (std::runtime_error("matrix::eval_indexed(): value of index exceeds number of vector elements")); return (*this)(n1, 0); @@ -332,7 +303,7 @@ ex matrix::eval_indexed(const basic & i) const // Index numeric -> return vector element if (all_indices_unsigned) { - unsigned n1 = ex_to_numeric(i1.get_value()).to_int(); + unsigned n1 = ex_to(i1.get_value()).to_int(); if (n1 >= col) throw (std::runtime_error("matrix::eval_indexed(): value of index exceeds number of vector elements")); return (*this)(0, n1); @@ -342,8 +313,8 @@ ex matrix::eval_indexed(const basic & i) const } else if (i.nops() == 3) { // Two indices - const idx & i1 = ex_to_idx(i.op(1)); - const idx & i2 = ex_to_idx(i.op(2)); + const idx & i1 = ex_to(i.op(1)); + const idx & i2 = ex_to(i.op(2)); if (!i1.get_dim().is_equal(row)) throw (std::runtime_error("matrix::eval_indexed(): dimension of first index must match number of rows")); @@ -356,7 +327,7 @@ ex matrix::eval_indexed(const basic & i) const // Both indices numeric -> return matrix element if (all_indices_unsigned) { - unsigned n1 = ex_to_numeric(i1.get_value()).to_int(), n2 = ex_to_numeric(i2.get_value()).to_int(); + unsigned n1 = ex_to(i1.get_value()).to_int(), n2 = ex_to(i2.get_value()).to_int(); if (n1 >= row) throw (std::runtime_error("matrix::eval_indexed(): value of first index exceeds number of rows")); if (n2 >= col) @@ -373,17 +344,17 @@ ex matrix::eval_indexed(const basic & i) const /** Sum of two indexed matrices. */ ex matrix::add_indexed(const ex & self, const ex & other) const { - GINAC_ASSERT(is_ex_of_type(self, indexed)); - GINAC_ASSERT(is_ex_of_type(self.op(0), matrix)); - GINAC_ASSERT(is_ex_of_type(other, indexed)); + GINAC_ASSERT(is_a(self)); + GINAC_ASSERT(is_a(self.op(0))); + GINAC_ASSERT(is_a(other)); GINAC_ASSERT(self.nops() == 2 || self.nops() == 3); // Only add two matrices if (is_ex_of_type(other.op(0), matrix)) { GINAC_ASSERT(other.nops() == 2 || other.nops() == 3); - const matrix &self_matrix = ex_to_matrix(self.op(0)); - const matrix &other_matrix = ex_to_matrix(other.op(0)); + const matrix &self_matrix = ex_to(self.op(0)); + const matrix &other_matrix = ex_to(other.op(0)); if (self.nops() == 2 && other.nops() == 2) { // vector + vector @@ -409,11 +380,11 @@ ex matrix::add_indexed(const ex & self, const ex & other) const /** Product of an indexed matrix with a number. */ ex matrix::scalar_mul_indexed(const ex & self, const numeric & other) const { - GINAC_ASSERT(is_ex_of_type(self, indexed)); - GINAC_ASSERT(is_ex_of_type(self.op(0), matrix)); + GINAC_ASSERT(is_a(self)); + GINAC_ASSERT(is_a(self.op(0))); GINAC_ASSERT(self.nops() == 2 || self.nops() == 3); - const matrix &self_matrix = ex_to_matrix(self.op(0)); + const matrix &self_matrix = ex_to(self.op(0)); if (self.nops() == 2) return indexed(self_matrix.mul(other), self.op(1)); @@ -424,10 +395,10 @@ ex matrix::scalar_mul_indexed(const ex & self, const numeric & other) const /** Contraction of an indexed matrix with something else. */ bool matrix::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const { - GINAC_ASSERT(is_ex_of_type(*self, indexed)); - GINAC_ASSERT(is_ex_of_type(*other, indexed)); + GINAC_ASSERT(is_a(*self)); + GINAC_ASSERT(is_a(*other)); GINAC_ASSERT(self->nops() == 2 || self->nops() == 3); - GINAC_ASSERT(is_ex_of_type(self->op(0), matrix)); + GINAC_ASSERT(is_a(self->op(0))); // Only contract with other matrices if (!is_ex_of_type(other->op(0), matrix)) @@ -435,14 +406,12 @@ bool matrix::contract_with(exvector::iterator self, exvector::iterator other, ex GINAC_ASSERT(other->nops() == 2 || other->nops() == 3); - const matrix &self_matrix = ex_to_matrix(self->op(0)); - const matrix &other_matrix = ex_to_matrix(other->op(0)); + const matrix &self_matrix = ex_to(self->op(0)); + const matrix &other_matrix = ex_to(other->op(0)); if (self->nops() == 2) { - unsigned self_dim = (self_matrix.col == 1) ? self_matrix.row : self_matrix.col; if (other->nops() == 2) { // vector * vector (scalar product) - unsigned other_dim = (other_matrix.col == 1) ? other_matrix.row : other_matrix.col; if (self_matrix.col == 1) { if (other_matrix.col == 1) { @@ -461,7 +430,7 @@ bool matrix::contract_with(exvector::iterator self, exvector::iterator other, ex *self = self_matrix.mul(other_matrix.transpose())(0, 0); } } - *other = _ex1(); + *other = _ex1; return true; } else { // vector * matrix @@ -472,7 +441,7 @@ bool matrix::contract_with(exvector::iterator self, exvector::iterator other, ex *self = indexed(self_matrix.mul(other_matrix), other->op(2)); else *self = indexed(self_matrix.transpose().mul(other_matrix), other->op(2)); - *other = _ex1(); + *other = _ex1; return true; } @@ -482,7 +451,7 @@ bool matrix::contract_with(exvector::iterator self, exvector::iterator other, ex *self = indexed(other_matrix.mul(self_matrix), other->op(1)); else *self = indexed(other_matrix.mul(self_matrix.transpose()), other->op(1)); - *other = _ex1(); + *other = _ex1; return true; } } @@ -492,28 +461,28 @@ bool matrix::contract_with(exvector::iterator self, exvector::iterator other, ex // A_ij * B_jk = (A*B)_ik if (is_dummy_pair(self->op(2), other->op(1))) { *self = indexed(self_matrix.mul(other_matrix), self->op(1), other->op(2)); - *other = _ex1(); + *other = _ex1; return true; } // A_ij * B_kj = (A*Btrans)_ik if (is_dummy_pair(self->op(2), other->op(2))) { *self = indexed(self_matrix.mul(other_matrix.transpose()), self->op(1), other->op(1)); - *other = _ex1(); + *other = _ex1; return true; } // A_ji * B_jk = (Atrans*B)_ik if (is_dummy_pair(self->op(1), other->op(1))) { *self = indexed(self_matrix.transpose().mul(other_matrix), self->op(2), other->op(2)); - *other = _ex1(); + *other = _ex1; return true; } // A_ji * B_kj = (B*A)_ki if (is_dummy_pair(self->op(1), other->op(2))) { *self = indexed(other_matrix.mul(self_matrix), other->op(1), self->op(2)); - *other = _ex1(); + *other = _ex1; return true; } } @@ -537,10 +506,10 @@ matrix matrix::add(const matrix & other) const throw std::logic_error("matrix::add(): incompatible matrices"); exvector sum(this->m); - exvector::iterator i; - exvector::const_iterator ci; - for (i=sum.begin(), ci=other.m.begin(); i!=sum.end(); ++i, ++ci) - (*i) += (*ci); + exvector::iterator i = sum.begin(), end = sum.end(); + exvector::const_iterator ci = other.m.begin(); + while (i != end) + *i++ += *ci++; return matrix(row,col,sum); } @@ -555,10 +524,10 @@ matrix matrix::sub(const matrix & other) const throw std::logic_error("matrix::sub(): incompatible matrices"); exvector dif(this->m); - exvector::iterator i; - exvector::const_iterator ci; - for (i=dif.begin(), ci=other.m.begin(); i!=dif.end(); ++i, ++ci) - (*i) -= (*ci); + exvector::iterator i = dif.begin(), end = dif.end(); + exvector::const_iterator ci = other.m.begin(); + while (i != end) + *i++ -= *ci++; return matrix(row,col,dif); } @@ -625,32 +594,31 @@ matrix matrix::pow(const ex & expn) const // Integer cases are computed by successive multiplication, using the // obvious shortcut of storing temporaries, like A^4 == (A*A)*(A*A). if (expn.info(info_flags::integer)) { - numeric k; - matrix prod(row,col); + numeric b = ex_to(expn); + matrix A(row,col); if (expn.info(info_flags::negative)) { - k = -ex_to_numeric(expn); - prod = this->inverse(); + b *= -1; + A = this->inverse(); } else { - k = ex_to_numeric(expn); - prod = *this; + A = *this; } - matrix result(row,col); + matrix C(row,col); for (unsigned r=0; rto_rational(srl); if (!rtest.is_zero()) ++sparse_count; if (!rtest.info(info_flags::numeric)) @@ -733,6 +702,7 @@ ex matrix::determinant(unsigned algo) const if (!rtest.info(info_flags::crational_polynomial) && rtest.info(info_flags::rational_function)) normal_flag = true; + ++r; } // Here is the heuristics in case this routine has to decide: @@ -785,7 +755,7 @@ ex matrix::determinant(unsigned algo) const int sign; sign = tmp.division_free_elimination(true); if (sign==0) - return _ex0(); + return _ex0; ex det = tmp.m[row*col-1]; // factor out accumulated bogus slag for (unsigned d=0; d uintpair; std::vector c_zeros; // number of zeros in column for (unsigned c=0; c pre_sort; - for (std::vector::iterator i=c_zeros.begin(); i!=c_zeros.end(); ++i) + for (std::vector::const_iterator i=c_zeros.begin(); i!=c_zeros.end(); ++i) pre_sort.push_back(i->second); std::vector pre_sort_test(pre_sort); // permutation_sign() modifies the vector so we make a copy here int sign = permutation_sign(pre_sort_test.begin(), pre_sort_test.end()); exvector result(row*col); // represents sorted matrix unsigned c = 0; - for (std::vector::iterator i=pre_sort.begin(); + for (std::vector::const_iterator i=pre_sort.begin(); i!=pre_sort.end(); ++i,++c) { for (unsigned r=0; rinfo(info_flags::numeric)) numeric_flag = false; - } + ++r; } // The pure numeric case is traditionally rather common. Hence, it is @@ -924,7 +898,7 @@ matrix matrix::inverse(void) const // First populate the identity matrix supposed to become the right hand side. matrix identity(row,col); for (unsigned i=0; iinfo(info_flags::numeric)) numeric_flag = false; + ++r; } // Here is the heuristics in case this routine has to decide: @@ -1133,7 +1109,7 @@ ex matrix::determinant_minor(void) const Pkey.push_back(i); unsigned fc = 0; // controls logic for our strange flipper counter do { - det = _ex0(); + det = _ex0; for (unsigned r=0; rm[r2*n+c] = _ex0(); + this->m[r2*n+c] = _ex0; } if (det) { // save space by deleting no longer needed elements for (unsigned c=r0+1; cm[r0*n+c] = _ex0(); + this->m[r0*n+c] = _ex0; } ++r0; } @@ -1260,12 +1236,12 @@ int matrix::division_free_elimination(const bool det) this->m[r2*n+c] = (this->m[r0*n+r1]*this->m[r2*n+c] - this->m[r2*n+r1]*this->m[r0*n+c]).expand(); // fill up left hand side with zeros for (unsigned c=0; c<=r1; ++c) - this->m[r2*n+c] = _ex0(); + this->m[r2*n+c] = _ex0; } if (det) { // save space by deleting no longer needed elements for (unsigned c=r0+1; cm[r0*n+c] = _ex0(); + this->m[r0*n+c] = _ex0; } ++r0; } @@ -1333,13 +1309,13 @@ int matrix::fraction_free_elimination(const bool det) matrix tmp_n(*this); matrix tmp_d(m,n); // for denominators, if needed lst srl; // symbol replacement list - exvector::iterator it = this->m.begin(); - exvector::iterator tmp_n_it = tmp_n.m.begin(); - exvector::iterator tmp_d_it = tmp_d.m.begin(); - for (; it!= this->m.end(); ++it, ++tmp_n_it, ++tmp_d_it) { - (*tmp_n_it) = (*it).normal().to_rational(srl); - (*tmp_d_it) = (*tmp_n_it).denom(); - (*tmp_n_it) = (*tmp_n_it).numer(); + exvector::const_iterator cit = this->m.begin(), citend = this->m.end(); + exvector::iterator tmp_n_it = tmp_n.m.begin(), tmp_d_it = tmp_d.m.begin(); + while (cit != citend) { + ex nd = cit->normal().to_rational(srl).numer_denom(); + ++cit; + *tmp_n_it++ = nd.op(0); + *tmp_d_it++ = nd.op(1); } unsigned r0 = 0; @@ -1373,7 +1349,7 @@ int matrix::fraction_free_elimination(const bool det) } // fill up left hand side with zeros for (unsigned c=0; c<=r1; ++c) - tmp_n.m[r2*n+c] = _ex0(); + tmp_n.m[r2*n+c] = _ex0; } if ((r1m.begin(); + exvector::iterator it = this->m.begin(), itend = this->m.end(); tmp_n_it = tmp_n.m.begin(); tmp_d_it = tmp_d.m.begin(); - for (; it!= this->m.end(); ++it, ++tmp_n_it, ++tmp_d_it) - (*it) = ((*tmp_n_it)/(*tmp_d_it)).subs(srl); + while (it != itend) + *it++ = ((*tmp_n_it++)/(*tmp_d_it++)).subs(srl); return sign; } @@ -1423,12 +1399,12 @@ int matrix::pivot(unsigned ro, unsigned co, bool symbolic) ++k; } else { // search largest element in column co beginning at row ro - GINAC_ASSERT(is_ex_of_type(this->m[k*col+co],numeric)); + GINAC_ASSERT(is_a(this->m[k*col+co])); unsigned kmax = k+1; - numeric mmax = abs(ex_to_numeric(m[kmax*col+co])); + numeric mmax = abs(ex_to(m[kmax*col+co])); while (kmaxm[kmax*col+co],numeric)); - numeric tmp = ex_to_numeric(this->m[kmax*col+co]); + GINAC_ASSERT(is_a(this->m[kmax*col+co])); + numeric tmp = ex_to(this->m[kmax*col+co]); if (abs(tmp) > mmax) { mmax = tmp; k = kmax; @@ -1468,7 +1444,7 @@ ex lst_to_matrix(const lst & l) if (l.op(i).nops() > j) m(i, j) = l.op(i).op(j); else - m(i, j) = _ex0(); + m(i, j) = _ex0; return m; }