* Implementation of symbolic matrices */
/*
- * GiNaC Copyright (C) 1999-2015 Johannes Gutenberg University Mainz, Germany
+ * GiNaC Copyright (C) 1999-2018 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
setflag(status_flags::not_shareable);
}
-// protected
-
-/** Ctor from representation, for internal use only. */
-matrix::matrix(unsigned r, unsigned c, const exvector & m2)
- : 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
}
}
+/** Construct a matrix from an 2 dimensional initializer list.
+ * Throws an exception if some row has a different length than all the others.
+ */
+matrix::matrix(std::initializer_list<std::initializer_list<ex>> l)
+ : row(l.size()), col(l.begin()->size())
+{
+ setflag(status_flags::not_shareable);
+
+ m.reserve(row*col);
+ for (const auto & r : l) {
+ unsigned c = 0;
+ for (const auto & e : r) {
+ m.push_back(e);
+ ++c;
+ }
+ if (c != col)
+ throw std::invalid_argument("matrix::matrix{{}}: wrong dimension");
+ }
+}
+
+// protected
+
+/** Ctor from representation, for internal use only. */
+matrix::matrix(unsigned r, unsigned c, const exvector & m2)
+ : row(r), col(c), m(m2)
+{
+ setflag(status_flags::not_shareable);
+}
+matrix::matrix(unsigned r, unsigned c, exvector && m2)
+ : row(r), col(c), m(std::move(m2))
+{
+ setflag(status_flags::not_shareable);
+}
+
//////////
// archiving
//////////
return m[i];
}
-/** Evaluate matrix entry by entry. */
-ex matrix::eval(int level) const
-{
- // check if we have to do anything at all
- if ((level==1)&&(flags & status_flags::evaluated))
- return *this;
-
- // emergency break
- if (level == -max_recursion_level)
- throw (std::runtime_error("matrix::eval(): recursion limit exceeded"));
-
- // eval() entry by entry
- exvector m2(row*col);
- --level;
- for (unsigned r=0; r<row; ++r)
- for (unsigned c=0; c<col; ++c)
- m2[r*col+c] = m[r*col+c].eval(level);
-
- return (new matrix(row, col, std::move(m2)))->setflag(status_flags::dynallocated |
- status_flags::evaluated);
-}
-
ex matrix::subs(const exmap & mp, unsigned options) const
{
exvector m2(row * col);
/** Inverse of this matrix.
*
+ * @param algo selects the algorithm (one of solve_algo)
* @return the inverted matrix
* @exception logic_error (matrix not square)
* @exception runtime_error (singular matrix) */
-matrix matrix::inverse() const
+matrix matrix::inverse(unsigned algo) const
{
if (row != col)
throw (std::logic_error("matrix::inverse(): matrix not square"));
matrix sol(row,col);
try {
- sol = this->solve(vars,identity);
+ sol = this->solve(vars, identity, algo);
} catch (const std::runtime_error & e) {
if (e.what()==std::string("matrix::solve(): inconsistent linear system"))
throw (std::runtime_error("matrix::inverse(): singular matrix"));
unsigned last_assigned_sol = n+1;
for (int r=m-1; r>=0; --r) {
unsigned fnz = 1; // first non-zero in row
- while ((fnz<=n) && (aug.m[r*(n+p)+(fnz-1)].is_zero()))
+ while ((fnz<=n) && (aug.m[r*(n+p)+(fnz-1)].normal().is_zero()))
++fnz;
if (fnz>n) {
// row consists only of zeros, corresponding rhs must be 0, too
- if (!aug.m[r*(n+p)+n+co].is_zero()) {
+ if (!aug.m[r*(n+p)+n+co].normal().is_zero()) {
throw (std::runtime_error("matrix::solve(): inconsistent linear system"));
}
} else {
for (unsigned j=fc; j<n-c; ++j)
Pkey[j] = Pkey[j-1]+1;
} while(fc);
- // next column, so change the role of A and B:
- A.swap(B);
- B.clear();
+ // next column, clear B and change the role of A and B:
+ A = std::move(B);
}
return det;
}
// Allocate and fill matrix
- matrix &M = *new matrix(rows, cols);
- M.setflag(status_flags::dynallocated);
+ matrix & M = dynallocate<matrix>(rows, cols);
unsigned i = 0;
for (auto & itr : l) {
size_t dim = l.nops();
// Allocate and fill matrix
- matrix &M = *new matrix(dim, dim);
- M.setflag(status_flags::dynallocated);
+ matrix & M = dynallocate<matrix>(dim, dim);
+
+ unsigned i = 0;
+ for (auto & it : l) {
+ M(i, i) = it;
+ ++i;
+ }
+
+ return M;
+}
+
+ex diag_matrix(std::initializer_list<ex> l)
+{
+ size_t dim = l.size();
+
+ // Allocate and fill matrix
+ matrix & M = dynallocate<matrix>(dim, dim);
unsigned i = 0;
for (auto & it : l) {
ex unit_matrix(unsigned r, unsigned c)
{
- matrix &Id = *new matrix(r, c);
- Id.setflag(status_flags::dynallocated);
+ matrix & Id = dynallocate<matrix>(r, c);
+ Id.setflag(status_flags::evaluated);
for (unsigned i=0; i<r && i<c; i++)
Id(i,i) = _ex1;
ex symbolic_matrix(unsigned r, unsigned c, const std::string & base_name, const std::string & tex_base_name)
{
- matrix &M = *new matrix(r, c);
- M.setflag(status_flags::dynallocated | status_flags::evaluated);
+ matrix & M = dynallocate<matrix>(r, c);
+ M.setflag(status_flags::evaluated);
bool long_format = (r > 10 || c > 10);
bool single_row = (r == 1 || c == 1);
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);
+ matrix & M = dynallocate<matrix>(rows, cols);
+ M.setflag(status_flags::evaluated);
unsigned ro = 0;
unsigned ro2 = 0;
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);
+ matrix & M = dynallocate<matrix>(nr, nc);
+ M.setflag(status_flags::evaluated);
for (unsigned ro=0; ro<nr; ++ro) {
for (unsigned co=0; co<nc; ++co) {