]> www.ginac.de Git - ginac.git/blobdiff - ginac/matrix.cpp
* Methods of class ex which do absolutely nothing than type dispatch should
[ginac.git] / ginac / matrix.cpp
index 650799e55f6353db6807e1d42a8d7904cc55291b..8a68b663b90293a318e445bf8f5801980490e901 100644 (file)
 #include <stdexcept>
 
 #include "matrix.h"
-#include "archive.h"
 #include "numeric.h"
 #include "lst.h"
 #include "idx.h"
 #include "indexed.h"
-#include "utils.h"
-#include "debugmsg.h"
 #include "power.h"
 #include "symbol.h"
 #include "normal.h"
+#include "print.h"
+#include "archive.h"
+#include "utils.h"
+#include "debugmsg.h"
 
 namespace GiNaC {
 
@@ -44,8 +45,6 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(matrix, basic)
 // default ctor, dtor, copy ctor, assignment operator and helpers:
 //////////
 
-// public
-
 /** Default ctor.  Initializes to 1 x 1-dimensional zero-matrix. */
 matrix::matrix() : inherited(TINFO_matrix), row(1), col(1)
 {
@@ -53,9 +52,6 @@ matrix::matrix() : inherited(TINFO_matrix), row(1), col(1)
        m.push_back(_ex0());
 }
 
-// protected
-
-/** For use by copy ctor and assignment operator. */
 void matrix::copy(const matrix & other)
 {
        inherited::copy(other);
@@ -64,10 +60,7 @@ void matrix::copy(const matrix & other)
        m = other.m;  // STL's vector copying invoked here
 }
 
-void matrix::destroy(bool call_parent)
-{
-       if (call_parent) inherited::destroy(call_parent);
-}
+DEFAULT_DESTROY(matrix)
 
 //////////
 // other ctors
@@ -118,7 +111,6 @@ matrix::matrix(unsigned r, unsigned c, const lst & l)
 // archiving
 //////////
 
-/** Construct object from archive_node. */
 matrix::matrix(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
 {
        debugmsg("matrix ctor from archive_node", LOGLEVEL_CONSTRUCT);
@@ -134,13 +126,6 @@ matrix::matrix(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst
        }
 }
 
-/** Unarchive the object. */
-ex matrix::unarchive(const archive_node &n, const lst &sym_lst)
-{
-       return (new matrix(n, sym_lst))->setflag(status_flags::dynallocated);
-}
-
-/** Archive the object. */
 void matrix::archive(archive_node &n) const
 {
        inherited::archive(n);
@@ -153,42 +138,43 @@ void matrix::archive(archive_node &n) const
        }
 }
 
+DEFAULT_UNARCHIVE(matrix)
+
 //////////
 // functions overriding virtual functions from bases classes
 //////////
 
 // public
 
-void matrix::print(std::ostream & os, unsigned upper_precedence) const
+void matrix::print(const print_context & c, unsigned level) const
 {
-       debugmsg("matrix print",LOGLEVEL_PRINT);
-       os << "[[ ";
-       for (unsigned r=0; r<row-1; ++r) {
-               os << "[[";
-               for (unsigned c=0; c<col-1; ++c)
-                       os << m[r*col+c] << ",";
-               os << m[col*(r+1)-1] << "]], ";
-       }
-       os << "[[";
-       for (unsigned c=0; c<col-1; ++c)
-               os << m[(row-1)*col+c] << ",";
-       os << m[row*col-1] << "]] ]]";
-}
+       debugmsg("matrix print", LOGLEVEL_PRINT);
+
+       if (is_of_type(c, print_tree)) {
+
+               inherited::print(c, level);
+
+       } else {
+
+               c.s << "[[ ";
+               for (unsigned y=0; y<row-1; ++y) {
+                       c.s << "[[";
+                       for (unsigned x=0; x<col-1; ++x) {
+                               m[y*col+x].print(c);
+                               c.s << ",";
+                       }
+                       m[col*(y+1)-1].print(c);
+                       c.s << "]], ";
+               }
+               c.s << "[[";
+               for (unsigned x=0; x<col-1; ++x) {
+                       m[(row-1)*col+x].print(c);
+                       c.s << ",";
+               }
+               m[row*col-1].print(c);
+               c.s << "]] ]]";
 
-void matrix::printraw(std::ostream & os) const
-{
-       debugmsg("matrix printraw",LOGLEVEL_PRINT);
-       os << class_name() << "(" << row << "," << col <<",";
-       for (unsigned r=0; r<row-1; ++r) {
-               os << "(";
-               for (unsigned c=0; c<col-1; ++c)
-                       os << m[r*col+c] << ",";
-               os << m[col*(r-1)-1] << "),";
        }
-       os << "(";
-       for (unsigned c=0; c<col-1; ++c)
-               os << m[(row-1)*col+c] << ",";
-       os << m[row*col-1] << "))";
 }
 
 /** nops is defined to be rows x columns. */
@@ -889,50 +875,32 @@ matrix matrix::inverse(void) const
        if (row != col)
                throw (std::logic_error("matrix::inverse(): matrix not square"));
        
-       // NOTE: the Gauss-Jordan elimination used here can in principle be
-       // replaced by two clever calls to gauss_elimination() and some to
-       // transpose().  Wouldn't be more efficient (maybe less?), just more
-       // orthogonal.
-       matrix tmp(row,col);
-       // set tmp to the unit matrix
-       for (unsigned i=0; i<col; ++i)
-               tmp.m[i*col+i] = _ex1();
+       // This routine actually doesn't do anything fancy at all.  We compute the
+       // inverse of the matrix A by solving the system A * A^{-1} == Id.
        
-       // create a copy of this matrix
-       matrix cpy(*this);
-       for (unsigned r1=0; r1<row; ++r1) {
-               int indx = cpy.pivot(r1, r1);
-               if (indx == -1) {
+       // First populate the identity matrix supposed to become the right hand side.
+       matrix identity(row,col);
+       for (unsigned i=0; i<row; ++i)
+               identity.set(i,i,_ex1());
+       
+       // Populate a dummy matrix of variables, just because of compatibility with
+       // matrix::solve() which wants this (for compatibility with under-determined
+       // systems of equations).
+       matrix vars(row,col);
+       for (unsigned r=0; r<row; ++r)
+               for (unsigned c=0; c<col; ++c)
+                       vars.set(r,c,symbol());
+       
+       matrix sol(row,col);
+       try {
+               sol = this->solve(vars,identity);
+       } catch (const std::runtime_error & e) {
+           if (e.what()==std::string("matrix::solve(): inconsistent linear system"))
                        throw (std::runtime_error("matrix::inverse(): singular matrix"));
-               }
-               if (indx != 0) {  // swap rows r and indx of matrix tmp
-                       for (unsigned i=0; i<col; ++i)
-                               tmp.m[r1*col+i].swap(tmp.m[indx*col+i]);
-               }
-               ex a1 = cpy.m[r1*col+r1];
-               for (unsigned c=0; c<col; ++c) {
-                       cpy.m[r1*col+c] /= a1;
-                       tmp.m[r1*col+c] /= a1;
-               }
-               for (unsigned r2=0; r2<row; ++r2) {
-                       if (r2 != r1) {
-                               if (!cpy.m[r2*col+r1].is_zero()) {
-                                       ex a2 = cpy.m[r2*col+r1];
-                                       // yes, there is something to do in this column
-                                       for (unsigned c=0; c<col; ++c) {
-                                               cpy.m[r2*col+c] -= a2 * cpy.m[r1*col+c];
-                                               if (!cpy.m[r2*col+c].info(info_flags::numeric))
-                                                       cpy.m[r2*col+c] = cpy.m[r2*col+c].normal();
-                                               tmp.m[r2*col+c] -= a2 * tmp.m[r1*col+c];
-                                               if (!tmp.m[r2*col+c].info(info_flags::numeric))
-                                                       tmp.m[r2*col+c] = tmp.m[r2*col+c].normal();
-                                       }
-                               }
-                       }
-               }
+               else
+                       throw;
        }
-       
-       return tmp;
+       return sol;
 }
 
 
@@ -995,8 +963,10 @@ matrix matrix::solve(const matrix & vars,
        switch(algo) {
                case solve_algo::gauss:
                        aug.gauss_elimination();
+                       break;
                case solve_algo::divfree:
                        aug.division_free_elimination();
+                       break;
                case solve_algo::bareiss:
                default:
                        aug.fraction_free_elimination();
@@ -1447,9 +1417,10 @@ ex lst_to_matrix(const lst & l)
        for (i=0; i<rows; i++)
                if (l.op(i).nops() > cols)
                        cols = l.op(i).nops();
-       
+
        // Allocate and fill matrix
        matrix &m = *new matrix(rows, cols);
+       m.setflag(status_flags::dynallocated);
        for (i=0; i<rows; i++)
                for (j=0; j<cols; j++)
                        if (l.op(i).nops() > j)
@@ -1464,6 +1435,7 @@ ex diag_matrix(const lst & l)
        unsigned dim = l.nops();
 
        matrix &m = *new matrix(dim, dim);
+       m.setflag(status_flags::dynallocated);
        for (unsigned i=0; i<dim; i++)
                m.set(i, i, l.op(i));