IFEM 90A354
matrix.h
Go to the documentation of this file.
1// $Id$
2//==============================================================================
17//==============================================================================
18
19#ifndef UTL_MATRIX_H
20#define UTL_MATRIX_H
21
22#include <vector>
23#include <iostream>
24#include <algorithm>
25#include <cstring>
26#include <cctype>
27#include <cmath>
28#include "BLAS.h"
29#include "print_tol.h"
30
31#ifdef INDEX_CHECK
32#if INDEX_CHECK > 1
33#define ABORT_ON_INDEX_CHECK abort()
34#else
35#define ABORT_ON_INDEX_CHECK
36#endif
37#define CHECK_INDEX(label,i,n) if (i < 1 || i > n) { \
38 std::cerr << label << i <<" is out of range [1,"<< n <<"]"<< std::endl; \
39 ABORT_ON_INDEX_CHECK; }
40#else
41#define CHECK_INDEX(label,i,n)
42#define ABORT_ON_INDEX_CHECK
43#endif
44
45#ifdef SING_CHECK
46#define ABORT_ON_SINGULARITY abort()
47#else
48#define ABORT_ON_SINGULARITY
49#endif
50
51
52namespace utl
53{
55 const char RETAIN = 2;
56
63 template<class T> class vector
64 {
65 public:
67 vector() {}
69 explicit vector(size_t n) { this->resize(n); }
71 vector(const T* values, size_t n) { this->fill(values,n); }
73 vector(const std::vector<T>& X) : myVec(X) {}
74
76 vector<T>& operator=(const std::vector<T>& X)
77 {
78 myVec = X;
79 return *this;
80 }
81
83 T* ptr() { return myVec.empty() ? nullptr : myVec.data(); }
85 const T* ptr() const { return myVec.empty() ? nullptr : myVec.data(); }
86
88 size_t size() const { return myVec.size(); }
90 bool empty() const { return myVec.empty(); }
92 bool zero(T tol = T(0)) const
93 {
94 return std::all_of(myVec.begin(), myVec.end(),
95 [tol](T v) { return std::fabs(v) <= tol; });
96 }
97
99 using ConstVecIter = typename std::vector<T>::const_iterator;
101 using VecIter = typename std::vector<T>::iterator;
102
104 ConstVecIter begin() const { return myVec.begin(); }
106 ConstVecIter end() const { return myVec.end(); }
108 VecIter begin(){ return myVec.begin(); }
110 VecIter end() { return myVec.end(); }
111
113 operator const std::vector<T>&() const { return myVec; }
115 operator std::vector<T>&() { return myVec; }
116
118 T& operator[](size_t i) { return myVec[i]; }
120 const T& operator[](size_t i) const { return myVec[i]; }
121
123 T& operator()(size_t i)
124 {
125 CHECK_INDEX("vector::operator(): Index ",i,myVec.size());
126 return myVec[i-1];
127 }
128
130 const T& operator()(size_t i) const
131 {
132 CHECK_INDEX("vector::operator(): Index ",i,myVec.size());
133 return myVec[i-1];
134 }
135
137 void fill(T s) { std::fill(myVec.begin(),myVec.end(),s); }
139 void fill(const T* values, size_t n = 0)
140 {
141 if (n > myVec.size())
142 myVec.resize(n);
143 memcpy(myVec.data(),values,myVec.size()*sizeof(T));
144 }
145
147 void push_back(T c) { myVec.push_back(c); }
148
151 {
152 myVec.insert(myVec.end(),i1,i2);
153 }
154
156 void push_back(const T* p, const T* q) { myVec.insert(myVec.end(),p,q); }
157
159 void swap(vector<T>& vec) { myVec.swap(vec.myVec); }
160
162 vector<T>& operator*=(T c);
164 vector<T>& operator/=(T d) { return this->operator*=(T(1)/d); }
165
167 vector<T>& operator*=(const std::vector<T>& X)
168 {
169 for (size_t i = 0; i < myVec.size() && i < X.size(); i++)
170 myVec[i] *= X[i];
171 return *this;
172 }
174 vector<T>& operator/=(const std::vector<T>& X)
175 {
176 for (size_t i = 0; i < myVec.size() && i < X.size(); i++)
177 myVec[i] *= (X[i] == T(0) ? T(0) : T(1)/X[i]);
178 return *this;
179 }
180
182 vector<T>& operator+=(const vector<T>& X) { return this->add(X); }
184 vector<T>& operator-=(const vector<T>& X) { return this->add(X,T(-1)); }
186 vector<T>& add(const std::vector<T>& X, const T& alfa = T(1),
187 unsigned int ofsx = 0, int stridex = 1,
188 unsigned int ofsy = 0, int stridey = 1);
189
192 vector<T>& relax(T alfa, const std::vector<T>& X)
193 {
194 if (alfa != T(1))
195 {
196 this->operator*=(alfa);
197 this->add(X,T(1)-alfa);
198 }
199 return *this;
200 }
203 vector<T>& relax(T alfa, const std::vector<T>& X, const std::vector<T>& Y)
204 {
205 return this->operator=(Y).relax(alfa,X);
206 }
207
215 T dot(const T* v, size_t nv,
216 size_t off1 = 0, int inc1 = 1,
217 size_t off2 = 0, int inc2 = 1) const;
218
225 T dot(const std::vector<T>& v,
226 size_t off1 = 0, int inc1 = 1,
227 size_t off2 = 0, int inc2 = 1) const
228 {
229 return this->dot(v.data(),v.size(),off1,inc1,off2,inc2);
230 }
231
235 T norm2(size_t off = 0, int inc = 1) const;
241 T normInf(size_t& off, int inc = 1, bool sign = false) const;
244 T normInf(int inc = 1) const { size_t o = 0; return this->normInf(o,inc); }
245
247 T max() const { return *std::max_element(myVec.begin(),myVec.end()); }
249 T min() const { return *std::min_element(myVec.begin(),myVec.end()); }
250
254 T asum(size_t off = 0, int inc = 1) const;
255
260 T sum(size_t off = 0, int inc = 1, size_t max = 0) const
261 {
262 T xsum = T(0);
263 if (inc < 1 || myVec.empty())
264 return xsum;
265
266 if (max == 0 || max > myVec.size())
267 max = myVec.size();
268 for (size_t i = off; i < max; i += inc)
269 xsum += myVec[i];
270 return xsum;
271 }
272
277 bool resize(size_t n, char forceClear = 0)
278 {
279 if (n == myVec.size())
280 {
281 if (forceClear == 1)
282 this->fill(T(0)); // Erase previous content
283 return false; // Size is not changed
284 }
285
286 if (forceClear < RETAIN)
287 myVec.clear();
288 myVec.resize(n,T(0));
289 return true;
290 }
291
293 void reserve(size_t n) { myVec.reserve(n); }
295 void clear() { myVec.clear(); }
296
297 private:
298 std::vector<T> myVec;
299 };
300
301
307 template<class T> class matrixBase
308 {
309 protected:
311 matrixBase() : n{0,0,0,0}, elem(myElem) {}
313 explicit matrixBase(vector<T>& vec) : n{0,0,0,0}, elem(vec) {}
316 matrixBase(size_t n_1, size_t n_2, size_t n_3 = 1, size_t n_4 = 1)
317 : n{n_1,n_2,n_3,n_4}, elem(myElem), myElem(n_1*n_2*n_3*n_4) {}
318
322 matrixBase(const matrixBase<T>& mat, bool copyContent = true)
323 : elem(myElem), myElem(mat.size())
324 {
325 memcpy(n,mat.n,sizeof(n));
326 if (copyContent)
327 elem = mat.elem;
328 }
329
338 void redim(size_t n_1, size_t n_2, size_t n_3, size_t n_4, bool forceClear)
339 {
340 if (forceClear)
341 {
342 // Erase previous content
343 if (this->size() == n_1*n_2*n_3*n_4)
344 this->fill(T(0));
345 else
346 this->clear();
347 }
348
349 if (n[0] == n_1 && n[1] == n_2 && n[2] == n_3 && n[3] == n_4)
350 return; // nothing to do
351
352 size_t oldn1 = n[0];
353 size_t oldn2 = n[1];
354 size_t oldn3 = n[2];
355 size_t oldSize = this->size();
356 n[0] = n_1;
357 n[1] = n_2;
358 n[2] = n_3;
359 n[3] = n_4;
360 if (this->size() == oldSize)
361 return; // no more to do, size is unchanged
362
363 // If the size in any of the matrix dimensions, except for the last one,
364 // are changed the previous matrix content must be cleared
365 if (!forceClear)
366 this->clearIfNrowChanged(oldn1,oldn2,oldn3);
367
368 elem.resize(n[0]*n[1]*n[2]*n[3],RETAIN);
369 }
370
372 virtual void clearIfNrowChanged(size_t n1, size_t n2, size_t n3) = 0;
373
374 public:
376 size_t dim(short int d = 1) const { return d > 0 && d <= 4 ? n[d-1] : 0; }
378 size_t size() const { return n[0]*n[1]*n[2]*n[3]; }
380 bool empty() const { return elem.empty(); }
382 bool zero(T tol = T(0)) const { return elem.zero(tol); }
383
385 const vector<T>& toVec() const { return elem; }
387 operator const std::vector<T>&() const { return elem; }
389 operator std::vector<T>&() { return elem; }
390
392 T* ptr(size_t c = 0)
393 {
394 return n[0]*c < elem.size() ? elem.ptr() + n[0]*c : nullptr;
395 }
397 const T* ptr(size_t c = 0) const
398 {
399 return n[0]*c < elem.size() ? elem.ptr() + n[0]*c : nullptr;
400 }
401
403 typename std::vector<T>::iterator begin() { return elem.begin(); }
405 typename std::vector<T>::iterator end() { return elem.end(); }
406
408 void clear() { n[0] = n[1] = n[2] = n[3] = 0; elem.clear(); }
409
411 void fill(T s) { std::fill(elem.begin(),elem.end(),s); }
413 void fill(const T* values, size_t n = 0) { elem.fill(values,n); }
414
416 matrixBase<T>& add(const matrixBase<T>& A, const T& alfa);
419
422 T norm2(int inc = 1) const { return elem.norm2(0,inc); }
425 T asum(int inc = 1) const { return elem.asum(0,inc); }
429 T sum(int inc = 1) const
430 {
431 if (inc > 0)
432 return elem.sum(0,inc);
433 else if (inc == 0 || (inc *= -1) > static_cast<int>(n[1]))
434 return T(0);
435 else
436 return elem.sum((inc-1)*n[0],1,inc*n[0]);
437 }
438
439 protected:
440 size_t n[4];
442
443 private:
445 };
446
447
455 template<class T> class matrix : public matrixBase<T>
456 {
457 public:
459 matrix() : nrow(this->n[0]), ncol(this->n[1]) {}
461 explicit matrix(vector<T>& vec)
462 : matrixBase<T>(vec), nrow(this->n[0]), ncol(this->n[1]) {}
464 matrix(size_t r, size_t c)
465 : matrixBase<T>(r,c), nrow(this->n[0]), ncol(this->n[1]) {}
467 matrix(const matrix<T>& mat, bool transposed = false)
468 : matrixBase<T>(mat,false), nrow(this->n[0]), ncol(this->n[1])
469 {
470 nrow = transposed ? mat.ncol : mat.nrow;
471 ncol = transposed ? mat.nrow : mat.ncol;
472 if (transposed)
473 for (size_t r = 0; r < ncol; r++)
474 for (size_t c = 0; c < nrow; c++)
475 this->elem[c+nrow*r] = mat.elem[r+ncol*c];
476 else if (!mat.elem.empty())
477 this->elem.fill(mat.elem.ptr());
478 }
480 virtual ~matrix() {}
481
488 void resize(size_t r, size_t c, bool forceClear = false)
489 {
490 this->redim(r,c,1,1,forceClear);
491 }
492
497 matrix<T>& expandRows(int incRows, bool setRows = false)
498 {
499 const int curRows = nrow;
500 if (setRows) incRows -= curRows;
501 const int newRows = curRows + incRows;
502 if (newRows < 1 || ncol < 1)
503 // The matrix is empty
504 this->clear();
505 else if (incRows < 0)
506 {
507 // The matrix size is reduced
508 T* newMat = this->ptr() + newRows;
509 for (size_t c = 1; c < ncol; c++, newMat += newRows)
510 memmove(newMat,this->ptr(c),newRows*sizeof(T));
511 nrow = newRows;
512 this->elem.resize(nrow*ncol,RETAIN);
513 }
514 else if (incRows > 0)
515 {
516 // The matrix size is increased
517 size_t oldRows = nrow;
518 nrow = newRows;
519 this->elem.resize(nrow*ncol,RETAIN);
520 T* oldMat = this->ptr() + oldRows*(ncol-1);
521 for (size_t c = ncol-1; c > 0; c--, oldMat -= oldRows)
522 {
523 memmove(this->ptr(c),oldMat,oldRows*sizeof(T));
524 for (size_t r = nrow-1; r >= oldRows; r--)
525 this->elem[r+nrow*(c-1)] = T(0);
526 }
527 }
528 return *this;
529 }
530
534 bool augmentRows(const matrix<T>& B, bool prepend = false)
535 {
536 if (B.ncol != ncol)
537 return false;
538
539 size_t oldRows = nrow;
540 size_t offset = prepend ? B.nrow : 0;
541 nrow += B.nrow;
542 this->elem.resize(nrow*ncol,RETAIN);
543 T* oldMat = this->ptr() + oldRows*(ncol-1);
544 for (size_t c = ncol; c > 0; c--, oldMat -= oldRows)
545 {
546 if (c > 1 || prepend)
547 memmove(this->ptr(c-1)+offset,oldMat,oldRows*sizeof(T));
548 if (prepend)
549 for (size_t r = 1; r <= B.nrow; r++)
550 this->elem[r-1+nrow*(c-1)] = B(r,c);
551 else
552 for (size_t r = nrow; r > oldRows; r--)
553 this->elem[r-1+nrow*(c-1)] = B(r-oldRows,c);
554 }
555 return true;
556 }
557
559 bool augmentCols(const matrix<T>& B)
560 {
561 if (B.nrow != nrow)
562 return false;
563
564 this->elem.push_back(B.elem.begin(),B.elem.end());
565 ncol += B.ncol;
566 return true;
567 }
568
570 size_t rows() const { return nrow; }
572 size_t cols() const { return ncol; }
573
576 {
577 if (&A == this)
578 return *this;
579
580 memcpy(this->n,A.n,sizeof(A.n));
581 this->elem = A.elem;
582 return *this;
583 }
584
586 matrix<T>& operator=(const std::vector<T>& X)
587 {
588 // Do not use vector<T>::operator= because we don't want to alter size
589 size_t nval = X.size() < this->elem.size() ? X.size() : this->elem.size();
590 std::copy(X.begin(),X.begin()+nval,this->elem.begin());
591 std::fill(this->elem.begin()+nval,this->elem.end(),T(0));
592 return *this;
593 }
594
597 T& operator()(size_t r, size_t c)
598 {
599 CHECK_INDEX("matrix::operator(): Row-index ",r,nrow);
600 CHECK_INDEX("matrix::operator(): Column-index ",c,ncol);
601 return this->elem[r-1+nrow*(c-1)];
602 }
603
606 const T& operator()(size_t r, size_t c) const
607 {
608 CHECK_INDEX("matrix::operator(): Row-index ",r,nrow);
609 CHECK_INDEX("matrix::operator(): Column-index ",c,ncol);
610 return this->elem[r-1+nrow*(c-1)];
611 }
612
614 vector<T> getRow(size_t r) const
615 {
616 CHECK_INDEX("matrix::getRow: Row-index ",r,nrow);
617 if (nrow < 2)
618 return this->elem;
619
620 vector<T> row(ncol);
621 for (size_t i = 0; i < ncol; i++)
622 row[i] = this->elem[r-1+nrow*i];
623 return row;
624 }
625
627 std::vector<T> getColumn(size_t c) const
628 {
629 CHECK_INDEX("matrix::getColumn: Column-index ",c,ncol);
630 if (ncol < 2)
631 return this->elem;
632
633 std::vector<T> col(nrow);
634 memcpy(col.data(),this->ptr(c-1),nrow*sizeof(T));
635 return col;
636 }
637
638 using matrixBase<T>::fill;
640 void fill(const std::vector<T>& v, size_t n, size_t m = 0)
641 {
642 if (n == 0 || v.size() < n)
643 return;
644 if (m == 0) m = v.size()/n;
645 this->resize(n,m,true);
646 if (n*m == v.size())
647 this->elem.fill(v.data());
648 else if ((n = v.size()/m) > nrow)
649 for (size_t c = 0; c < ncol; c++)
650 this->fillColumn(c+1,v.data()+c*n);
651 else // n < nrow
652 for (size_t c = 0; c < ncol; c++)
653 for (size_t r = 0; r < n; r++)
654 this->elem[r+c*nrow] = v[r+c*n];
655 }
656
658 void fillColumn(size_t c, const std::vector<T>& data)
659 {
660 CHECK_INDEX("matrix::fillColumn: Column-index ",c,ncol);
661 size_t ndata = nrow > data.size() ? data.size() : nrow;
662 memcpy(this->ptr(c-1),data.data(),ndata*sizeof(T));
663 }
664
666 void fillColumn(size_t c, const T* data)
667 {
668 CHECK_INDEX("matrix::fillColumn: Column-index ",c,ncol);
669 memcpy(this->ptr(c-1),data,nrow*sizeof(T));
670 }
671
673 void fillRow(size_t r, const T* data)
674 {
675 CHECK_INDEX("matrix::fillRow: Row-index ",r,nrow);
676 if (nrow < 2)
677 this->elem.fill(data);
678 else for (size_t i = 0; i < ncol; i++)
679 this->elem[r-1+nrow*i] = data[i];
680 }
681
683 void fillBlock(const matrix<T>& block, size_t r, size_t c,
684 bool transposed = false)
685 {
686 size_t nr = transposed ? block.cols() : block.rows();
687 size_t nc = transposed ? block.rows() : block.cols();
688 for (size_t i = 1; i <= nr && i+r-1 <= nrow; i++)
689 {
690 size_t ip = i+r-2 + nrow*(c-1);
691 for (size_t j = 1; j <= nc && j+c-1 <= ncol; j++, ip += nrow)
692 this->elem[ip] = transposed ? block(j,i) : block(i,j);
693 }
694 }
695
697 void addBlock(const matrix<T>& block, T s, size_t r, size_t c,
698 bool transposed = false)
699 {
700 size_t nr = transposed ? block.cols() : block.rows();
701 size_t nc = transposed ? block.rows() : block.cols();
702 for (size_t i = 1; i <= nr && i+r-1 <= nrow; i++)
703 {
704 size_t ip = i+r-2 + nrow*(c-1);
705 for (size_t j = 1; j <= nc && j+c-1 <= ncol; j++, ip += nrow)
706 this->elem[ip] += s*(transposed ? block(j,i) : block(i,j));
707 }
708 }
709
711 void extractBlock(matrix<T>& block, size_t r, size_t c,
712 bool addTo = false, bool transposed = false) const
713 {
714 size_t nr = transposed ? block.cols() : block.rows();
715 size_t nc = transposed ? block.rows() : block.cols();
716 for (size_t i = 1; i <= nr && i+r-1 <= nrow; i++)
717 {
718 size_t ip = i+r-2 + nrow*(c-1);
719 for (size_t j = 1; j <= nc && j+c-1 <= ncol; j++, ip += nrow)
720 if (addTo)
721 (transposed ? block(j,i) : block(i,j)) += this->elem[ip];
722 else
723 (transposed ? block(j,i) : block(i,j)) = this->elem[ip];
724 }
725 }
726
728 matrix<T>& diag(T d, size_t dim = 0)
729 {
730 if (dim > 0)
731 this->resize(dim,dim,true);
732 else
733 this->resize(nrow,ncol,true);
734 for (size_t r = 0; r < nrow && r < ncol; r++)
735 this->elem[r+nrow*r] = d;
736 return *this;
737 }
739 matrix<T>& diag(const T* d, size_t dim = 0)
740 {
741 if (dim > 0)
742 this->resize(dim,dim,true);
743 else
744 this->resize(nrow,ncol,true);
745 for (size_t r = 0; r < nrow && r < ncol; r++)
746 this->elem[r+nrow*r] = d[r];
747 return *this;
748 }
750 matrix<T>& diag(const std::vector<T>& d)
751 {
752 if (d.empty())
753 this->clear();
754 else
755 this->diag(d.data(), d.size());
756 return *this;
757 }
758
761 matrix<T>& scale(const T* d, size_t dim);
763 matrix<T>& scale(const std::vector<T>& d)
764 {
765 return this->scale(d.data(), d.size());
766 }
767
770 {
771 matrix<T> tmp(*this);
772 for (size_t r = 0; r < nrow; r++)
773 for (size_t c = 0; c < ncol; c++)
774 this->elem[c+ncol*r] = tmp.elem[r+nrow*c];
775
776 nrow = tmp.ncol;
777 ncol = tmp.nrow;
778 return *this;
779 }
780
782 T trace() const { return this->elem.sum(0,nrow+1); }
784 T rowsum(size_t r) const { return this->elem.sum(r-1,nrow); }
786 T colsum(size_t c) const { return this->elem.sum(nrow*(c-1),1,nrow*c); }
787
788#define THIS(i,j) this->operator()(i,j)
789
791 T det() const
792 {
793 if (ncol == 1 && nrow >= 1)
794 return THIS(1,1);
795 else if (ncol == 2 && nrow >= 2)
796 return THIS(1,1)*THIS(2,2) - THIS(2,1)*THIS(1,2);
797 else if (ncol == 3 && nrow >= 3)
798 return THIS(1,1)*(THIS(2,2)*THIS(3,3) - THIS(3,2)*THIS(2,3))
799 - THIS(1,2)*(THIS(2,1)*THIS(3,3) - THIS(3,1)*THIS(2,3))
800 + THIS(1,3)*(THIS(2,1)*THIS(3,2) - THIS(3,1)*THIS(2,2));
801 else if (ncol > 0 && nrow > 0) {
802 std::cerr <<"matrix::det: Not available for "
803 << nrow <<"x"<< ncol <<" matrices"<< std::endl;
804 ABORT_ON_SINGULARITY;
805 return T(-999);
806 }
807 else
808 return T(0);
809 }
810
814 T inverse(T tol = T(0))
815 {
816 T Det = this->det();
817 if (Det == T(-999))
818 return Det;
819 else if (Det <= tol && Det >= -tol) {
820 std::cerr <<"matrix::inverse: Singular matrix |A|="<< Det << std::endl;
821 ABORT_ON_SINGULARITY;
822 return T(0);
823 }
824
825 if (ncol == 1)
826 THIS(1,1) = T(1) / Det;
827 else if (ncol == 2) {
828 matrix<T> B(2,2);
829 B(1,1) = THIS(2,2) / Det;
830 B(2,1) = -THIS(2,1) / Det;
831 B(1,2) = -THIS(1,2) / Det;
832 B(2,2) = THIS(1,1) / Det;
833 *this = B;
834 }
835 else if (ncol == 3) {
836 matrix<T> B(3,3);
837 B(1,1) = (THIS(2,2)*THIS(3,3) - THIS(3,2)*THIS(2,3)) / Det;
838 B(2,1) = -(THIS(2,1)*THIS(3,3) - THIS(3,1)*THIS(2,3)) / Det;
839 B(3,1) = (THIS(2,1)*THIS(3,2) - THIS(3,1)*THIS(2,2)) / Det;
840 B(1,2) = -(THIS(1,2)*THIS(3,3) - THIS(3,2)*THIS(1,3)) / Det;
841 B(2,2) = (THIS(1,1)*THIS(3,3) - THIS(3,1)*THIS(1,3)) / Det;
842 B(3,2) = -(THIS(1,1)*THIS(3,2) - THIS(3,1)*THIS(1,2)) / Det;
843 B(1,3) = (THIS(1,2)*THIS(2,3) - THIS(2,2)*THIS(1,3)) / Det;
844 B(2,3) = -(THIS(1,1)*THIS(2,3) - THIS(2,1)*THIS(1,3)) / Det;
845 B(3,3) = (THIS(1,1)*THIS(2,2) - THIS(2,1)*THIS(1,2)) / Det;
846 *this = B;
847 }
848
849 return Det;
850 }
851
854 bool isSymmetric(T tol = T(0)) const
855 {
856 if (nrow != ncol)
857 return false;
858
859 for (size_t r = 0; r < nrow; r++)
860 for (size_t c = 0; c < r; c++)
861 {
862 T diff = this->elem[r+nrow*c] - this->elem[c+nrow*r];
863 if (diff < -tol || diff > tol)
864 return false;
865 }
866
867 return true;
868 }
869
871 matrix<T>& operator+=(const matrix<T>& A) { return this->add(A); }
873 matrix<T>& operator-=(const matrix<T>& A) { return this->add(A,T(-1)); }
875 matrix<T>& add(const matrix<T>& A, T alfa = T(1))
876 {
877 return static_cast<matrix<T>&>(this->matrixBase<T>::add(A,alfa));
878 }
879
881 matrix<T>& operator*=(T c) { return this->multiply(c); }
883 matrix<T>& operator/=(T d) { return this->multiply(T(1)/d); }
886 {
887 return static_cast<matrix<T>&>(this->matrixBase<T>::multiply(c));
888 }
889
902 bool transA = false, bool transB = false,
903 bool addTo = false, const T& alpha = T(1));
904
917 bool multiplyMat(const matrix<T>& A, const std::vector<T>& B,
918 bool transA = false, bool addTo = false);
919
932 bool multiplyMat(const std::vector<T>& A, const matrix<T>& B,
933 bool transB = false, bool addTo = false);
934
944 bool multiply(const std::vector<T>& X, std::vector<T>& Y,
945 bool transA = false, char addTo = 0) const;
946
952 bool multiply(const std::vector<T>& X, std::vector<T>& Y,
953 const T& alpha, const T& beta = T(0),
954 bool transA = false, int stridex = 1, int stridey = 1,
955 unsigned int ofsx = 0, unsigned int ofsy = 0) const;
956
958 bool outer_product(const std::vector<T>& X, const std::vector<T>& Y,
959 bool addTo = false, T alpha = T(1));
960
962 T normInf() const
963 {
964 if (nrow == 0)
965 return T(0);
966
967 // Compute row sums
968 vector<T> sums(nrow);
969 for (size_t i = 0; i < nrow; i++)
970 sums[i] = this->elem.asum(i,nrow);
971 return *std::max_element(sums.begin(),sums.end());
972 }
973
974 private:
976 bool compatible(const std::vector<T>& X, bool transA) const
977 {
978 if (nrow > 0 && ncol > 0)
979 if ((transA ? nrow : ncol) == X.size())
980 return true;
981
982 std::cerr <<"matrix::multiply: Incompatible matrices: A("
983 << nrow <<','<< ncol <<"), X("<< X.size() <<")\n"
984 <<" when computing Y = "
985 << (transA ? "A^t":"A") <<" * X"<< std::endl;
986 ABORT_ON_INDEX_CHECK;
987 return false;
988 }
989
991 bool compatible(const matrix<T>& A, const matrix<T>& B,
992 bool transA, bool transB, size_t& M, size_t& N, size_t& K)
993 {
994 M = transA ? A.ncol : A.nrow;
995 N = transB ? B.nrow : B.ncol;
996 K = transA ? A.nrow : A.ncol;
997 if (K == (transB ? B.ncol : B.nrow))
998 return true;
999
1000 std::cerr <<"matrix::multiply: Incompatible matrices: A("
1001 << A.nrow <<','<< A.ncol <<"), B("
1002 << B.nrow <<','<< B.ncol <<")\n"
1003 <<" when computing C = "
1004 << (transA ? "A^t":"A") <<" * "
1005 << (transB ? "B^t":"B") << std::endl;
1006 ABORT_ON_INDEX_CHECK;
1007 return false;
1008 }
1009
1012 bool compatible(const matrix<T>& A, const std::vector<T>& B,
1013 bool transA, size_t& M, size_t& N, size_t& K)
1014 {
1015 M = transA ? A.ncol : A.nrow;
1016 K = transA ? A.nrow : A.ncol;
1017 N = K > 0 ? B.size()/K : 0;
1018 if (N*K == B.size() && !B.empty())
1019 return true;
1020
1021 std::cerr <<"matrix::multiply: Incompatible matrices: A("
1022 << A.nrow <<','<< A.ncol <<"), B(r*c="<< B.size() <<")\n"
1023 <<" when computing C = "
1024 << (transA ? "A^t":"A") <<" * B"<< std::endl;
1025 ABORT_ON_INDEX_CHECK;
1026 return false;
1027 }
1028
1031 bool compatible(const std::vector<T>& A, const matrix<T>& B,
1032 bool transB, size_t& M, size_t& N, size_t& K)
1033 {
1034 N = transB ? B.nrow : B.ncol;
1035 K = transB ? B.ncol : B.nrow;
1036 M = K > 0 ? A.size() / K : 0;
1037 if (M*K == A.size() && !A.empty())
1038 return true;
1039
1040 std::cerr <<"matrix::multiply: Incompatible matrices: A(r*c="<< A.size()
1041 <<"), B("<< B.nrow <<","<< B.ncol <<")\n"
1042 <<" when computing C = A * "
1043 << (transB ? "B^t":"B") << std::endl;
1044 ABORT_ON_INDEX_CHECK;
1045 return false;
1046 }
1047
1049 bool compatible(const std::vector<T>& X, const std::vector<T>& Y)
1050 {
1051 if (X.size() == nrow && Y.size() == ncol)
1052 return true;
1053
1054 std::cerr <<"matrix::outer_product: Incompatible matrix and vectors: A("
1055 << nrow <<','<< ncol <<"), X("
1056 << X.size() <<"), Y("<< Y.size() <<")\n"
1057 <<" when computing A += X*Y^t"
1058 << std::endl;
1059 ABORT_ON_INDEX_CHECK;
1060 return false;
1061 }
1062
1063 protected:
1065 void clearIfNrowChanged(size_t n1, size_t, size_t) override
1066 {
1067 if (n1 != nrow) this->elem.clear();
1068 }
1069
1070 private:
1071 size_t& nrow;
1072 size_t& ncol;
1073 };
1074
1075
1076#ifdef HAS_BLAS
1077 //============================================================================
1078 //=== BLAS-implementation of the matrix/vector multiplication methods ====
1079 //============================================================================
1080
1081 template<> inline
1083 {
1084 cblas_sscal(myVec.size(),c,myVec.data(),1);
1085 return *this;
1086 }
1087
1088 template<> inline
1089 vector<double>& vector<double>::operator*=(double c)
1090 {
1091 cblas_dscal(myVec.size(),c,myVec.data(),1);
1092 return *this;
1093 }
1094
1095 template<> inline
1096 float vector<float>::dot(const float* v, size_t nv,
1097 size_t o1, int i1, size_t o2, int i2) const
1098 {
1099 int n1 = i1 > 1 || i1 < -1 ? myVec.size()/abs(i1) : myVec.size()-o1;
1100 int n2 = i2 > 1 || i2 < -1 ? nv/abs(i2) : nv-o2;
1101 int n = n1 < n2 ? n1 : n2;
1102 return cblas_sdot(n,myVec.data()+o1,i1,v+o2,i2);
1103 }
1104
1105 template<> inline
1106 double vector<double>::dot(const double* v, size_t nv,
1107 size_t o1, int i1, size_t o2, int i2) const
1108 {
1109 int n1 = i1 > 1 || i1 < -1 ? myVec.size()/abs(i1) : myVec.size()-o1;
1110 int n2 = i2 > 1 || i2 < -1 ? nv/abs(i2) : nv-o2;
1111 int n = n1 < n2 ? n1 : n2;
1112 return cblas_ddot(n,myVec.data()+o1,i1,v+o2,i2);
1113 }
1114
1115 template<> inline
1116 float vector<float>::norm2(size_t off, int inc) const
1117 {
1118 int n = inc > 1 || inc < -1 ? myVec.size()/abs(inc) : myVec.size()-off;
1119 return cblas_snrm2(n,myVec.data()+off,inc);
1120 }
1121
1122 template<> inline
1123 double vector<double>::norm2(size_t off, int inc) const
1124 {
1125 int n = inc > 1 || inc < -1 ? myVec.size()/abs(inc) : myVec.size()-off;
1126 return cblas_dnrm2(n,myVec.data()+off,inc);
1127 }
1128
1129 template<> inline
1130 float vector<float>::normInf(size_t& off, int inc, bool sign) const
1131 {
1132 if (inc < 1 || myVec.empty())
1133 return 0.0f;
1134
1135 const float* v = myVec.data() + off;
1136 off = 1 + cblas_isamax(myVec.size()/inc,v,inc);
1137 return sign ? v[(off-1)*inc] : fabsf(v[(off-1)*inc]);
1138 }
1139
1140 template<> inline
1141 double vector<double>::normInf(size_t& off, int inc, bool sign) const
1142 {
1143 if (inc < 1 || myVec.empty())
1144 return 0.0;
1145
1146 const double* v = myVec.data() + off;
1147 off = 1 + cblas_idamax(myVec.size()/inc,v,inc);
1148 return sign ? v[(off-1)*inc] : fabs(v[(off-1)*inc]);
1149 }
1150
1151 template<> inline
1152 float vector<float>::asum(size_t off, int inc) const
1153 {
1154 int n = inc > 1 || inc < -1 ? myVec.size()/abs(inc) : myVec.size()-off;
1155 return cblas_sasum(n,myVec.data()+off,inc);
1156 }
1157
1158 template<> inline
1159 double vector<double>::asum(size_t off, int inc) const
1160 {
1161 int n = inc > 1 || inc < -1 ? myVec.size()/abs(inc) : myVec.size()-off;
1162 return cblas_dasum(n,myVec.data()+off,inc);
1163 }
1164
1165 template<> inline
1166 vector<float>& vector<float>::add(const std::vector<float>& X,
1167 const float& alfa,
1168 unsigned int ofsx, int stridex,
1169 unsigned int ofsy, int stridey)
1170 {
1171 if (myVec.empty() && stridex > 0 && stridey > 0)
1172 myVec.resize(ofsy+stridey*(X.size()-ofsx)/stridex);
1173
1174 int nx = stridex == 0 ? 1 : 1 + (X.size()-ofsx-1)/abs(stridex);
1175 int ny = stridey == 0 ? 1 : 1 + (myVec.size()-ofsy-1)/abs(stridey);
1176 int n = nx < ny ? (stridex == 0 ? ny : nx) : (stridey == 0 ? nx : ny);
1177 if (n > 0)
1178 cblas_saxpy(n,alfa,X.data()+ofsx,stridex,myVec.data()+ofsy,stridey);
1179 return *this;
1180 }
1181
1182 template<> inline
1183 vector<double>& vector<double>::add(const std::vector<double>& X,
1184 const double& alfa,
1185 unsigned int ofsx, int stridex,
1186 unsigned int ofsy, int stridey)
1187 {
1188 if (myVec.empty() && stridex > 0 && stridey > 0)
1189 myVec.resize(ofsy+stridey*(X.size()-ofsx)/stridex);
1190
1191 int nx = stridex == 0 ? 1 : 1 + (X.size()-ofsx-1)/abs(stridex);
1192 int ny = stridey == 0 ? 1 : 1 + (myVec.size()-ofsy-1)/abs(stridey);
1193 int n = nx < ny ? (stridex == 0 ? ny : nx) : (stridey == 0 ? nx : ny);
1194 if (n > 0)
1195 cblas_daxpy(n,alfa,X.data()+ofsx,stridex,myVec.data()+ofsy,stridey);
1196 return *this;
1197 }
1198
1199 template<> inline
1200 matrixBase<float>& matrixBase<float>::add(const matrixBase<float>& A,
1201 const float& alfa)
1202 {
1203 int n = this->size() < A.size() ? this->size() : A.size();
1204 if (n > 0)
1205 cblas_saxpy(n,alfa,A.ptr(),1,this->ptr(),1);
1206 return *this;
1207 }
1208
1209 template<> inline
1210 matrixBase<double>& matrixBase<double>::add(const matrixBase<double>& A,
1211 const double& alfa)
1212 {
1213 int n = this->size() < A.size() ? this->size() : A.size();
1214 if (n > 0)
1215 cblas_daxpy(n,alfa,A.ptr(),1,this->ptr(),1);
1216 return *this;
1217 }
1218
1219 template<> inline
1220 matrixBase<float>& matrixBase<float>::multiply(const float& c)
1221 {
1222 cblas_sscal(this->size(),c,this->ptr(),1);
1223 return *this;
1224 }
1225
1226 template<> inline
1227 matrixBase<double>& matrixBase<double>::multiply(const double& c)
1228 {
1229 cblas_dscal(this->size(),c,this->ptr(),1);
1230 return *this;
1231 }
1232
1233 template<> inline
1234 matrix<float>& matrix<float>::scale(const float* d, size_t dim)
1235 {
1236 for (size_t c = 0; c < dim && c < ncol; c++)
1237 cblas_sscal(nrow,d[c],this->ptr(c),1);
1238 return *this;
1239 }
1240
1241 template<> inline
1242 matrix<double>& matrix<double>::scale(const double* d, size_t dim)
1243 {
1244 for (size_t c = 0; c < dim && c < ncol; c++)
1245 cblas_dscal(nrow,d[c],this->ptr(c),1);
1246 return *this;
1247 }
1248
1249 template<> inline
1250 bool matrix<float>::multiply(const std::vector<float>& X,
1251 std::vector<float>& Y,
1252 bool transA, char addTo) const
1253 {
1254 if (!this->compatible(X,transA))
1255 return false;
1256 else if (!addTo || Y.empty())
1257 {
1258 Y.resize(transA ? ncol : nrow);
1259 if (addTo) std::fill(Y.begin(),Y.end(),0.0f);
1260 }
1261
1262 cblas_sgemv(CblasColMajor,
1263 transA ? CblasTrans : CblasNoTrans,
1264 nrow, ncol, addTo < 0 ? -1.0f : 1.0f,
1265 this->ptr(), nrow,
1266 X.data(), 1, addTo ? 1.0f : 0.0f,
1267 Y.data(), 1);
1268
1269 return true;
1270 }
1271
1272 template<> inline
1273 bool matrix<double>::multiply(const std::vector<double>& X,
1274 std::vector<double>& Y,
1275 bool transA, char addTo) const
1276 {
1277 if (!this->compatible(X,transA))
1278 return false;
1279 else if (!addTo || Y.empty())
1280 {
1281 Y.resize(transA ? ncol : nrow);
1282 if (addTo) std::fill(Y.begin(),Y.end(),0.0);
1283 }
1284
1285 cblas_dgemv(CblasColMajor,
1286 transA ? CblasTrans : CblasNoTrans,
1287 nrow, ncol, addTo < 0 ? -1.0 : 1.0,
1288 this->ptr(), nrow,
1289 X.data(), 1, addTo ? 1.0 : 0.0,
1290 Y.data(), 1);
1291
1292 return true;
1293 }
1294
1295 template<> inline
1296 bool matrix<float>::multiply(const std::vector<float>& X,
1297 std::vector<float>& Y,
1298 const float& alpha, const float& beta,
1299 bool transA, int stridex, int stridey,
1300 unsigned int ofsx, unsigned int ofsy) const
1301 {
1302 if (stridex == 0 || stridey == 0)
1303 {
1304 std::cerr <<"matrix::multiply: Stride must be non-zero ("
1305 << stridex <<", "<< stridey <<")"<< std::endl;
1306 ABORT_ON_INDEX_CHECK;
1307 return false;
1308 }
1309
1310 if (ofsx == 0 && stridex == 1 && !this->compatible(X,transA))
1311 return false;
1312 else if (beta == 0.0f || Y.empty())
1313 {
1314 Y.resize(ofsy + 1 + ((transA ? ncol : nrow)-1)*abs(stridey));
1315 if (beta != 0.0f) std::fill(Y.begin(),Y.end(),0.0f);
1316 }
1317
1318 cblas_sgemv(CblasColMajor,
1319 transA ? CblasTrans : CblasNoTrans,
1320 nrow, ncol, alpha,
1321 this->ptr(), nrow,
1322 X.data()+ofsx, stridex, beta,
1323 Y.data()+ofsy, stridey);
1324
1325 return true;
1326 }
1327
1328 template<> inline
1329 bool matrix<double>::multiply(const std::vector<double>& X,
1330 std::vector<double>& Y,
1331 const double& alpha, const double& beta,
1332 bool transA, int stridex, int stridey,
1333 unsigned int ofsx, unsigned int ofsy) const
1334 {
1335 if (stridex == 0 || stridey == 0)
1336 {
1337 std::cerr <<"matrix::multiply: Stride must be non-zero ("
1338 << stridex <<", "<< stridey <<")"<< std::endl;
1339 ABORT_ON_INDEX_CHECK;
1340 return false;
1341 }
1342
1343 if (ofsx == 0 && stridex == 1 && !this->compatible(X,transA))
1344 return false;
1345 else if (beta == 0.0 || Y.empty())
1346 {
1347 Y.resize(ofsy + 1 + ((transA ? ncol : nrow)-1)*abs(stridey));
1348 if (beta != 0.0) std::fill(Y.begin(),Y.end(),0.0);
1349 }
1350
1351 cblas_dgemv(CblasColMajor,
1352 transA ? CblasTrans : CblasNoTrans,
1353 nrow, ncol, alpha,
1354 this->ptr(), nrow,
1355 X.data()+ofsx, stridex, beta,
1356 Y.data()+ofsy, stridey);
1357
1358 return true;
1359 }
1360
1361 template<> inline
1362 matrix<float>& matrix<float>::multiply(const matrix<float>& A,
1363 const matrix<float>& B,
1364 bool transA, bool transB,
1365 bool addTo, const float& alpha)
1366 {
1367 size_t M, N, K;
1368 if (!this->compatible(A,B,transA,transB,M,N,K))
1369 {
1370 this->clear();
1371 return *this;
1372 }
1373 else if (!addTo || this->empty())
1374 this->resize(M,N);
1375
1376 cblas_sgemm(CblasColMajor,
1377 transA ? CblasTrans : CblasNoTrans,
1378 transB ? CblasTrans : CblasNoTrans,
1379 M, N, K, alpha,
1380 A.ptr(), A.nrow,
1381 B.ptr(), B.nrow,
1382 addTo ? 1.0f : 0.0f,
1383 this->ptr(), nrow);
1384
1385 return *this;
1386 }
1387
1388 template<> inline
1389 matrix<double>& matrix<double>::multiply(const matrix<double>& A,
1390 const matrix<double>& B,
1391 bool transA, bool transB,
1392 bool addTo, const double& alpha)
1393 {
1394 size_t M, N, K;
1395 if (!this->compatible(A,B,transA,transB,M,N,K))
1396 {
1397 this->clear();
1398 return *this;
1399 }
1400 else if (!addTo || this->empty())
1401 this->resize(M,N);
1402
1403 cblas_dgemm(CblasColMajor,
1404 transA ? CblasTrans : CblasNoTrans,
1405 transB ? CblasTrans : CblasNoTrans,
1406 M, N, K, alpha,
1407 A.ptr(), A.nrow,
1408 B.ptr(), B.nrow,
1409 addTo ? 1.0 : 0.0,
1410 this->ptr(), nrow);
1411
1412 return *this;
1413 }
1414
1415 template<> inline
1416 bool matrix<float>::multiplyMat(const matrix<float>& A,
1417 const std::vector<float>& B,
1418 bool transA, bool addTo)
1419 {
1420 size_t M, N, K;
1421 if (!this->compatible(A,B,transA,M,N,K))
1422 return false;
1423 else if (!addTo || this->empty())
1424 this->resize(M,N);
1425
1426 cblas_sgemm(CblasColMajor,
1427 transA ? CblasTrans : CblasNoTrans, CblasNoTrans,
1428 M, N, K, 1.0f,
1429 A.ptr(), A.nrow,
1430 B.data(), K,
1431 addTo ? 1.0f : 0.0f,
1432 this->ptr(), nrow);
1433
1434 return true;
1435 }
1436
1437 template<> inline
1438 bool matrix<double>::multiplyMat(const matrix<double>& A,
1439 const std::vector<double>& B,
1440 bool transA, bool addTo)
1441 {
1442 size_t M, N, K;
1443 if (!this->compatible(A,B,transA,M,N,K))
1444 return false;
1445 else if (!addTo || this->empty())
1446 this->resize(M,N);
1447
1448 cblas_dgemm(CblasColMajor,
1449 transA ? CblasTrans : CblasNoTrans, CblasNoTrans,
1450 M, N, K, 1.0,
1451 A.ptr(), A.nrow,
1452 B.data(), K,
1453 addTo ? 1.0 : 0.0,
1454 this->ptr(), nrow);
1455
1456 return true;
1457 }
1458
1459 template<> inline
1460 bool matrix<float>::multiplyMat(const std::vector<float>& A,
1461 const matrix<float>& B,
1462 bool transB, bool addTo)
1463 {
1464 size_t M, N, K;
1465 if (!this->compatible(A,B,transB,M,N,K))
1466 return false;
1467 else if (!addTo || this->empty())
1468 this->resize(M,N);
1469
1470 cblas_sgemm(CblasColMajor,
1471 CblasNoTrans, transB ? CblasTrans : CblasNoTrans,
1472 M, N, K, 1.0f,
1473 A.data(), M,
1474 B.ptr(), B.nrow,
1475 addTo ? 1.0f : 0.0f,
1476 this->ptr(), nrow);
1477
1478 return true;
1479 }
1480
1481 template<> inline
1482 bool matrix<double>::multiplyMat(const std::vector<double>& A,
1483 const matrix<double>& B,
1484 bool transB, bool addTo)
1485 {
1486 size_t M, N, K;
1487 if (!this->compatible(A,B,transB,M,N,K))
1488 return false;
1489 else if (!addTo || this->empty())
1490 this->resize(M,N);
1491
1492 cblas_dgemm(CblasColMajor,
1493 CblasNoTrans, transB ? CblasTrans : CblasNoTrans,
1494 M, N, K, 1.0,
1495 A.data(), M,
1496 B.ptr(), B.nrow,
1497 addTo ? 1.0 : 0.0,
1498 this->ptr(), nrow);
1499
1500 return true;
1501 }
1502
1503 template<> inline
1504 bool matrix<float>::outer_product(const std::vector<float>& X,
1505 const std::vector<float>& Y,
1506 bool addTo, float alpha)
1507 {
1508 if (!addTo)
1509 this->resize(X.size(),Y.size());
1510 else if (!this->compatible(X,Y))
1511 return false;
1512
1513 cblas_sgemm(CblasColMajor,
1514 CblasNoTrans, CblasTrans,
1515 nrow, ncol, 1, alpha,
1516 X.data(), nrow,
1517 Y.data(), ncol,
1518 addTo ? 1.0f : 0.0f,
1519 this->ptr(), nrow);
1520
1521 return true;
1522 }
1523
1524 template<> inline
1525 bool matrix<double>::outer_product(const std::vector<double>& X,
1526 const std::vector<double>& Y,
1527 bool addTo, double alpha)
1528 {
1529 if (!addTo)
1530 this->resize(X.size(),Y.size());
1531 else if (!this->compatible(X,Y))
1532 return false;
1533
1534 cblas_dgemm(CblasColMajor,
1535 CblasNoTrans, CblasTrans,
1536 nrow, ncol, 1, alpha,
1537 X.data(), nrow,
1538 Y.data(), ncol,
1539 addTo ? 1.0 : 0.0,
1540 this->ptr(), nrow);
1541
1542 return true;
1543 }
1544
1545#else
1546 //============================================================================
1547 //=== Non-BLAS inlined implementations (slow...) =========================
1548 //============================================================================
1549
1550 template<class T> inline
1552 {
1553 for (T& x : myVec)
1554 x *= c;
1555 return *this;
1556 }
1557
1558 template<class T> inline
1559 T vector<T>::dot(const T* v, size_t nv,
1560 size_t o1, int i1, size_t o2, int i2) const
1561 {
1562 size_t i, j;
1563 T dotprod = T(0);
1564 for (i = o1, j = o2; i < myVec.size() && j < nv; i += i1, j += i2)
1565 dotprod += myVec[i] * v[j];
1566 return dotprod;
1567 }
1568
1569 template<class T> inline
1570 T vector<T>::norm2(size_t off, int inc) const
1571 {
1572 double xsum = 0.0;
1573 if (inc < 1 || myVec.size() <= off)
1574 return xsum;
1575
1576 // Warning: This might overflow or underflow for large/small values
1577 for (size_t i = off; i < myVec.size(); i += inc)
1578 xsum += myVec[i]*myVec[i];
1579 return sqrt(xsum);
1580 }
1581
1582 template<class T> inline
1583 T vector<T>::normInf(size_t& off, int inc, bool sign) const
1584 {
1585 T xmax = T(0);
1586 if (inc < 1 || myVec.size() <= off)
1587 return xmax;
1588
1589 T amax = T(0);
1590 for (size_t i = off; i < myVec.size(); i += inc)
1591 if (myVec[i] > amax)
1592 {
1593 off = 1+i/inc;
1594 xmax = amax = myVec[i];
1595 }
1596 else if (myVec[i] < -amax)
1597 {
1598 off = 1+i/inc;
1599 xmax = myVec[i];
1600 amax = -xmax;
1601 }
1602
1603 return sign ? xmax : amax;
1604 }
1605
1606 template<class T> inline
1607 T vector<T>::asum(size_t off, int inc) const
1608 {
1609 T xsum = T(0);
1610 if (inc < 1 || myVec.size() <= off)
1611 return xsum;
1612
1613 for (size_t i = off; i < myVec.size(); i += inc)
1614 xsum += myVec[i] < T(0) ? -myVec[i] : myVec[i];
1615 return xsum;
1616 }
1617
1618 template<class T> inline
1619 vector<T>& vector<T>::add(const std::vector<T>& X, const T& alfa,
1620 unsigned int ofsx, int stridex,
1621 unsigned int ofsy, int stridey)
1622 {
1623 if (stridex < 0 || stridey < 0 || stridex+stridey == 0)
1624 {
1625 std::cerr <<"vector::add: Negative stride not supported ("
1626 << stridex <<", "<< stridey <<")"<< std::endl;
1627 ABORT_ON_INDEX_CHECK;
1628 return *this;
1629 }
1630
1631 std::vector<T>& Y = myVec;
1632 if (Y.empty() && stridex > 0)
1633 Y.resize(ofsy+stridey*(X.size()-ofsx)/stridex);
1634
1635 for (; ofsx < X.size() && ofsy < Y.size(); ofsx += stridex, ofsy += stridey)
1636 Y[ofsy] += alfa*X[ofsx];
1637 return *this;
1638 }
1639
1640 template<class T> inline
1642 {
1643 const vector<T>& X = A.elem;
1644 vector<T>& Y = this->elem;
1645
1646 for (size_t i = 0; i < X.size() && i < Y.size(); i++)
1647 Y[i] += alfa*X[i];
1648 return *this;
1649 }
1650
1651 template<class T> inline
1653 {
1654 for (T& x : this->elem)
1655 x *= c;
1656 return *this;
1657 }
1658
1659 template<class T> inline
1660 matrix<T>& matrix<T>::scale(const T* d, size_t dim)
1661 {
1662 for (size_t c = 0; c < dim && c < ncol; c++)
1663 for (size_t r = 0; r < nrow; r++)
1664 this->elem[r+nrow*c] *= d[c];
1665 return *this;
1666 }
1667
1668 template<class T> inline
1669 bool matrix<T>::multiply(const std::vector<T>& X, std::vector<T>& Y,
1670 bool transA, char addTo) const
1671 {
1672 if (!this->compatible(X,transA))
1673 return false;
1674 else if (!addTo || Y.empty())
1675 {
1676 Y.resize(transA ? ncol : nrow);
1677 std::fill(Y.begin(),Y.end(),T(0));
1678 }
1679
1680 for (size_t i = 0; i < Y.size(); i++)
1681 for (size_t j = 0; j < X.size(); j++)
1682 if (transA)
1683 Y[i] += THIS(j+1,i+1) * (addTo < 0 ? -X[j] : X[j]);
1684 else
1685 Y[i] += THIS(i+1,j+1) * (addTo < 0 ? -X[j] : X[j]);
1686
1687 return true;
1688 }
1689
1690 template<class T> inline
1691 bool matrix<T>::multiply(const std::vector<T>& X, std::vector<T>& Y,
1692 const T& alpha, const T& beta,
1693 bool transA, int stridex, int stridey,
1694 unsigned int ofsx, unsigned int ofsy) const
1695 {
1696 if (stridex <= 0 || stridey <= 0)
1697 {
1698 std::cerr <<"matrix::multiply: Non-positive stride not supported ("
1699 << stridex <<", "<< stridey <<")"<< std::endl;
1700 ABORT_ON_INDEX_CHECK;
1701 return false;
1702 }
1703
1704 if (ofsx == 0 && stridex == 1 && !this->compatible(X,transA))
1705 return false;
1706 else if (beta == T(0) || Y.empty())
1707 {
1708 Y.resize(ofsy + 1 + ((transA ? ncol : nrow)-1)*stridey);
1709 std::fill(Y.begin(),Y.end(),T(0));
1710 }
1711 else if (beta != T(1))
1712 for (size_t i = ofsy; i < Y.size(); i += stridey)
1713 Y[i] *= beta;
1714
1715 size_t a, b, i, j;
1716 for (a = 1, i = ofsy; i < Y.size(); a++, i += stridey)
1717 for (b = 1, j = ofsx; j < X.size(); b++, j += stridex)
1718 if (transA)
1719 Y[i] += alpha * THIS(b,a) * X[j];
1720 else
1721 Y[i] += alpha * THIS(a,b) * X[j];
1722
1723 return true;
1724 }
1725
1726 template<class T> inline
1728 const matrix<T>& B,
1729 bool transA, bool transB, bool addTo,
1730 const T& alpha)
1731 {
1732 size_t M, N, K;
1733 if (!this->compatible(A,B,transA,transB,M,N,K))
1734 {
1735 this->clear();
1736 return *this;
1737 }
1738 else if (!addTo || this->empty())
1739 this->resize(M,N,true);
1740
1741 for (size_t i = 1; i <= M; i++)
1742 for (size_t j = 1; j <= N; j++)
1743 for (size_t k = 1; k <= K; k++)
1744 if (transA && transB)
1745 THIS(i,j) += alpha*A(k,i)*B(j,k);
1746 else if (transA)
1747 THIS(i,j) += alpha*A(k,i)*B(k,j);
1748 else if (transB)
1749 THIS(i,j) += alpha*A(i,k)*B(j,k);
1750 else
1751 THIS(i,j) += alpha*A(i,k)*B(k,j);
1752
1753 return *this;
1754 }
1755
1756 template<class T> inline
1757 bool matrix<T>::multiplyMat(const matrix<T>& A, const std::vector<T>& B,
1758 bool transA, bool addTo)
1759 {
1760 size_t M, N, K;
1761 if (!this->compatible(A,B,transA,M,N,K))
1762 return false;
1763 else if (!addTo || this->empty())
1764 this->resize(M,N,true);
1765
1766 for (size_t i = 1; i <= M; i++)
1767 for (size_t j = 1; j <= N; j++)
1768 for (size_t k = 1; k <= K; k++)
1769 if (transA)
1770 THIS(i,j) += A(k,i)*B[k-1+K*(j-1)];
1771 else
1772 THIS(i,j) += A(i,k)*B[k-1+K*(j-1)];
1773
1774 return true;
1775 }
1776
1777 template<class T> inline
1778 bool matrix<T>::multiplyMat(const std::vector<T>& A, const matrix<T>& B,
1779 bool transB, bool addTo)
1780 {
1781 size_t M, N, K;
1782 if (!this->compatible(A,B,transB,M,N,K))
1783 return false;
1784 else if (!addTo || this->empty())
1785 this->resize(M,N,true);
1786
1787 for (size_t i = 1; i <= M; i++)
1788 for (size_t j = 1; j <= N; j++)
1789 for (size_t k = 1; k <= K; k++)
1790 if (transB)
1791 THIS(i,j) += A[i-1+M*(k-1)]*B(j,k);
1792 else
1793 THIS(i,j) += A[i-1+M*(k-1)]*B(k,j);
1794
1795 return true;
1796 }
1797
1798 template<class T> inline
1799 bool matrix<T>::outer_product(const std::vector<T>& X,
1800 const std::vector<T>& Y,
1801 bool addTo, T alpha)
1802 {
1803 if (!addTo)
1804 this->resize(X.size(),Y.size());
1805 else if (!this->compatible(X,Y))
1806 return false;
1807
1808 if (addTo)
1809 for (size_t j = 0; j < ncol; j++)
1810 for (size_t i = 0; i < nrow; i++)
1811 this->elem[i+nrow*j] += alpha*X[i]*Y[j];
1812 else
1813 for (size_t j = 0; j < ncol; j++)
1814 for (size_t i = 0; i < nrow; i++)
1815 this->elem[i+nrow*j] = alpha*X[i]*Y[j];
1816
1817 return true;
1818 }
1819
1820#endif
1821
1822 //============================================================================
1823 //=== Global operators ===================================================
1824 //============================================================================
1825
1831 template<class T> inline T trunc(T v)
1832 {
1833 return v > T(zero_print_tol) || v < T(-zero_print_tol) || std::isnan(v) ?
1834 v : T(0);
1835 }
1836
1838 template<class T> std::istream& operator>>(std::istream& s, vector<T>& X)
1839 {
1840 size_t n = 0;
1841 s >> n;
1842 X.resize(n,true);
1843 for (T& val : X)
1844 s >> val;
1845 return s;
1846 }
1847
1849 template<class T> std::ostream& operator<<(std::ostream& s,
1850 const vector<T>& X)
1851 {
1852 if (X.size() < 1)
1853 s <<" (empty)";
1854 else for (size_t i = 0; i < X.size(); i++)
1855 s << ((i%nval_per_line) ? ' ':'\n') << trunc(X[i]);
1856
1857 return s << std::endl;
1858 }
1859
1861 template<class T> std::istream& operator>>(std::istream& s, matrix<T>& A)
1862 {
1863 size_t m = 0, n = 0;
1864 char c = 0;
1865 while (s.get(c) && isspace(c));
1866 bool symmetric = (c == 'S' || c == 's');
1867 bool columnori = (c == 'C' || c == 'c');
1868 if (symmetric)
1869 {
1870 s.ignore(10,':');
1871 s >> m;
1872 n = m;
1873 }
1874 else if (isalpha(c))
1875 {
1876 s.ignore(15,' ');
1877 s >> m >> n;
1878 }
1879 else
1880 {
1881 s.putback(c);
1882 s >> m >> n;
1883 }
1884 A.resize(m,n);
1885 for (size_t i = 1; i <= m; i++)
1886 {
1887 while (s.get(c) && isspace(c));
1888 if (c == 'R')
1889 s.ignore(10,':');
1890 else
1891 s.putback(c);
1892 for (size_t j = (symmetric ? i : 1); j <= n; j++)
1893 {
1894 s >> (columnori ? A(j,i) : A(i,j));
1895 if (symmetric && j > i)
1896 A(j,i) = A(i,j);
1897 }
1898 }
1899 return s;
1900 }
1901
1907 template<class T> std::ostream& operator<<(std::ostream& s,
1908 const matrix<T>& A)
1909 {
1910 if (A.rows() < 1 || A.cols() < 1)
1911 return s <<" (empty)"<< std::endl;
1912
1913 bool symm = A.isSymmetric(zero_print_tol);
1914 for (size_t i = 1; i <= A.rows(); i++)
1915 {
1916 size_t c1 = symm ? i : 1;
1917 s <<"\nRow "<< i <<": "<< trunc(A(i,c1));
1918 for (size_t j = c1+1; j <= A.cols(); j++)
1919 s <<' '<< trunc(A(i,j));
1920 }
1921
1922 return s << std::endl;
1923 }
1924
1926 template<class T> void writeMatlab(const char* label, const vector<T>& X,
1927 std::ostream& s = std::cout)
1928 {
1929 if (label)
1930 s << label <<" = [";
1931 else
1932 s <<"[";
1933
1934 for (size_t i = 1; i <= X.size(); i++)
1935 s <<' '<< trunc(X(i));
1936 s <<" ];"<< std::endl;
1937 }
1938
1940 template<class T> void writeMatlab(const char* label, const matrix<T>& A,
1941 std::ostream& s = std::cout)
1942 {
1943 if (label)
1944 s << label <<" = [";
1945 else
1946 s <<"[";
1947
1948 size_t nsp = label ? 4 + strlen(label) : 1;
1949 for (size_t i = 1; i <= A.rows(); i++)
1950 {
1951 if (i > 1)
1952 {
1953 s <<";\n";
1954 for (size_t k = 0; k < nsp; k++) s <<' ';
1955 }
1956 for (size_t j = 1; j <= A.cols(); j++)
1957 s <<' '<< trunc(A(i,j));
1958 }
1959 s <<" ];"<< std::endl;
1960 }
1961}
1962
1963#undef THIS
1964#endif
BLAS support for various platforms.
static SystemMatrix * K
Pointer to coefficient matrix A.
Definition EigSolver.C:91
static SystemMatrix * M
Pointer to coefficient matrix B.
Definition EigSolver.C:92
virtual bool empty() const
Checks if the matrix is empty.
Definition SystemMatrix.h:249
Common base class for multi-dimensional (2D and 3D) matrices.
Definition matrix.h:308
size_t n[4]
Dimension of the matrix.
Definition matrix.h:440
size_t dim(short int d=1) const
Query dimensions.
Definition matrix.h:376
matrixBase< T > & add(const matrixBase< T > &A, const T &alfa)
Add the given matrix A scaled by alfa to *this.
Definition matrix.h:1641
matrixBase(vector< T > &vec)
Constructor using an external vector for matrix element storage.
Definition matrix.h:313
void fill(const T *values, size_t n=0)
Fill the matrix with data from an array.
Definition matrix.h:413
matrixBase()
The constructor is protected to allow sub-class instances only.
Definition matrix.h:311
vector< T > & elem
Actual matrix elements, stored column by column.
Definition matrix.h:441
std::vector< T >::iterator end()
Iterator to the end of the matrix elements.
Definition matrix.h:405
void fill(T s)
Fill the matrix with a scalar value.
Definition matrix.h:411
matrixBase(const matrixBase< T > &mat, bool copyContent=true)
Copy constructor.
Definition matrix.h:322
const vector< T > & toVec() const
Type casting to a one-dimensional utl::vector, for access.
Definition matrix.h:385
size_t size() const
Query total matrix size.
Definition matrix.h:378
T norm2(int inc=1) const
Return the Euclidean norm of the matrix.
Definition matrix.h:422
std::vector< T >::iterator begin()
Iterator to the start of the matrix elements.
Definition matrix.h:403
void clear()
Clears the matrix and sets its dimension to zero.
Definition matrix.h:408
T asum(int inc=1) const
Return the sum of the absolute value of the matrix elements.
Definition matrix.h:425
T sum(int inc=1) const
Return the sum of the matrix elements.
Definition matrix.h:429
bool empty() const
Check if the matrix is empty.
Definition matrix.h:380
bool zero(T tol=T(0)) const
Check if the matrix elements are all zero.
Definition matrix.h:382
virtual void clearIfNrowChanged(size_t n1, size_t n2, size_t n3)=0
Clears the matrix content if the first dimension(s) changed.
void redim(size_t n_1, size_t n_2, size_t n_3, size_t n_4, bool forceClear)
Resize the matrix to dimension .
Definition matrix.h:338
T * ptr(size_t c=0)
Access through pointer.
Definition matrix.h:392
matrixBase(size_t n_1, size_t n_2, size_t n_3=1, size_t n_4=1)
Constructor creating a matrix of dimension .
Definition matrix.h:316
const T * ptr(size_t c=0) const
Reference through pointer.
Definition matrix.h:397
vector< T > myElem
Internal matrix storage.
Definition matrix.h:444
matrixBase< T > & multiply(const T &c)
Multiplication of this matrix by a scalar c.
Definition matrix.h:1652
Two-dimensional rectangular matrix with some algebraic operations.
Definition matrix.h:456
matrix< T > & operator*=(T c)
Multiplication with a scalar.
Definition matrix.h:881
const T & operator()(size_t r, size_t c) const
Index-1 based element reference.
Definition matrix.h:606
size_t cols() const
Query number of matrix columns.
Definition matrix.h:572
bool multiply(const std::vector< T > &X, std::vector< T > &Y, const T &alpha, const T &beta=T(0), bool transA=false, int stridex=1, int stridey=1, unsigned int ofsx=0, unsigned int ofsy=0) const
Matrix-vector multiplication.
Definition matrix.h:1691
matrix< T > & transpose()
Replace the current matrix by its transpose.
Definition matrix.h:769
matrix< T > & diag(const T *d, size_t dim=0)
Create a diagonal matrix.
Definition matrix.h:739
bool multiply(const std::vector< T > &X, std::vector< T > &Y, bool transA=false, char addTo=0) const
Matrix-vector multiplication.
Definition matrix.h:1669
T trace() const
Return the trace of the matrix (sum of its diagonal elements).
Definition matrix.h:782
matrix(size_t r, size_t c)
Constructor creating a matrix of dimension .
Definition matrix.h:464
void extractBlock(matrix< T > &block, size_t r, size_t c, bool addTo=false, bool transposed=false) const
Extract a block of the matrix to another matrix.
Definition matrix.h:711
void fillRow(size_t r, const T *data)
Fill a row of the matrix.
Definition matrix.h:673
matrix< T > & scale(const T *d, size_t dim)
Scale the columns of a matrix.
Definition matrix.h:1660
void clearIfNrowChanged(size_t n1, size_t, size_t) override
Clears the content if the number of rows changed.
Definition matrix.h:1065
T normInf() const
Return the infinite norm of the matrix.
Definition matrix.h:962
matrix< T > & expandRows(int incRows, bool setRows=false)
Increase or decrease the number of rows in the matrix.
Definition matrix.h:497
matrix< T > & add(const matrix< T > &A, T alfa=T(1))
Add the given matrix A scaled by alfa to *this.
Definition matrix.h:875
size_t & ncol
Number of matrix columns.
Definition matrix.h:1072
bool augmentCols(const matrix< T > &B)
Increase the number of columns by augmenting the given matrix.
Definition matrix.h:559
bool compatible(const std::vector< T > &X, const std::vector< T > &Y)
Check dimension compatibility for outer product multiplication.
Definition matrix.h:1049
bool augmentRows(const matrix< T > &B, bool prepend=false)
Increase the number of rows by augmenting the given matrix.
Definition matrix.h:534
matrix< T > & multiply(const matrix< T > &A, const matrix< T > &B, bool transA=false, bool transB=false, bool addTo=false, const T &alpha=T(1))
Matrix-matrix multiplication.
Definition matrix.h:1727
matrix< T > & diag(const std::vector< T > &d)
Create a diagonal matrix.
Definition matrix.h:750
bool isSymmetric(T tol=T(0)) const
Check for symmetry.
Definition matrix.h:854
T det() const
Compute the determinant of a square matrix.
Definition matrix.h:791
T inverse(T tol=T(0))
Compute the inverse of a square matrix.
Definition matrix.h:814
matrix< T > & operator+=(const matrix< T > &A)
Add the given matrix A to *this.
Definition matrix.h:871
T & operator()(size_t r, size_t c)
Index-1 based element access.
Definition matrix.h:597
void fillColumn(size_t c, const T *data)
Fill a column of the matrix.
Definition matrix.h:666
matrix(const matrix< T > &mat, bool transposed=false)
Copy constructor, optionally creates the transpose of mat.
Definition matrix.h:467
void fillBlock(const matrix< T > &block, size_t r, size_t c, bool transposed=false)
Fill a block of the matrix with another matrix.
Definition matrix.h:683
matrix< T > & scale(const std::vector< T > &d)
Scale the columns of a matrix.
Definition matrix.h:763
bool compatible(const matrix< T > &A, const matrix< T > &B, bool transA, bool transB, size_t &M, size_t &N, size_t &K)
Check dimension compatibility for matrix-matrix multiplication.
Definition matrix.h:991
matrix< T > & operator=(const std::vector< T > &X)
Overloaded assignment operator.
Definition matrix.h:586
size_t & nrow
Number of matrix rows.
Definition matrix.h:1071
matrix< T > & operator/=(T d)
Division by a scalar.
Definition matrix.h:883
T colsum(size_t c) const
Return the sum of a matrix column.
Definition matrix.h:786
matrix< T > & multiply(T c)
Multiplication of this matrix by a scalar c.
Definition matrix.h:885
void resize(size_t r, size_t c, bool forceClear=false)
Resize the matrix to dimension .
Definition matrix.h:488
T rowsum(size_t r) const
Return the sum of a matrix row.
Definition matrix.h:784
size_t rows() const
Query number of matrix rows.
Definition matrix.h:570
virtual ~matrix()
Empty destructor.
Definition matrix.h:480
matrix()
Constructor creating an empty matrix.
Definition matrix.h:459
std::vector< T > getColumn(size_t c) const
Extract a column from the matrix.
Definition matrix.h:627
void addBlock(const matrix< T > &block, T s, size_t r, size_t c, bool transposed=false)
Add a scalar multiple of another matrix to a block of the matrix.
Definition matrix.h:697
bool multiplyMat(const std::vector< T > &A, const matrix< T > &B, bool transB=false, bool addTo=false)
Matrix-matrix multiplication.
Definition matrix.h:1778
bool outer_product(const std::vector< T > &X, const std::vector< T > &Y, bool addTo=false, T alpha=T(1))
Outer product between two vectors.
Definition matrix.h:1799
void fillColumn(size_t c, const std::vector< T > &data)
Fill a column of the matrix.
Definition matrix.h:658
matrix< T > & diag(T d, size_t dim=0)
Create a diagonal matrix.
Definition matrix.h:728
bool multiplyMat(const matrix< T > &A, const std::vector< T > &B, bool transA=false, bool addTo=false)
Matrix-matrix multiplication.
Definition matrix.h:1757
matrix< T > & operator=(const matrix< T > &A)
Assignment operator.
Definition matrix.h:575
matrix(vector< T > &vec)
Constructor using an external vector for matrix element storage.
Definition matrix.h:461
bool compatible(const std::vector< T > &X, bool transA) const
Check dimension compatibility for matrix-vector multiplication.
Definition matrix.h:976
matrix< T > & operator-=(const matrix< T > &A)
Subtract the given matrix A from *this.
Definition matrix.h:873
bool compatible(const matrix< T > &A, const std::vector< T > &B, bool transA, size_t &M, size_t &N, size_t &K)
Check dimension compatibility for matrix-matrix multiplication, when the matrix B is represented by a...
Definition matrix.h:1012
void fill(const std::vector< T > &v, size_t n, size_t m=0)
Fill the matrix with vector data.
Definition matrix.h:640
vector< T > getRow(size_t r) const
Extract a row from the matrix.
Definition matrix.h:614
bool compatible(const std::vector< T > &A, const matrix< T > &B, bool transB, size_t &M, size_t &N, size_t &K)
Check dimension compatibility for matrix-matrix multiplication, when the matrix A is represented by a...
Definition matrix.h:1031
A vector class with some added algebraic operations.
Definition matrix.h:64
VecIter begin()
Start of the vector container, for update.
Definition matrix.h:108
VecIter end()
End of the vector container, for update.
Definition matrix.h:110
vector< T > & operator/=(T d)
Division by a scalar.
Definition matrix.h:164
vector()
Constructor creating an empty vector.
Definition matrix.h:67
vector(const T *values, size_t n)
Constructor creating a vector from a C-array.
Definition matrix.h:71
vector< T > & operator=(const std::vector< T > &X)
Overloaded assignment operator.
Definition matrix.h:76
vector< T > & operator-=(const vector< T > &X)
Subtract the given vector X from *this.
Definition matrix.h:184
void fill(T s)
Fill the vector with a scalar value.
Definition matrix.h:137
void fill(const T *values, size_t n=0)
Fill the vector with data from an array.
Definition matrix.h:139
T asum(size_t off=0, int inc=1) const
Return the sum of the absolute value of the vector elements.
Definition matrix.h:1607
T max() const
Return the largest element of the vector.
Definition matrix.h:247
typename std::vector< T >::iterator VecIter
Convenience alias for non-const iterators.
Definition matrix.h:101
const T * ptr() const
Reference through pointer.
Definition matrix.h:85
void push_back(T c)
Append a scalar value to the vector, increasing its size by one.
Definition matrix.h:147
bool empty() const
Is the vector empty (zero size)?
Definition matrix.h:90
T normInf(int inc=1) const
Return the infinite norm of the vector (no index offset).
Definition matrix.h:244
T & operator()(size_t i)
Index-1 based element access.
Definition matrix.h:123
vector< T > & operator+=(const vector< T > &X)
Add the given vector X to *this.
Definition matrix.h:182
void reserve(size_t n)
Pre-allocation of vector length to n.
Definition matrix.h:293
void push_back(const T *p, const T *q)
Append a range of values increasing the size by q-p.
Definition matrix.h:156
bool zero(T tol=T(0)) const
Is the vector elements all zero?
Definition matrix.h:92
vector< T > & relax(T alfa, const std::vector< T > &X, const std::vector< T > &Y)
Perform where Z = *this.
Definition matrix.h:203
vector< T > & add(const std::vector< T > &X, const T &alfa=T(1), unsigned int ofsx=0, int stridex=1, unsigned int ofsy=0, int stridey=1)
Add the given vector X scaled by alfa to *this.
Definition matrix.h:1619
T norm2(size_t off=0, int inc=1) const
Return the Euclidean norm of the vector.
Definition matrix.h:1570
ConstVecIter begin() const
Start of the vector container, for access.
Definition matrix.h:104
void swap(vector< T > &vec)
Swap the content with another vector.
Definition matrix.h:159
vector< T > & operator*=(const std::vector< T > &X)
Component-wise multiplication with a vector.
Definition matrix.h:167
const T & operator()(size_t i) const
Index-1 based element reference.
Definition matrix.h:130
std::vector< T > myVec
Internal vector storage.
Definition matrix.h:298
typename std::vector< T >::const_iterator ConstVecIter
Convenience alias for const iterators.
Definition matrix.h:99
vector< T > & operator/=(const std::vector< T > &X)
Component-wise division with a vector.
Definition matrix.h:174
vector< T > & relax(T alfa, const std::vector< T > &X)
Perform where Y = *this.
Definition matrix.h:192
T & operator[](size_t i)
Index-0 based element access.
Definition matrix.h:118
ConstVecIter end() const
End of the vector container, for access.
Definition matrix.h:106
T min() const
Return the smallest element of the vector.
Definition matrix.h:249
void push_back(ConstVecIter i1, ConstVecIter i2)
Append a range of values increasing the size by i2-i1.
Definition matrix.h:150
vector(const std::vector< T > &X)
Overloaded copy constructor.
Definition matrix.h:73
bool resize(size_t n, char forceClear=0)
Resize the vector to length n.
Definition matrix.h:277
T sum(size_t off=0, int inc=1, size_t max=0) const
Return the sum of the vector elements.
Definition matrix.h:260
void clear()
Clear the vector, setting its size to zero.
Definition matrix.h:295
T dot(const T *v, size_t nv, size_t off1=0, int inc1=1, size_t off2=0, int inc2=1) const
Dot product between *this and another vector.
Definition matrix.h:1559
vector< T > & operator*=(T c)
Multiplication with a scalar.
Definition matrix.h:1551
size_t size() const
Size of the vector.
Definition matrix.h:88
T * ptr()
Access through pointer.
Definition matrix.h:83
const T & operator[](size_t i) const
Index-0 based element reference.
Definition matrix.h:120
T normInf(size_t &off, int inc=1, bool sign=false) const
Return the infinite norm of the vector, or signed max value.
Definition matrix.h:1583
vector(size_t n)
Constructor creating a vector of length n.
Definition matrix.h:69
T dot(const std::vector< T > &v, size_t off1=0, int inc1=1, size_t off2=0, int inc2=1) const
Dot product between *this and another vector.
Definition matrix.h:225
General utility classes and functions.
Definition SIMoptions.h:22
T trunc(T v)
Truncate a value to zero when it is less than a given threshold.
Definition matrix.h:1831
std::istream & operator>>(std::istream &s, vector< T > &X)
Read the vector X from the stream s.
Definition matrix.h:1838
double zero_print_tol
Zero tolerance for printing numbers.
Definition MatVec.C:24
std::ostream & operator<<(std::ostream &s, const vector< T > &X)
Print the vector X to the stream s.
Definition matrix.h:1849
int nval_per_line
Number of values to print per line.
Definition MatVec.C:23
const char RETAIN
Flag for vector::resize() method telling it to retain its content.
Definition matrix.h:55
void writeMatlab(const char *label, const vector< T > &X, std::ostream &s=std::cout)
Print the vector X to the stream s in matlab format.
Definition matrix.h:1926
Global parameters for controlling the print of vectors and matrices.