]> www.ginac.de Git - ginac.git/blobdiff - ginac/matrix.cpp
* Improved lsolve() of systems containing non-numeric coefficients.
[ginac.git] / ginac / matrix.cpp
index f62e2d409244d8a50d44890b8eae74f8ac5e4eb1..821e184d3acc0e8f014e67216f90aba91390778c 100644 (file)
@@ -3,7 +3,7 @@
  *  Implementation of symbolic matrices */
 
 /*
- *  GiNaC Copyright (C) 1999-2006 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
@@ -113,12 +113,13 @@ 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"));
        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);
        }
 }
 
@@ -221,7 +222,7 @@ ex matrix::eval(int level) const
                        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
@@ -262,6 +263,24 @@ ex matrix::conjugate() 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
@@ -1395,18 +1414,27 @@ int matrix::fraction_free_elimination(const bool det)
        
        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) {
@@ -1509,6 +1537,16 @@ int matrix::pivot(unsigned ro, unsigned co, bool symbolic)
        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;