]> www.ginac.de Git - ginac.git/blobdiff - ginac/matrix.cpp
- dirac_trace() is twice as fast
[ginac.git] / ginac / matrix.cpp
index cc80f7cae43b66d1223f0364acdac57ba533cf9f..99083c060be15496d74c849266fa5ce18e1624ff 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. */
@@ -222,22 +208,6 @@ ex matrix::expand(unsigned options) const
        return matrix(row, col, tmp);
 }
 
-/** Search ocurrences.  A matrix 'has' an expression if it is the expression
- *  itself or one of the elements 'has' it. */
-bool matrix::has(const ex & other) const
-{
-       GINAC_ASSERT(other.bp!=0);
-       
-       // tautology: it is the expression itself
-       if (is_equal(*other.bp)) return true;
-       
-       // search all the elements
-       for (exvector::const_iterator r=m.begin(); r!=m.end(); ++r)
-               if ((*r).has(other)) return true;
-       
-       return false;
-}
-
 /** Evaluate matrix entry by entry. */
 ex matrix::eval(int level) const
 {
@@ -286,14 +256,14 @@ ex matrix::evalf(int level) const
        return matrix(row, col, m2);
 }
 
-ex matrix::subs(const lst & ls, const lst & lr) const
+ex matrix::subs(const lst & ls, const lst & lr, bool no_pattern) const
 {
        exvector m2(row * col);
        for (unsigned r=0; r<row; ++r)
                for (unsigned c=0; c<col; ++c)
-                       m2[r*col+c] = m[r*col+c].subs(ls, lr);
+                       m2[r*col+c] = m[r*col+c].subs(ls, lr, no_pattern);
 
-       return matrix(row, col, m2);
+       return ex(matrix(row, col, m2)).bp->basic::subs(ls, lr, no_pattern);
 }
 
 // protected
@@ -786,7 +756,7 @@ ex matrix::determinant(unsigned algo) const
                        std::vector<unsigned> pre_sort;
                        for (std::vector<uintpair>::iterator i=c_zeros.begin(); i!=c_zeros.end(); ++i)
                                pre_sort.push_back(i->second);
-                       int sign = permutation_sign(pre_sort);
+                       int sign = permutation_sign(pre_sort.begin(), pre_sort.end());
                        exvector result(row*col);  // represents sorted matrix
                        unsigned c = 0;
                        for (std::vector<unsigned>::iterator i=pre_sort.begin();
@@ -889,50 +859,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 +947,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();