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