* Implementation of symbolic matrices */
/*
- * GiNaC Copyright (C) 1999-2005 Johannes Gutenberg University Mainz, Germany
+ * GiNaC Copyright (C) 1999-2008 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
//////////
/** Default ctor. Initializes to 1 x 1-dimensional zero-matrix. */
-matrix::matrix() : inherited(TINFO_matrix), row(1), col(1), m(1, _ex0)
+matrix::matrix() : inherited(&matrix::tinfo_static), row(1), col(1), m(1, _ex0)
{
setflag(status_flags::not_shareable);
}
* @param r number of rows
* @param c number of cols */
matrix::matrix(unsigned r, unsigned c)
- : inherited(TINFO_matrix), row(r), col(c), m(r*c, _ex0)
+ : inherited(&matrix::tinfo_static), row(r), col(c), m(r*c, _ex0)
{
setflag(status_flags::not_shareable);
}
/** 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(&matrix::tinfo_static), row(r), col(c), m(m2)
{
setflag(status_flags::not_shareable);
}
* 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), m(r*c, _ex0)
+ : inherited(&matrix::tinfo_static), row(r), col(c), m(r*c, _ex0)
{
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);
- for (unsigned int i=0; true; i++) {
+ archive_node::archive_node_cit first = n.find_first("m");
+ archive_node::archive_node_cit last = n.find_last("m");
+ ++last;
+ for (archive_node::archive_node_cit i=first; i<last; ++i) {
ex e;
- if (n.find_ex("m", e, sym_lst, i))
- m.push_back(e);
- else
- break;
+ n.find_ex_by_loc(i, e, sym_lst);
+ m.push_back(e);
}
}
m2[r*col+c] = m[r*col+c].eval(level);
return (new matrix(row, col, m2))->setflag(status_flags::dynallocated |
- status_flags::evaluated);
+ status_flags::evaluated);
}
ex matrix::subs(const exmap & mp, unsigned options) const
return *this;
}
+ex matrix::real_part() const
+{
+ exvector v;
+ v.reserve(m.size());
+ for (exvector::const_iterator i=m.begin(); i!=m.end(); ++i)
+ v.push_back(i->real_part());
+ return matrix(row, col, v);
+}
+
+ex matrix::imag_part() const
+{
+ exvector v;
+ v.reserve(m.size());
+ for (exvector::const_iterator i=m.begin(); i!=m.end(); ++i)
+ v.push_back(i->imag_part());
+ return matrix(row, col, v);
+}
+
// protected
int matrix::compare_same_type(const basic & other) const
for (unsigned r1=0; r1<this->rows(); ++r1) {
for (unsigned c=0; c<this->cols(); ++c) {
+ // Quick test: can we shortcut?
if (m[r1*col+c].is_zero())
continue;
for (unsigned r2=0; r2<other.cols(); ++r2)
- prod[r1*other.col+r2] += (m[r1*col+c] * other.m[c*other.col+r2]).expand();
+ prod[r1*other.col+r2] += (m[r1*col+c] * other.m[c*other.col+r2]);
}
}
return matrix(row, other.col, prod);
unsigned sparse_count = 0; // counts non-zero elements
exvector::const_iterator r = m.begin(), rend = m.end();
while (r != rend) {
+ if (!r->info(info_flags::numeric))
+ numeric_flag = false;
exmap srl; // symbol replacement list
ex rtest = r->to_rational(srl);
if (!rtest.is_zero())
++sparse_count;
- if (!rtest.info(info_flags::numeric))
- numeric_flag = false;
if (!rtest.info(info_flags::crational_polynomial) &&
rtest.info(info_flags::rational_function))
normal_flag = true;
unsigned r0 = 0;
for (unsigned c0=0; c0<n && r0<m-1; ++c0) {
- int indx = tmp_n.pivot(r0, c0, true);
- if (indx==-1) {
+ // When trying to find a pivot, we should try a bit harder than expand().
+ // Searching the first non-zero element in-place here instead of calling
+ // pivot() allows us to do no more substitutions and back-substitutions
+ // than are actually necessary.
+ int indx = r0;
+ while ((indx<m) &&
+ (tmp_n[indx*n+c0].subs(srl, subs_options::no_pattern).expand().is_zero()))
+ ++indx;
+ if (indx==m) {
+ // all elements in column c0 below row r0 vanish
sign = 0;
if (det)
return 0;
- }
- if (indx>=0) {
- if (indx>0) {
+ } else {
+ if (indx>r0) {
+ // Matrix needs pivoting, swap rows r0 and indx of tmp_n and tmp_d.
sign = -sign;
- // tmp_n's rows r0 and indx were swapped, do the same in tmp_d:
- for (unsigned c=c0; c<n; ++c)
+ for (unsigned c=c0; c<n; ++c) {
+ tmp_n.m[n*indx+c].swap(tmp_n.m[n*r0+c]);
tmp_d.m[n*indx+c].swap(tmp_d.m[n*r0+c]);
+ }
}
for (unsigned r2=r0+1; r2<m; ++r2) {
for (unsigned c=c0+1; c<n; ++c) {
return k;
}
+/** Function to check that all elements of the matrix are zero.
+ */
+bool matrix::is_zero_matrix() const
+{
+ for (exvector::const_iterator i=m.begin(); i!=m.end(); ++i)
+ if(!(i->is_zero()))
+ return false;
+ return true;
+}
+
ex lst_to_matrix(const lst & l)
{
lst::const_iterator itr, itc;
return M;
}
+ex reduced_matrix(const matrix& m, unsigned r, unsigned c)
+{
+ if (r+1>m.rows() || c+1>m.cols() || m.cols()<2 || m.rows()<2)
+ throw std::runtime_error("minor_matrix(): index out of bounds");
+
+ const unsigned rows = m.rows()-1;
+ const unsigned cols = m.cols()-1;
+ matrix &M = *new matrix(rows, cols);
+ M.setflag(status_flags::dynallocated | status_flags::evaluated);
+
+ unsigned ro = 0;
+ unsigned ro2 = 0;
+ while (ro2<rows) {
+ if (ro==r)
+ ++ro;
+ unsigned co = 0;
+ unsigned co2 = 0;
+ while (co2<cols) {
+ if (co==c)
+ ++co;
+ M(ro2,co2) = m(ro, co);
+ ++co;
+ ++co2;
+ }
+ ++ro;
+ ++ro2;
+ }
+
+ return M;
+}
+
+ex sub_matrix(const matrix&m, unsigned r, unsigned nr, unsigned c, unsigned nc)
+{
+ if (r+nr>m.rows() || c+nc>m.cols())
+ throw std::runtime_error("sub_matrix(): index out of bounds");
+
+ matrix &M = *new matrix(nr, nc);
+ M.setflag(status_flags::dynallocated | status_flags::evaluated);
+
+ for (unsigned ro=0; ro<nr; ++ro) {
+ for (unsigned co=0; co<nc; ++co) {
+ M(ro,co) = m(ro+r,co+c);
+ }
+ }
+
+ return M;
+}
+
} // namespace GiNaC