1 #ifndef MATRIX_H
2 #define MATRIX_H
3 #include "MatrixDef.h"
4 
5 namespace ATC_matrix {
6 static const int myPrecision = 15;
7 
8   /**
9    *  @class  Matrix
10    *  @brief  Base class for linear algebra subsystem
11    */
12 
13 template<typename T>
14 class Matrix
15 {
16 
17 protected:
18   Matrix(const Matrix &c);
19 public:
Matrix()20   Matrix() {}
~Matrix()21   virtual ~Matrix() {}
22 
23   //* stream output functions
print(std::ostream & o)24   void print(std::ostream &o) const { o << to_string(); }
25   void print(std::ostream &o, const std::string &name) const;
26   friend std::ostream& operator<<(std::ostream &o, const Matrix<T> &m){m.print(o); return o;}
27   void print() const;
28   virtual void print(const std::string &name) const;
29   virtual std::string to_string() const;
30 
31   // element by element operations
32   DenseMatrix<T> operator/(const Matrix<T>& B) const;
33   DenseMatrix<T> pow(int n) const;
34   DenseMatrix<T> pow(double n) const;
35 
36   // functions that return a copy
37   DenseMatrix<T> transpose() const;
38   void row_partition(const std::set<int> & rowsIn, std::set<int> & rows, std::set<int> & colsC,
39     DenseMatrix<T> & A1, DenseMatrix<T> & A2, bool complement=true) const;
40   std::set<int> row_partition(const std::set<int> & rows,
41     DenseMatrix<T> & A1, DenseMatrix<T> & A2) const;
42   void map(const std::set<int>& rows, const std::set<int>& cols, DenseMatrix<T> & A) const;
43   void insert(const std::set<int>& rows, const std::set<int>& cols, const DenseMatrix<T> & A);
44   void assemble(const std::set<int>& rows, const std::set<int>& cols, const DenseMatrix<T> & A);
45 
46   // matrix to scalar functions
47   T sum()    const;
48   T stdev()  const;
49   T max()    const;
50   T min()    const;
51   T maxabs() const;
52   T minabs() const;
53   T norm()   const;
54   T norm_sq()   const;
55   T mean()   const;
56   T dot(const Matrix<T> &r) const;
57   T trace() const;
58 
59   // row and column operations
60   T row_sum  (INDEX i=0) const { return    row(*this,i).sum();   }
61   T row_mean (INDEX i=0) const { return    row(*this,i).mean();  }
62   T row_norm (INDEX i=0) const { return    row(*this,i).norm();  }
63   T row_min  (INDEX i=0) const { return    row(*this,i).min();  }
64   T row_max  (INDEX i=0) const { return    row(*this,i).max();  }
65   T row_stdev(INDEX i=0) const { return    row(*this,i).stdev(); }
66   T col_sum  (INDEX i=0) const { return column(*this,i).sum();   }
67   T col_mean (INDEX i=0) const { return column(*this,i).mean();  }
68   T col_norm (INDEX i=0) const { return column(*this,i).norm();  }
69   T col_min  (INDEX i=0) const { return column(*this,i).min();  }
70   T col_max  (INDEX i=0) const { return column(*this,i).max();  }
71   T col_stdev(INDEX i=0) const { return column(*this,i).stdev(); }
72 
73   // pure virtual functions (required to implement these) ---------------------
74   //* reference index operator
75   virtual T& operator()(INDEX i, INDEX j)=0;
76   //* value index operator
77   virtual T  operator()(INDEX i, INDEX j)const=0;
78   //* value flat index operator
79   virtual T& operator [](INDEX i)=0;
80   //* reference flat index operator
81   virtual T operator [](INDEX i) const=0;
82   //* returns the # of rows
83   virtual INDEX nRows() const=0;
84   //* returns the # of columns
85   virtual INDEX nCols() const=0;
86   //* returns a pointer to the data (dangerous)
87   virtual T * ptr() const=0;
88   //* resizes the matrix, copy what fits default to OFF
89   virtual void resize(INDEX nRows, INDEX nCols=1, bool copy=false)=0;
90   //* resizes the matrix, zero it out default to ON
91   virtual void  reset(INDEX nRows, INDEX nCols=1, bool zero=true)=0;
92   //* resizes and copies data
93   virtual void copy(const T * ptr, INDEX nRows, INDEX nCols=1)=0;
94   //* create restart file
95   virtual void write_restart(FILE *f) const=0;
96   //* writes a matlab command to recreate this in a variable named s
97   virtual void matlab(std::ostream &o, const std::string &s="M") const;
98   //* writes a mathematica command to recreate this in a variable named s
99   virtual void mathematica(std::ostream &o, const std::string &s="M") const;
100 
101   // output to matlab, with variable name s
102   void matlab(const std::string &s="M") const;
103   // output to mathematica, with variable name s
104   void mathematica(const std::string &s="M") const;
105 
106   Matrix<T>& operator+=(const Matrix &r);
107   Matrix<T>& operator-=(const Matrix &r);
108 
109   Matrix<T>& operator*=(const Matrix<T>& R);
110   Matrix<T>& operator/=(const Matrix<T>& R);
111   Matrix<T>& operator+=(const T v);
112   Matrix<T>& operator-=(const T v);
113   Matrix<T>& operator*=(const T v);
114   Matrix<T>& operator/=(T v);
115   Matrix<T>& divide_zero_safe(const Matrix<T>& B);
116 
117   Matrix<T>& operator=(const T &v);
118   Matrix<T>& operator=(const Matrix<T> &c);
119   virtual void set_all_elements_to(const T &v);
120   //* adds a matrix scaled by factor s to this one.
121   void add_scaled(const Matrix<T> &A, const T& s);
122 
123   //* sets all elements to zero
124   Matrix& zero();
125   //* sets matrix to the identity
126   Matrix& identity(int nrows=0);
127   //* returns the total number of elements
128   virtual INDEX size() const;
129   //* returns true if (i,j) is within the range of the matrix
130   bool in_range(INDEX i, INDEX j) const;
131   //* returns true if the matrix size is rs x cs
132   bool is_size(INDEX rs, INDEX cs) const;
133   //* returns true if the matrix is square and not empty
134   bool is_square() const;
135   //* returns true if Matrix, m, is the same size as this
136   bool same_size(const Matrix &m) const;
137   //* returns true if Matrix a and Matrix b are the same size
138   static bool same_size(const Matrix<T> &a, const Matrix<T> &b);
139   //* returns true if Matrix a rows are equal to Matrix b cols
140   static bool cols_equals_rows(const Matrix<T> &a, const Matrix<T> &b);
141   //* checks if memory is contiguous, only can be false for clone vector
memory_contiguous()142   virtual bool memory_contiguous() const { return true; }
143   //* checks if all values are within the prescribed range
144   virtual bool check_range(T min, T max) const;
145 
146 protected:
147   virtual void _set_equal(const Matrix<T> &r);
148 };
149 
150 //* Matrix operations
151 //@{
152 //* Sets C as b*C + a*A[tranpose?]*B[transpose?]
153 template<typename T>
154 void MultAB(const Matrix<T> &A, const Matrix<T> &B, DenseMatrix<T> &C,
155             bool At=0, bool Bt=0, T a=1, T b=0);
156 //* performs a matrix-vector multiply
157 template<typename T>
158 void MultMv(const Matrix<T> &A, const Vector<T> &v, DenseVector<T> &c,
159             const bool At, T a, T b);
160 // returns the inverse of a double precision matrix
161 DenseMatrix<double> inv(const Matrix<double>& A);
162 // returns the eigensystem of a pair of double precision matrices
163 DenseMatrix<double> eigensystem(const Matrix<double>& A, const Matrix<double>& B, DenseMatrix<double> & eVals, bool normalize = true);
164 // returns the polar decomposition of a double precision matrix
165 DenseMatrix<double>  polar_decomposition(const Matrix<double>& A, DenseMatrix<double> & rotation, DenseMatrix<double> & stretch, bool leftRotation = true);
166 
167 //* returns the trace of a matrix
168 template<typename T>
trace(const Matrix<T> & A)169 T trace(const Matrix<T>& A) { return A.trace(); }
170 //* computes the determinant of a square matrix
171 double det(const Matrix<double>& A);
172 //* Returns the maximum eigenvalue of a matrix.
173 double max_eigenvalue(const Matrix<double>& A);
174 //@}
175 
176 //-----------------------------------------------------------------------------
177 // computes the sum of the difference squared of each element.
178 //-----------------------------------------------------------------------------
179 template<typename T>
sum_difference_squared(const Matrix<T> & A,const Matrix<T> & B)180 double sum_difference_squared(const Matrix<T>& A, const Matrix<T> &B)
181 {
182   SSCK(A, B, "sum_difference_squared");
183   double v=0.0;
184   for (INDEX i=0; i<A.size(); i++) {
185     double d = A[i]-B[i];
186     v += d*d;
187   }
188   return v;
189 }
190 
191 //-----------------------------------------------------------------------------
192 //* Operator for Matrix-matrix product
193 //-----------------------------------------------------------------------------
194 template<typename T>
195 DenseMatrix<T> operator*(const Matrix<T> &A, const Matrix<T> &B)
196 {
197   DenseMatrix<T> C(0,0,false);
198   MultAB(A,B,C);
199   return C;
200 }
201 //-----------------------------------------------------------------------------
202 //* Multiply a Matrix by a scalar
203 //-----------------------------------------------------------------------------
204 template<typename T>
205 DenseMatrix<T> operator*(const Matrix<T> &M, const T s)
206 {
207   DenseMatrix<T> R(M);
208   return R*=s;
209 }
210 //-----------------------------------------------------------------------------
211 //* Multiply a Matrix by a scalar
212 template<typename T>
213 DenseMatrix<T> operator*(const T s, const Matrix<T> &M)
214 {
215   DenseMatrix<T> R(M);
216   return R*=s;
217 }
218 //-----------------------------------------------------------------------------
219 //* inverse scaling operator - must always create memory
220 template<typename T>
221 DenseMatrix<T> operator/(const Matrix<T> &M, const T s)
222 {
223   DenseMatrix<T> R(M);
224   return R*=(1.0/s); // for integer types this may be worthless
225 }
226 //-----------------------------------------------------------------------------
227 //* Operator for Matrix-matrix sum
228 template<typename T>
229 DenseMatrix<T> operator+(const Matrix<T> &A, const Matrix<T> &B)
230 {
231   DenseMatrix<T> C(A);
232   return C+=B;
233 }
234 //-----------------------------------------------------------------------------
235 //* Operator for Matrix-matrix subtraction
236 template<typename T>
237 DenseMatrix<T> operator-(const Matrix<T> &A, const Matrix<T> &B)
238 {
239   DenseMatrix<T> C(A);
240   return C-=B;
241 }
242 /******************************************************************************
243 * Template definitions for class Matrix
244 ******************************************************************************/
245 
246 //-----------------------------------------------------------------------------
247 //* performs a matrix-matrix multiply with general type implementation
248 template<typename T>
MultAB(const Matrix<T> & A,const Matrix<T> & B,DenseMatrix<T> & C,const bool At,const bool Bt,T a,T b)249 void MultAB(const Matrix<T> &A, const Matrix<T> &B, DenseMatrix<T> &C,
250             const bool At, const bool Bt, T a, T b)
251 {
252   const INDEX sA[2] = {A.nRows(), A.nCols()};  // m is sA[At] k is sA[!At]
253   const INDEX sB[2] = {B.nRows(), B.nCols()};  // k is sB[Bt] n is sB[!Bt]
254 
255   const INDEX M=sA[At], K=sB[Bt], N=sB[!Bt]; // M is the number of rows in A or Atrans (sA[At]),
256                                     // K is the number of rows in B or Btrans (sB[Bt], sA[!At]),
257                                     // N is the number of columns in B or Btrans (sB[!Bt]).
258 
259   GCK(A, B, sA[!At]!=K, "MultAB<T> shared index not equal size");
260   if (!C.is_size(M,N))
261   {
262     C.resize(M,N);          // set size of C
263     C.zero();
264   }
265   else C *= b; // Zero C
266   for (INDEX p=0; p<M; p++) {
267     INDEX p_times_At    = p*At;
268     INDEX p_times_notAt = p*!At;
269     for (INDEX q=0; q<N; q++) {
270         INDEX q_times_Bt    = q*Bt;
271         INDEX q_times_notBt = q*!Bt;
272       for (INDEX r=0; r<K; r++) {
273          INDEX ai = p_times_notAt+r*At;
274          INDEX aj = p_times_At+r*!At;
275          INDEX bi = r*!Bt+q_times_Bt;
276          INDEX bj = r*Bt+q_times_notBt;
277          T a_entry = A(ai, aj);
278          T b_entry = B(bi, bj);
279          T mult    = a_entry * b_entry;
280          C(p,q) += mult;
281       }
282     }
283   }
284 }
285 
286 //-----------------------------------------------------------------------------
287 //* output operator
288 template<typename T>
to_string()289 std::string Matrix<T>::to_string() const
290 {
291   std::string s;
292   for (INDEX i=0; i<nRows(); i++)
293   {
294     if (i) s += '\n';
295     for (INDEX j=0; j<nCols(); j++)
296     {
297       if (j) s+= '\t';
298       s += ATC_Utility::to_string((*this)(i,j),myPrecision)+"   ";
299     }
300   }
301   return s;
302 }
303 //-----------------------------------------------------------------------------
304 //* output operator that wraps the matrix in a nice labeled box
305 template<typename T>
print(std::ostream & o,const std::string & name)306 void Matrix<T>::print(std::ostream &o, const std::string &name) const
307 {
308   o << "------- Begin "<<name<<" -----------------\n";
309   this->print(o);
310   o << "\n------- End "<<name<<" -------------------\n";
311 }
312 //-----------------------------------------------------------------------------
313 //* print operator, use cout by default
314 template<typename T>
print()315 void Matrix<T>::print() const
316 {
317   print(std::cout);
318 }
319 //-----------------------------------------------------------------------------
320 //* named print operator, use cout by default
321 template<typename T>
print(const std::string & name)322 void Matrix<T>::print(const std::string &name) const
323 {
324   print(std::cout, name);
325 }
326 //-----------------------------------------------------------------------------
327 //* element by element division
328 template<typename T>
329 DenseMatrix<T> Matrix<T>::operator/ (const Matrix<T>& B) const
330 {
331   SSCK(*this, B, "Matrix<T>::Operator/");
332   DenseMatrix<T> R(*this);
333   R /= B;
334   return R;
335 }
336 //-----------------------------------------------------------------------------
337 //* element-wise raise to a power
338 template<typename T>
pow(int n)339 DenseMatrix<T> Matrix<T>::pow(int n) const
340 {
341   DenseMatrix<T> R(*this);
342   int sz=this->size(); for(INDEX i=0; i<sz; i++)
343   {
344     double val = R[i];
345     for (int k=1; k<n; k++) val *= R[i];
346     for (int k=n; k<1; k++) val /= R[i];
347     R[i] = val;
348   }
349   return R;
350 }
351 //-----------------------------------------------------------------------------
352 //* element-wise raise to a power
353 template<typename T>
pow(double n)354 DenseMatrix<T> Matrix<T>::pow(double n) const
355 {
356   DenseMatrix<T> R(*this);
357   int sz=this->size(); for(INDEX i=0; i<sz; i++)
358   {
359     double val = R[i];
360     R[i] = pow(val,n);
361   }
362   return R;
363 }
364 //-----------------------------------------------------------------------------
365 //* returns the transpose of this matrix (makes a copy)
366 template <typename T>
transpose()367 DenseMatrix<T> Matrix<T>::transpose()                                     const
368 {
369   DenseMatrix<T> t(this->nCols(), this->nRows());
370   int szi = this->nRows();
371   int szj = this->nCols();
372   for (INDEX i = 0; i < szi; i++)
373     for (INDEX j = 0; j < szj; j++)
374       t(j,i) = (*this)(i,j);
375   return t;
376 }
377 //-----------------------------------------------------------------------------
378 //* returns the transpose of a matrix (makes a copy)
379 template <typename T>
transpose(const Matrix<T> & A)380 DenseMatrix<T> transpose(const Matrix<T> &A)
381 {
382   return A.transpose();
383 }
384 //-----------------------------------------------------------------------------
385 //* Returns the sum of all matrix elements
386 template<typename T>
sum()387 T Matrix<T>::sum() const
388 {
389   if (!size())  return T(0);
390   T v = (*this)[0];
391   for (INDEX i=1; i<this->size(); i++) v += (*this)[i];
392   return v;
393 }
394 //-----------------------------------------------------------------------------
395 //* Returns the standard deviation of the matrix
396 template<typename T>
stdev()397 T Matrix<T>::stdev() const
398 {
399   GCHK(this->size()<2, "Matrix::stdev() size must be > 1");
400   T mean = this->mean();
401   T diff = (*this)[0]-mean;
402   T stdev = diff*diff;
403   for (INDEX i=1; i<this->size(); i++)
404   {
405     diff = (*this)[i]-mean;
406     stdev += diff*diff;
407   }
408   return sqrt(stdev/T(this->size()-1));
409 }
410 //-----------------------------------------------------------------------------
411 //* Returns the maximum of the matrix
412 template<typename T>
max()413 T Matrix<T>::max() const
414 {
415   GCHK(!this->size(), "Matrix::max() size must be > 0");
416   T v = (*this)[0];
417   for (INDEX i=1; i<this->size(); i++)   v = std::max(v, (*this)[i]);
418   return v;
419 }
420 //-----------------------------------------------------------------------------
421 //* Returns the minimum of the matrix
422 template<typename T>
min()423 T Matrix<T>::min() const
424 {
425   GCHK(!this->size(), "Matrix::min() size must be > 0");
426   T v = (*this)[0];
427   for (INDEX i=1; i<this->size(); i++)   v = std::min(v, (*this)[i]);
428   return v;
429 }
430 //-----------------------------------------------------------------------------
431 //* Returns the maximum absolute value of the matrix
432 template<typename T>
maxabs()433 T Matrix<T>::maxabs() const
434 {
435   GCHK(!this->size(), "Matrix::maxabs() size must be > 0");
436   T v = (*this)[0];
437   for (INDEX i=1; i<this->size(); i++)   v = ATC_Utility::max_abs(v, (*this)[i]);
438   return v;
439 }
440 //-----------------------------------------------------------------------------
441 //* Returns the minimum absoute value of the matrix
442 template<typename T>
minabs()443 T Matrix<T>::minabs() const
444 {
445   GCHK(!this->size(), "Matrix::minabs() size must be > 0");
446   T v = (*this)[0];
447   for (INDEX i=1; i<this->size(); i++)   v = ATC_Utility::min_abs(v, (*this)[i]);
448   return v;
449 }
450 //-----------------------------------------------------------------------------
451 //* returns the L2 norm of the matrix
452 template<typename T>
norm()453 T Matrix<T>::norm()                                                       const
454 {
455   GCHK(!this->size(), "Matrix::norm() size must be > 0");
456   return sqrt(dot(*this));
457 }
458 //-----------------------------------------------------------------------------
459 //* returns the L2 norm of the matrix
460 template<typename T>
norm_sq()461 T Matrix<T>::norm_sq()                                                       const
462 {
463   GCHK(!this->size(), "Matrix::norm() size must be > 0");
464   return dot(*this);
465 }
466 //-----------------------------------------------------------------------------
467 //* returns the average of the matrix
468 template<typename T>
mean()469 T Matrix<T>::mean()                                                       const
470 {
471   GCHK(!this->size(), "Matrix::mean() size must be > 0");
472   return sum()/T(this->size());
473 }
474 //-----------------------------------------------------------------------------
475 //* Returns the dot product of two vectors
476 template<typename T>
dot(const Matrix<T> & r)477 T Matrix<T>::dot(const Matrix<T>& r)  const
478 {
479   SSCK(*this, r, "Matrix<T>::dot");
480   if (!this->size()) return T(0);
481   T v = r[0]*(*this)[0];
482   for (INDEX i=1; i<this->size(); i++)  v += r[i]*(*this)[i];
483   return v;
484 }
485 //-----------------------------------------------------------------------------
486 // returns the sum of the matrix diagonal
487 //-----------------------------------------------------------------------------
488 template<typename T>
trace()489 T Matrix<T>::trace() const
490 {
491   const INDEX N = std::min(nRows(),nCols());
492   if (!N) return T(0);
493   T r = (*this)(0,0);
494   for (INDEX i=0; i<N; i++)
495     r += (*this)(i,i);
496   return r;
497 }
498 //-----------------------------------------------------------------------------
499 //* Adds a matrix to this one
500 template<typename T>
501 Matrix<T>& Matrix<T>::operator+=(const Matrix &r)
502 {
503   SSCK(*this, r, "operator+= or operator +");
504   int sz=this->size(); for(INDEX i=0; i<sz; i++) (*this)[i]+=r[i];
505   return *this;
506 }
507 //-----------------------------------------------------------------------------
508 // subtracts a matrix from this one
509 //-----------------------------------------------------------------------------
510 template<typename T>
511 Matrix<T>& Matrix<T>::operator-=(const Matrix &r)
512 {
513   SSCK(*this, r, "operator-= or operator -");
514   int sz=this->size(); for(INDEX i=0; i<sz; i++) (*this)[i]-=r[i];
515   return *this;
516 }
517 //-----------------------------------------------------------------------------
518 // multiplies each element in this by the corresponding element in R
519 //-----------------------------------------------------------------------------
520 
521 template<typename T>
522 Matrix<T>& Matrix<T>::operator*=(const Matrix<T>& R)
523 {
524   if ((R.nCols()==1) && (this->nCols()>1)) { // multiply every entry in a row by the same value
525     int szi = this->nRows();
526     int szj = this->nCols();
527     for (INDEX i = 0; i < szi; i++)
528       for (INDEX j = 0; j < szj; j++)
529         {
530           (*this)(i,j) *= R[i];
531         }
532   }
533   else if (((R.nCols()==R.size()) && (R.nRows()==R.size())) && !((this->nCols()==this->size()) && (this->nRows()==this->size()))){
534     int szi = this->nRows();
535     int szj = this->nCols();
536     for (INDEX i = 0; i < szi; i++)
537       for (INDEX j = 0; j < szj; j++)
538       {
539           (*this)(i,j) *= R[i];
540     }
541   }
542   else { // multiply each entry by a different value
543 
544     int sz = this->size();
545     for (INDEX i = 0; i < sz; i++)
546       {
547         (*this)[i] *= R[i];
548       }
549   }
550   return *this;
551 }
552 //-----------------------------------------------------------------------------
553 // divides each element in this by the corresponding element in R
554 //-----------------------------------------------------------------------------
555 template<typename T>
556 Matrix<T>& Matrix<T>::operator/=(const Matrix<T>& R)
557 {
558   if ((R.nCols()==1) && (this->nCols()>1)) { // divide every entry in a row by the same value
559     int szi = this->nRows();
560     int szj = this->nCols();
561     for (INDEX i = 0; i < szi; i++)
562       for (INDEX j = 0; j < szj; j++)
563         {
564           (*this)(i,j) /= R[i];
565         }
566   }
567   else { // divide each entry by a different value
568     SSCK(*this, R, "operator/= or operator/");
569     int sz = this->size();
570     for(INDEX i = 0; i < sz; i++)
571       {
572         GCHK(fabs(R[i])==0,"Operator/: division by zero");
573         (*this)[i] /= R[i];
574       }
575   }
576   return *this;
577 }
578 //-----------------------------------------------------------------------------
579 // divides each element in this by the corresponding element in R unless zero
580 //-----------------------------------------------------------------------------
581 template<typename T>
divide_zero_safe(const Matrix<T> & R)582 Matrix<T>& Matrix<T>::divide_zero_safe(const Matrix<T>& R)
583 {
584   if ((R.nCols()==1) && (this->nCols()>1)) { // divide every entry in a row by the same value
585     int szi = this->nRows();
586     int szj = this->nCols();
587     for (INDEX i = 0; i < szi; i++)
588       for (INDEX j = 0; j < szj; j++)
589         {
590           if(fabs(R[i])!=0) {
591             (*this)(i,j) /= R[i];
592           }
593         }
594   }
595   else { // divide each entry by a different value
596     SSCK(*this, R, "operator/= or operator/");
597     int sz = this->size();
598     for(INDEX i = 0; i < sz; i++)
599       {
600         if(fabs(R[i])!=0) {
601           (*this)[i] /= R[i];
602         }
603       }
604   }
605   return *this;
606 }
607 //-----------------------------------------------------------------------------
608 // scales this matrix by a constant
609 //-----------------------------------------------------------------------------
610 template<typename T>
611 Matrix<T>& Matrix<T>::operator*=(const T v)
612 {
613   int sz=this->size(); for(INDEX i=0; i<sz; i++) (*this)[i]*=v;
614   return *this;
615 }
616 //-----------------------------------------------------------------------------
617 // adds a constant to this matrix
618 //-----------------------------------------------------------------------------
619 template<typename T>
620 Matrix<T>& Matrix<T>::operator+=(const T v)
621 {
622   int sz=this->size(); for(INDEX i=0; i<sz; i++) (*this)[i]+=v;
623   return *this;
624 }
625 //-----------------------------------------------------------------------------
626 // substracts a constant to this matrix
627 //-----------------------------------------------------------------------------
628 template<typename T>
629 Matrix<T>& Matrix<T>::operator-=(const T v)
630 {
631   int sz=this->size(); for(INDEX i=0; i<sz; i++) (*this)[i]-=v;
632   return *this;
633 }
634 //-----------------------------------------------------------------------------
635 //* scales this matrix by the inverse of a constant
636 template<typename T>
637 Matrix<T>& Matrix<T>::operator/=(T v)
638 {
639   return (*this)*=(1.0/v);
640 }
641 
642 //----------------------------------------------------------------------------
643 // Assigns one matrix to another
644 //----------------------------------------------------------------------------
645 template<typename T>
646 Matrix<T>& Matrix<T>::operator=(const Matrix<T> &r)
647 {
648   this->_set_equal(r);
649   return *this;
650 }
651 //----------------------------------------------------------------------------
652 // general matrix assignment (for densely packed matrices)
653 //----------------------------------------------------------------------------
654 template<typename T>
_set_equal(const Matrix<T> & r)655 void Matrix<T>::_set_equal(const Matrix<T> &r)
656 {
657   this->resize(r.nRows(), r.nCols());
658   const Matrix<T> *pr = &r;
659   if (const SparseMatrix<T> *ps = sparse_cast(pr))
660     copy_sparse_to_matrix(ps, *this);
661 
662   else if (diag_cast(pr))  // r is Diagonal?
663   {
664     this->zero();
665     for (INDEX i=0; i<r.size(); i++) (*this)(i,i) = r[i];
666   }
667   else memcpy(this->ptr(), r.ptr(), r.size()*sizeof(T));
668 }
669 //-----------------------------------------------------------------------------
670 //* sets all elements to a constant
671 template<typename T>
672 inline Matrix<T>& Matrix<T>::operator=(const T &v)
673 {
674   set_all_elements_to(v);
675   return *this;
676 }
677 //-----------------------------------------------------------------------------
678 //* sets all elements to a constant
679 template<typename T>
set_all_elements_to(const T & v)680 void Matrix<T>::set_all_elements_to(const T &v)
681 {
682   int sz=this->size(); for(INDEX i=0; i<sz; i++) (*this)[i] = v;
683 }
684 //----------------------------------------------------------------------------
685 // adds a matrix scaled by factor s to this one.
686 //----------------------------------------------------------------------------
687 template <typename T>
add_scaled(const Matrix<T> & A,const T & s)688 void Matrix<T>::add_scaled(const Matrix<T> &A, const T& s)
689 {
690     SSCK(A, *this, "Matrix::add_scaled");
691     int sz=this->size(); for(INDEX i=0; i<sz; i++) (*this)[i] += A[i]*s;
692 }
693 //-----------------------------------------------------------------------------
694 //* writes a matlab command to the console
695 template<typename T>
matlab(const std::string & s)696 void Matrix<T>::matlab(const std::string &s) const
697 {
698   this->matlab(std::cout, s);
699 }
700 //-----------------------------------------------------------------------------
701 //* Writes a matlab script defining the vector to the stream
702 template<typename T>
matlab(std::ostream & o,const std::string & s)703 void Matrix<T>::matlab(std::ostream &o, const std::string &s) const
704 {
705   o << s <<"=zeros(" << nRows() << ","<<nCols()<<");\n";
706   int szi = this->nRows();
707   int szj = this->nCols();
708   for (INDEX i = 0; i < szi; i++)
709     for (INDEX j = 0; j < szj; j++)
710       o << s << "("<<i+1<<","<<j+1<<")=" << (*this)(i,j) << ";\n";
711 }
712 //-----------------------------------------------------------------------------
713 //* writes a mathematica command to the console
714 template<typename T>
mathematica(const std::string & s)715 void Matrix<T>::mathematica(const std::string &s) const
716 {
717   this->mathematica(std::cout, s);
718 }
719 //-----------------------------------------------------------------------------
720 //* Writes a mathematica script defining the vector to the stream
721 template<typename T>
mathematica(std::ostream & o,const std::string & s)722 void Matrix<T>::mathematica(std::ostream &o, const std::string &s) const
723 {
724   o << s <<" = { \n";
725   o.precision(15);
726   o << std::fixed;
727   for(INDEX i=0; i< nRows(); i++) {
728     o <<" { " << (*this)(i,0);
729     for(INDEX j=1; j< nCols(); j++) o << ", " << (*this)(i,j);
730     if (i+1 == nRows()) { o <<" }  \n"; }
731     else                { o <<" }, \n"; }
732 
733   }
734   o << "};\n";
735   o << std::scientific;
736 }
737 //-----------------------------------------------------------------------------
738 //* sets all matrix elements to zero
739 template<typename T>
zero()740 inline Matrix<T>& Matrix<T>::zero()
741 {
742   set_all_elements_to(T(0));
743   return *this;
744 }
745 //-----------------------------------------------------------------------------
746 //* sets to identity
747 template<typename T>
identity(int nrows)748 inline Matrix<T>& Matrix<T>::identity(int nrows)
749 {
750   if (nrows == 0) {
751     SQCK(*this, "DenseMatrix::inv(), matrix not square"); // check matrix is square
752     nrows = nRows();
753   }
754   reset(nrows,nrows);
755   for(INDEX i=0; i< nRows(); i++) (*this)(i,i) = 1;
756   return *this;
757 }
758 //-----------------------------------------------------------------------------
759 //* returns the total number of elements
760 template<typename T>
size()761 inline INDEX Matrix<T>::size() const
762 {
763   return nRows()*nCols();
764 }
765 //-----------------------------------------------------------------------------
766 //* returns true if (i,j) is within the range of the matrix
767 template<typename T>
in_range(INDEX i,INDEX j)768 inline bool Matrix<T>::in_range(INDEX i, INDEX j) const
769 {
770   return i<nRows() && j<nCols();
771 }
772 //-----------------------------------------------------------------------------
773 //* returns true if the matrix size is rs x cs
774 template<typename T>
is_size(INDEX rs,INDEX cs)775 inline bool Matrix<T>::is_size(INDEX rs, INDEX cs) const
776 {
777   return nRows()==rs && nCols()==cs;
778 }
779 //-----------------------------------------------------------------------------
780 //* returns true if the matrix is square and not empty
781 template<typename T>
is_square()782 inline bool Matrix<T>::is_square() const
783 {
784   return nRows()==nCols() && nRows();
785 }
786 //-----------------------------------------------------------------------------
787 //* returns true if Matrix, m, is the same size as this
788 template<typename T>
same_size(const Matrix<T> & m)789 inline bool Matrix<T>::same_size(const Matrix<T> &m) const
790 {
791   return is_size(m.nRows(), m.nCols());
792 }
793 //-----------------------------------------------------------------------------
794 //* returns true if Matrix a and Matrix b are the same size
795 template<typename T>
same_size(const Matrix<T> & a,const Matrix<T> & b)796 inline bool Matrix<T>::same_size(const Matrix<T> &a, const Matrix<T> &b)
797 {
798   return a.same_size(b);
799 }
800 //-----------------------------------------------------------------------------
801 //* returns true if Matrix a rows =  Matrix b cols
802 template<typename T>
cols_equals_rows(const Matrix<T> & a,const Matrix<T> & b)803 inline bool Matrix<T>::cols_equals_rows(const Matrix<T> &a, const Matrix<T> &b)
804 {
805   return a.nCols() == b.nRows();
806 }
807 //-----------------------------------------------------------------------------
808 //* returns true if no value is outside of the range
809 template<typename T>
check_range(T min,T max)810 inline bool Matrix<T>::check_range(T min, T max) const
811 {
812   for (INDEX i = 0; i < this->nRows(); i++) {
813     for (INDEX j = 0; j < this->nCols(); j++) {
814       T val = (*this)(i,j);
815       if ( (val > max) || (val < min) ) return false;
816     }
817   }
818   return true;
819 }
820 //-----------------------------------------------------------------------------
821 //* Displays indexing error message and quits
822 template<typename T>
ierror(const Matrix<T> & a,const char * FILE,int LINE,INDEX i,INDEX j)823 void ierror(const Matrix<T> &a, const char *FILE, int LINE, INDEX i, INDEX j)
824 {
825   std::cout << "Error: Matrix indexing failure ";
826   std::cout << "in file: " << FILE << ", line: "<< LINE <<"\n";
827   std::cout << "Tried accessing index (" << i << ", " << j <<")\n";
828   std::cout << "Matrix size was "<< a.nRows() << "x" << a.nCols() << "\n";
829   ERROR_FOR_BACKTRACE
830   exit(EXIT_FAILURE);
831 }
832 //-----------------------------------------------------------------------------
833 //* Displays custom message and indexing error and quits
834 template<typename T>
ierror(const Matrix<T> & a,INDEX i,INDEX j,const std::string m)835 void ierror(const Matrix<T> &a, INDEX i, INDEX j, const std::string m)
836 {
837   std::cout << m << "\n";
838   std::cout << "Tried accessing index (" << i << ", " << j <<")\n";
839   std::cout << "Matrix size was "<< a.nRows() << "x" << a.nCols() << "\n";
840   ERROR_FOR_BACKTRACE
841   exit(EXIT_FAILURE);
842 }
843 //-----------------------------------------------------------------------------
844 //* Displays matrix compatibility error message
845 template<typename T>
merror(const Matrix<T> & a,const Matrix<T> & b,const std::string m)846 void merror(const Matrix<T> &a, const Matrix<T> &b, const std::string m)
847 {
848   std::cout << "Error: " << m << "\n";
849   std::cout << "Matrix sizes were " << a.nRows() << "x" << a.nCols();
850   if (&a != &b) std::cout << ", and "<< b.nRows() << "x" << b.nCols();
851   std::cout << "\n";
852   if (a.size() < 100) a.print("Matrix");
853   ERROR_FOR_BACKTRACE
854   exit(EXIT_FAILURE);
855 }
856 
857 //-----------------------------------------------------------------------------
858 //* returns upper or lower half of a partitioned matrix
859 //* A1 is the on-diagonal square matrix, A2 is the off-diagonal matrix
860 //* rowsIn is the rows to be placed in A1
861 //* rows is the map for A1, (rows,colsC) is the map for A2
862 
863 template <typename T>
row_partition(const std::set<int> & rowsIn,std::set<int> & rows,std::set<int> & colsC,DenseMatrix<T> & A1,DenseMatrix<T> & A2,bool complement)864 void Matrix<T>::row_partition(const std::set<int> & rowsIn,
865 std::set<int> & rows, std::set<int> & colsC,
866 DenseMatrix<T> & A1, DenseMatrix<T> & A2, bool complement) const
867 {
868   if (complement) {
869     for (INDEX i = 0; i < this->nRows();  i++) {
870       if (rowsIn.find(i) == rowsIn.end() ) rows.insert(i);
871     }
872   }
873   else  rows = rowsIn;
874   // complement of set "rows" in set of this.cols is "cols"
875   for (INDEX i = 0; i < this->nCols();  i++) {
876     if (rows.find(i) == rows.end() ) colsC.insert(i);
877   }
878   // degenerate cases
879   if      (int(rows.size()) == this->nCols()) {
880     A1 = (*this);
881     A2.reset(0,0);
882     return;
883   }
884   else if (rows.size() == 0) {
885     A1.reset(0,0);
886     A2 = (*this);
887     return;
888   }
889   // non-degenerate case
890   int nrows  = rows.size();
891   int ncolsC = colsC.size();
892   A1.reset(nrows,nrows);
893   A2.reset(nrows,ncolsC);
894   std::set<int>::const_iterator itrI, itrJ;
895   INDEX i =0;
896   for (itrI = rows.begin(); itrI != rows.end(); itrI++) {
897     INDEX j = 0;
898     for (itrJ = rows.begin(); itrJ != rows.end(); itrJ++) {
899       A1(i,j) = (*this)(*itrI,*itrJ);
900       j++;
901     }
902     j = 0;
903     for (itrJ = colsC.begin(); itrJ != colsC.end(); itrJ++) {
904       A2(i,j) = (*this)(*itrI,*itrJ);
905       j++;
906     }
907     i++;
908   }
909 }
910 
911 template <typename T>
row_partition(const std::set<int> & rows,DenseMatrix<T> & A1,DenseMatrix<T> & A2)912 std::set<int> Matrix<T>::row_partition(const std::set<int> & rows,
913 DenseMatrix<T> & A1, DenseMatrix<T> & A2) const
914 {
915   // complement of set "rows" in set of this.cols is "cols"
916   std::set<int> colsC;
917   for (INDEX i = 0; i < this->nCols();  i++) {
918     if (rows.find(i) == rows.end() ) colsC.insert(i);
919   }
920   // degenerate cases
921   if      (int(rows.size()) == this->nCols()) {
922     A1 = (*this);
923     A2.reset(0,0);
924     return colsC;
925   }
926   else if (rows.size() == 0) {
927     A1.reset(0,0);
928     A2 = (*this);
929     return colsC;
930   }
931   // non-degenerate case
932   int nrows  = rows.size();
933   int ncolsC = colsC.size();
934   A1.reset(nrows,nrows);
935   A2.reset(nrows,ncolsC);
936   std::set<int>::const_iterator itrI, itrJ;
937   INDEX i =0;
938   for (itrI = rows.begin(); itrI != rows.end(); itrI++) {
939     INDEX j = 0;
940     for (itrJ = rows.begin(); itrJ != rows.end(); itrJ++) {
941       A1(i,j) = (*this)(*itrI,*itrJ);
942       j++;
943     }
944     j = 0;
945     for (itrJ = colsC.begin(); itrJ != colsC.end(); itrJ++) {
946       A2(i,j) = (*this)(*itrI,*itrJ);
947       j++;
948     }
949     i++;
950   }
951   return colsC;
952 }
953 
954 //-----------------------------------------------------------------------------
955 //* returns row & column mapped matrix
956 template <typename T>
map(const std::set<int> & rows,const std::set<int> & cols,DenseMatrix<T> & A)957 void Matrix<T>::map(const std::set<int> & rows, const std::set<int> & cols,
958 DenseMatrix<T> & A ) const
959 {
960   if      (rows.size() == 0 || cols.size() == 0 ) {
961     A.reset(0,0);
962     return;
963   }
964   int nrows = rows.size();
965   int ncols = cols.size();
966   A.reset(nrows,ncols);
967   std::set<int>::const_iterator itrI, itrJ;
968   INDEX i =0;
969   for (itrI = rows.begin(); itrI != rows.end(); itrI++) {
970     INDEX j = 0;
971     for (itrJ = cols.begin(); itrJ != cols.end(); itrJ++) {
972       A(i,j) = (*this)(*itrI,*itrJ);
973       j++;
974     }
975     i++;
976   }
977 }
978 //-----------------------------------------------------------------------------
979 //* inserts elements from a smaller matrix
980 template <typename T>
insert(const std::set<int> & rows,const std::set<int> & cols,const DenseMatrix<T> & A)981 void Matrix<T>::insert(const std::set<int> & rows, const std::set<int> & cols,
982 const DenseMatrix<T> & A )
983 {
984   if      (rows.size() == 0 || cols.size() == 0 )  return;
985   std::set<int>::const_iterator itrI, itrJ;
986   int i =0;
987   for (itrI = rows.begin(); itrI != rows.end(); itrI++) {
988     int j = 0;
989     for (itrJ = cols.begin(); itrJ != cols.end(); itrJ++) {
990       (*this)(*itrI,*itrJ) = A(i,j);
991 //std::cout << *itrI << " " << *itrJ << " : " << (*this)(*itrI,*itrJ) << "\n";
992       j++;
993     }
994     i++;
995   }
996 }
997 //-----------------------------------------------------------------------------
998 //* assemble elements from a smaller matrix
999 template <typename T>
assemble(const std::set<int> & rows,const std::set<int> & cols,const DenseMatrix<T> & A)1000 void Matrix<T>::assemble(const std::set<int> & rows, const std::set<int> & cols,
1001 const DenseMatrix<T> & A )
1002 {
1003   if      (rows.size() == 0 || cols.size() == 0 )  return;
1004   std::set<int>::const_iterator itrI, itrJ;
1005   int i =0;
1006   for (itrI = rows.begin(); itrI != rows.end(); itrI++) {
1007     int j = 0;
1008     for (itrJ = cols.begin(); itrJ != cols.end(); itrJ++) {
1009       (*this)(*itrI,*itrJ) += A(i,j);
1010       j++;
1011     }
1012     i++;
1013   }
1014 }
1015 //-----------------------------------------------------------------------------
1016 
1017 } // end namespace
1018 
1019 #endif
1020