]> www.ginac.de Git - ginac.git/blobdiff - ginac/matrix.cpp
* introduced typedef propinfovector in order to please Cint.
[ginac.git] / ginac / matrix.cpp
index 1a5d6953c3d994365d9d6b05a60ebf351119e7bd..25de42bf57d2fc4262fd4c8f189aa385d9e10857 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
@@ -95,11 +88,29 @@ matrix::matrix(unsigned r, unsigned c, const exvector & m2)
        debugmsg("matrix ctor from unsigned,unsigned,exvector",LOGLEVEL_CONSTRUCT);
 }
 
+/** 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
+ *  thrown away. */
+matrix::matrix(unsigned r, unsigned c, const lst & l)
+  : inherited(TINFO_matrix), row(r), col(c)
+{
+       debugmsg("matrix ctor from unsigned,unsigned,lst",LOGLEVEL_CONSTRUCT);
+       m.resize(r*c, _ex0());
+
+       for (unsigned i=0; i<l.nops(); i++) {
+               unsigned x = i % c;
+               unsigned y = i / c;
+               if (y >= r)
+                       break; // matrix smaller than list: throw away excessive elements
+               m[y*c+x] = l.op(i);
+       }
+}
+
 //////////
 // 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);
@@ -115,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);
@@ -134,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. */
@@ -381,6 +386,57 @@ ex matrix::eval_indexed(const basic & i) const
        return i.hold();
 }
 
+/** Sum of two indexed matrices. */
+ex matrix::add_indexed(const ex & self, const ex & other) const
+{
+       GINAC_ASSERT(is_ex_of_type(self, indexed));
+       GINAC_ASSERT(is_ex_of_type(self.op(0), matrix));
+       GINAC_ASSERT(is_ex_of_type(other, indexed));
+       GINAC_ASSERT(self.nops() == 2 || self.nops() == 3);
+
+       // Only add two matrices
+       if (is_ex_of_type(other.op(0), matrix)) {
+               GINAC_ASSERT(other.nops() == 2 || other.nops() == 3);
+
+               const matrix &self_matrix = ex_to_matrix(self.op(0));
+               const matrix &other_matrix = ex_to_matrix(other.op(0));
+
+               if (self.nops() == 2 && other.nops() == 2) { // vector + vector
+
+                       if (self_matrix.row == other_matrix.row)
+                               return indexed(self_matrix.add(other_matrix), self.op(1));
+                       else if (self_matrix.row == other_matrix.col)
+                               return indexed(self_matrix.add(other_matrix.transpose()), self.op(1));
+
+               } else if (self.nops() == 3 && other.nops() == 3) { // matrix + matrix
+
+                       if (self.op(1).is_equal(other.op(1)) && self.op(2).is_equal(other.op(2)))
+                               return indexed(self_matrix.add(other_matrix), self.op(1), self.op(2));
+                       else if (self.op(1).is_equal(other.op(2)) && self.op(2).is_equal(other.op(1)))
+                               return indexed(self_matrix.add(other_matrix.transpose()), self.op(1), self.op(2));
+
+               }
+       }
+
+       // Don't know what to do, return unevaluated sum
+       return self + other;
+}
+
+/** Product of an indexed matrix with a number. */
+ex matrix::scalar_mul_indexed(const ex & self, const numeric & other) const
+{
+       GINAC_ASSERT(is_ex_of_type(self, indexed));
+       GINAC_ASSERT(is_ex_of_type(self.op(0), matrix));
+       GINAC_ASSERT(self.nops() == 2 || self.nops() == 3);
+
+       const matrix &self_matrix = ex_to_matrix(self.op(0));
+
+       if (self.nops() == 2)
+               return indexed(self_matrix.mul(other), self.op(1));
+       else // self.nops() == 3
+               return indexed(self_matrix.mul(other), self.op(1), self.op(2));
+}
+
 /** Contraction of an indexed matrix with something else. */
 bool matrix::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
 {
@@ -546,6 +602,19 @@ matrix matrix::mul(const matrix & other) const
 }
 
 
+/** Product of matrix and scalar. */
+matrix matrix::mul(const numeric & other) const
+{
+       exvector prod(row * col);
+
+       for (unsigned r=0; r<row; ++r)
+               for (unsigned c=0; c<col; ++c)
+                       prod[r*col+c] = m[r*col+c] * other;
+
+       return matrix(row, col, prod);
+}
+
+
 /** operator() to access elements.
  *
  *  @param ro row of element
@@ -1357,20 +1426,17 @@ int matrix::pivot(unsigned ro, unsigned co, bool symbolic)
        return k;
 }
 
-/** Convert list of lists to matrix. */
-ex lst_to_matrix(const ex &l)
+ex lst_to_matrix(const lst & l)
 {
-       if (!is_ex_of_type(l, lst))
-               throw(std::invalid_argument("argument to lst_to_matrix() must be a lst"));
-       
        // Find number of rows and columns
        unsigned rows = l.nops(), cols = 0, i, j;
        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)
@@ -1380,4 +1446,16 @@ ex lst_to_matrix(const ex &l)
        return m;
 }
 
+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));
+
+       return m;
+}
+
 } // namespace GiNaC