X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?a=blobdiff_plain;f=ginac%2Fmatrix.cpp;h=c9b3521a4665cdd8f210782809e244288de7efa1;hb=b66548802c56b34d6b212a0196d622937841ca61;hp=eaf4468a33742248ea252add319d5a522e6bc5d3;hpb=1a75b1adc0e425989d9d3bf1b208411b738b9672;p=ginac.git diff --git a/ginac/matrix.cpp b/ginac/matrix.cpp index eaf4468a..c9b3521a 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,19 +32,24 @@ #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. */ @@ -53,18 +58,8 @@ matrix::matrix() : inherited(TINFO_matrix), row(1), col(1) m.push_back(_ex0); } -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 @@ -94,12 +89,13 @@ matrix::matrix(unsigned r, unsigned c, const lst & l) { m.resize(r*c, _ex0); - 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,7 +103,7 @@ 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) { if (!(n.find_unsigned("row", row)) || !(n.find_unsigned("col", col))) throw (std::runtime_error("unknown matrix dimensions in archive")); @@ -141,74 +137,63 @@ DEFAULT_UNARCHIVE(matrix) // public -void matrix::print(const print_context & c, unsigned level) const +void matrix::print_elements(const print_context & c, const std::string & row_start, const std::string & row_end, const std::string & row_sep, const std::string & 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 +403,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 +592,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 +660,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()); @@ -832,7 +817,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")); @@ -877,6 +862,7 @@ 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); @@ -884,20 +870,22 @@ ex matrix::charpoly(const symbol & lambda) const for (unsigned j=0; jmul(B); - c = B.trace()/ex(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 +1278,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 @@ -1390,7 +1378,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; } @@ -1418,11 +1406,11 @@ int matrix::pivot(unsigned ro, unsigned co, bool symbolic) ++k; } else { // search largest element in column co beginning at row ro - GINAC_ASSERT(is_a(this->m[k*col+co])); + GINAC_ASSERT(is_exactly_a(this->m[k*col+co])); unsigned kmax = k+1; numeric mmax = abs(ex_to(m[kmax*col+co])); while (kmax(this->m[kmax*col+co])); + GINAC_ASSERT(is_exactly_a(this->m[kmax*col+co])); numeric tmp = ex_to(this->m[kmax*col+co]); if (abs(tmp) > mmax) { mmax = tmp; @@ -1449,41 +1437,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(); - matrix &m = *new matrix(dim, dim); - m.setflag(status_flags::dynallocated); - for (unsigned i=0; i