X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fmatrix.cpp;h=2c191ff4f69c04d993b2724b16f13e13d445156e;hp=46d7a64cd9faa2330cca7a035e9782c2cb334da6;hb=d54e497297f4687c385ff8fbc91296365887c7c0;hpb=bf82f5b1d41738936afe763e1fa6aa347c81ba2c diff --git a/ginac/matrix.cpp b/ginac/matrix.cpp index 46d7a64c..2c191ff4 100644 --- a/ginac/matrix.cpp +++ b/ginac/matrix.cpp @@ -3,7 +3,7 @@ * Implementation of symbolic matrices */ /* - * GiNaC Copyright (C) 1999-2002 Johannes Gutenberg University Mainz, Germany + * GiNaC Copyright (C) 1999-2003 Johannes Gutenberg University Mainz, Germany * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,39 +32,34 @@ #include "lst.h" #include "idx.h" #include "indexed.h" +#include "add.h" #include "power.h" #include "symbol.h" +#include "operators.h" #include "normal.h" -#include "print.h" #include "archive.h" #include "utils.h" namespace GiNaC { -GINAC_IMPLEMENT_REGISTERED_CLASS(matrix, basic) +GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(matrix, basic, + print_func(&matrix::do_print). + print_func(&matrix::do_print_latex). + print_func(&basic::do_print_tree). + print_func(&matrix::do_print_python_repr)) ////////// -// default ctor, dtor, copy ctor, assignment operator and helpers: +// default constructor ////////// /** Default ctor. Initializes to 1 x 1-dimensional zero-matrix. */ -matrix::matrix() : inherited(TINFO_matrix), row(1), col(1) +matrix::matrix() : inherited(TINFO_matrix), row(1), col(1), m(1, _ex0) { - m.push_back(_ex0); + setflag(status_flags::not_shareable); } -void matrix::copy(const matrix & other) -{ - inherited::copy(other); - row = other.row; - col = other.col; - m = other.m; // STL's vector copying invoked here -} - -DEFAULT_DESTROY(matrix) - ////////// -// other ctors +// other constructors ////////// // public @@ -74,32 +69,36 @@ DEFAULT_DESTROY(matrix) * @param r number of rows * @param c number of cols */ matrix::matrix(unsigned r, unsigned c) - : inherited(TINFO_matrix), row(r), col(c) + : inherited(TINFO_matrix), row(r), col(c), m(r*c, _ex0) { - m.resize(r*c, _ex0); + setflag(status_flags::not_shareable); } // 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) {} + : inherited(TINFO_matrix), row(r), col(c), m(m2) +{ + setflag(status_flags::not_shareable); +} /** Construct matrix from (flat) list of elements. If the list has fewer * elements than the matrix, the remaining matrix elements are set to zero. * If the list has more elements than the matrix, the excessive elements are * thrown away. */ matrix::matrix(unsigned r, unsigned c, const lst & l) - : inherited(TINFO_matrix), row(r), col(c) + : inherited(TINFO_matrix), row(r), col(c), m(r*c, _ex0) { - m.resize(r*c, _ex0); + setflag(status_flags::not_shareable); - for (unsigned i=0; i= r) break; // matrix smaller than list: throw away excessive elements - m[y*c+x] = l.op(i); + m[y*c+x] = *it; } } @@ -107,8 +106,10 @@ matrix::matrix(unsigned r, unsigned c, const lst & l) // archiving ////////// -matrix::matrix(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) +matrix::matrix(const archive_node &n, lst &sym_lst) : inherited(n, sym_lst) { + setflag(status_flags::not_shareable); + if (!(n.find_unsigned("row", row)) || !(n.find_unsigned("col", col))) throw (std::runtime_error("unknown matrix dimensions in archive")); m.reserve(row * col); @@ -141,74 +142,63 @@ DEFAULT_UNARCHIVE(matrix) // public -void matrix::print(const print_context & c, unsigned level) const +void matrix::print_elements(const print_context & c, const char *row_start, const char *row_end, const char *row_sep, const char *col_sep) const { - if (is_a(c)) { - - inherited::print(c, level); - - } else { - - if (is_a(c)) - c.s << class_name() << '('; - - if (is_a(c)) - c.s << "\\left(\\begin{array}{" << std::string(col,'c') << "}"; - else - c.s << "["; - - for (unsigned ro=0; ro(c)) - c.s << "["; - for (unsigned co=0; co(c)) - c.s << "&"; - else - c.s << ","; - } else { - if (!is_a(c)) - c.s << "]"; - } - } - if (ro(c)) - c.s << "\\\\"; - else - c.s << ","; - } + for (unsigned ro=0; ro(c)) - c.s << "\\end{array}\\right)"; - else - c.s << "]"; +void matrix::do_print(const print_context & c, unsigned level) const +{ + c.s << "["; + print_elements(c, "[", "]", ",", ","); + c.s << "]"; +} - if (is_a(c)) - c.s << ')'; +void matrix::do_print_latex(const print_latex & c, unsigned level) const +{ + c.s << "\\left(\\begin{array}{" << std::string(col,'c') << "}"; + print_elements(c, "", "", "\\\\", "&"); + c.s << "\\end{array}\\right)"; +} - } +void matrix::do_print_python_repr(const print_python_repr & c, unsigned level) const +{ + c.s << class_name() << '('; + print_elements(c, "[", "]", ",", ","); + c.s << ')'; } /** nops is defined to be rows x columns. */ -unsigned matrix::nops() const +size_t matrix::nops() const { - return row*col; + return static_cast(row) * static_cast(col); } /** returns matrix entry at position (i/col, i%col). */ -ex matrix::op(int i) const +ex matrix::op(size_t i) const { + GINAC_ASSERT(i=0); GINAC_ASSERT(i(other.op(0))) { GINAC_ASSERT(other.nops() == 2 || other.nops() == 3); const matrix &self_matrix = ex_to(self.op(0)); @@ -418,7 +408,7 @@ bool matrix::contract_with(exvector::iterator self, exvector::iterator other, ex GINAC_ASSERT(is_a(self->op(0))); // Only contract with other matrices - if (!is_ex_of_type(other->op(0), matrix)) + if (!is_a(other->op(0))) return false; GINAC_ASSERT(other->nops() == 2 || other->nops() == 3); @@ -607,7 +597,7 @@ matrix matrix::pow(const ex & expn) const if (col!=row) throw (std::logic_error("matrix::pow(): matrix not square")); - if (is_ex_exactly_of_type(expn, numeric)) { + if (is_exactly_a(expn)) { // 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)) { @@ -675,7 +665,7 @@ ex & matrix::operator() (unsigned ro, unsigned co) /** Transposed of an m x n matrix, producing a new n x m matrix object that * represents the transposed. */ -matrix matrix::transpose(void) const +matrix matrix::transpose() const { exvector trans(this->cols()*this->rows()); @@ -712,7 +702,7 @@ ex matrix::determinant(unsigned algo) const unsigned sparse_count = 0; // counts non-zero elements exvector::const_iterator r = m.begin(), rend = m.end(); while (r != rend) { - lst srl; // symbol replacement list + exmap srl; // symbol replacement list ex rtest = r->to_rational(srl); if (!rtest.is_zero()) ++sparse_count; @@ -832,7 +822,7 @@ ex matrix::determinant(unsigned algo) const * * @return the sum of diagonal elements * @exception logic_error (matrix not square) */ -ex matrix::trace(void) const +ex matrix::trace() const { if (row != col) throw (std::logic_error("matrix::trace(): matrix not square")); @@ -860,7 +850,7 @@ ex matrix::trace(void) const * @return characteristic polynomial as new expression * @exception logic_error (matrix not square) * @see matrix::determinant() */ -ex matrix::charpoly(const symbol & lambda) const +ex matrix::charpoly(const ex & lambda) const { if (row != col) throw (std::logic_error("matrix::charpoly(): matrix not square")); @@ -877,27 +867,30 @@ ex matrix::charpoly(const symbol & lambda) const // trapped and we use Leverrier's algorithm which goes as row^3 for // every coefficient. The expensive part is the matrix multiplication. if (numeric_flag) { + matrix B(*this); ex c = B.trace(); - ex poly = power(lambda,row)-c*power(lambda,row-1); + ex poly = power(lambda, row) - c*power(lambda, row-1); for (unsigned i=1; imul(B); - c = B.trace()/ex(i+1); - poly -= c*power(lambda,row-i-1); + c = B.trace() / ex(i+1); + poly -= c*power(lambda, row-i-1); } if (row%2) return -poly; else return poly; - } + + } else { - matrix M(*this); - for (unsigned r=0; rcols(); @@ -1290,7 +1284,7 @@ int matrix::fraction_free_elimination(const bool det) // // Bareiss (fraction-free) elimination in addition divides that element // by m[k-1](k-1,k-1) for k>1, where it can be shown by means of the - // Sylvester determinant that this really divides m[k+1](r,c). + // Sylvester identity that this really divides m[k+1](r,c). // // We also allow rational functions where the original prove still holds. // However, we must care for numerator and denominator separately and @@ -1327,7 +1321,7 @@ int matrix::fraction_free_elimination(const bool det) // makes things more complicated than they need to be. matrix tmp_n(*this); matrix tmp_d(m,n); // for denominators, if needed - lst srl; // symbol replacement list + exmap srl; // symbol replacement list 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) { @@ -1390,7 +1384,7 @@ int matrix::fraction_free_elimination(const bool det) tmp_n_it = tmp_n.m.begin(); tmp_d_it = tmp_d.m.begin(); while (it != itend) - *it++ = ((*tmp_n_it++)/(*tmp_d_it++)).subs(srl); + *it++ = ((*tmp_n_it++)/(*tmp_d_it++)).subs(srl, subs_options::no_pattern); return sign; } @@ -1449,41 +1443,54 @@ int matrix::pivot(unsigned ro, unsigned co, bool symbolic) ex lst_to_matrix(const lst & l) { + lst::const_iterator itr, itc; + // Find number of rows and columns - unsigned rows = l.nops(), cols = 0, i, j; - for (i=0; i cols) - cols = l.op(i).nops(); + size_t rows = l.nops(), cols = 0; + for (itr = l.begin(); itr != l.end(); ++itr) { + if (!is_a(*itr)) + throw (std::invalid_argument("lst_to_matrix: argument must be a list of lists")); + if (itr->nops() > cols) + cols = itr->nops(); + } // Allocate and fill matrix matrix &M = *new matrix(rows, cols); M.setflag(status_flags::dynallocated); - for (i=0; i j) - M(i, j) = l.op(i).op(j); - else - M(i, j) = _ex0; + + unsigned i; + for (itr = l.begin(), i = 0; itr != l.end(); ++itr, ++i) { + unsigned j; + for (itc = ex_to(*itr).begin(), j = 0; itc != ex_to(*itr).end(); ++itc, ++j) + M(i, j) = *itc; + } + return M; } ex diag_matrix(const lst & l) { - unsigned dim = l.nops(); + lst::const_iterator it; + size_t dim = l.nops(); + + // Allocate and fill matrix + matrix &M = *new matrix(dim, dim); + M.setflag(status_flags::dynallocated); - matrix &m = *new matrix(dim, dim); - m.setflag(status_flags::dynallocated); - for (unsigned i=0; i