Geophysical Inversion and Modelling Library v1.5.4
Loading...
Searching...
No Matches
matrix.h
1/******************************************************************************
2 * Copyright (C) 2007-2024 by the GIMLi development team *
3 * Carsten Rücker carsten@resistivity.net *
4 * *
5 * Licensed under the Apache License, Version 2.0 (the "License"); *
6 * you may not use this file except in compliance with the License. *
7 * You may obtain a copy of the License at *
8 * *
9 * http://www.apache.org/licenses/LICENSE-2.0 *
10 * *
11 * Unless required by applicable law or agreed to in writing, software *
12 * distributed under the License is distributed on an "AS IS" BASIS, *
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
14 * See the License for the specific language governing permissions and *
15 * limitations under the License. *
16 * *
17 ******************************************************************************/
18
19#ifndef _GIMLI_MATRIX__H
20#define _GIMLI_MATRIX__H
21
22#include "gimli.h"
23#include "pos.h"
24#include "vector.h"
25
26#include <cstring>
27#include <fstream>
28#include <iostream>
29#include <cerrno>
30
31#ifdef USE_THREADS
32 #if USE_BOOST_THREAD
33 #include <boost/thread.hpp>
34 #endif // USE_BOOST_THREAD
35#endif // USE_THREADS
36
37namespace GIMLI{
38
39template < class ValueType > class DLLEXPORT Matrix3 {
40public:
41 ValueType mat_[9];
42
43 Matrix3()
44 : valid_(false){ clear(); }
45
46 Matrix3(const Matrix3 < ValueType > & m ){
47 mat_[0] = m.mat_[0]; mat_[1] = m.mat_[1]; mat_[2] = m.mat_[2];
48 mat_[3] = m.mat_[3]; mat_[4] = m.mat_[4]; mat_[5] = m.mat_[5];
49 mat_[6] = m.mat_[6]; mat_[7] = m.mat_[7]; mat_[8] = m.mat_[8];
50 }
51
52 inline ValueType & operator [](Index i){ return mat_[i];}
53 inline const ValueType & operator [](Index i) const { return mat_[i];}
54
55 #define DEFINE_UNARY_MOD_OPERATOR__(OP, NAME) \
56 inline Matrix3 < ValueType > & operator OP##= (const ValueType & val) { \
57 for (Index i = 0; i < 9; i += 3) {\
58 mat_[i] OP##= val; mat_[i+1] OP##= val; mat_[i+2] OP##= val; } return *this; \
59 }
60
61 DEFINE_UNARY_MOD_OPERATOR__(+, PLUS)
62 DEFINE_UNARY_MOD_OPERATOR__(-, MINUS)
63 DEFINE_UNARY_MOD_OPERATOR__(/, DIVID)
64 DEFINE_UNARY_MOD_OPERATOR__(*, MULT)
65
66 #undef DEFINE_UNARY_MOD_OPERATOR__
67
68 void clear(){
69 mat_[0] = 0.0; mat_[1] = 0.0; mat_[2] = 0.0;
70 mat_[3] = 0.0; mat_[4] = 0.0; mat_[5] = 0.0;
71 mat_[6] = 0.0; mat_[7] = 0.0; mat_[8] = 0.0;
72 }
73 inline Index rows() const { return 3; }
74 inline Index cols() const { return 3; }
75
76 inline const Vector < ValueType > col(Index i) const {
77 Vector < ValueType >ret(3);
78 ret[0] = mat_[i]; ret[1] = mat_[3 + i]; ret[2] = mat_[6 + i];
79 return ret;
80 }
81
82 inline const Vector < ValueType > row(Index i) const {
83 Vector < ValueType >ret(3);
84 ret[0] = mat_[i * 3]; ret[1] = mat_[i * 3 + 1]; ret[2] = mat_[i * 3 + 2];
85 return ret;
86 }
87
88 // inline void setVal(const RVector & v, Index i){
89 // __M
90 // log(Warning, "deprecated");
91 // mat_[i * 3] = v[0]; mat_[i * 3 + 1] = v[1]; mat_[i * 3 + 2] = v[2];
92 // }
93 inline void setVal(Index i, const RVector & v){
94 mat_[i * 3] = v[0]; mat_[i * 3 + 1] = v[1]; mat_[i * 3 + 2] = v[2];
95 }
96
97 inline void setValid(bool v){valid_ = v;}
98
99 inline bool valid() const {return valid_;}
100
101 inline ValueType det() const {
102 return mat_[0] * (mat_[4] * mat_[8] - mat_[5] * mat_[7]) -
103 mat_[1] * (mat_[3] * mat_[8] - mat_[5] * mat_[6]) +
104 mat_[2] * (mat_[3] * mat_[7] - mat_[4] * mat_[6]);
105 }
106
107protected:
108
109 bool valid_;
110};
111
112template < class ValueType >
113std::ostream & operator << (std::ostream & str, const Matrix3 < ValueType > & vec){
114 for (Index i = 0; i < 3; i ++)
115 str << vec[i] << " ";
116 str << std::endl;
117 for (Index i = 0; i < 3; i ++)
118 str << vec[3 + i] << " ";
119 str << std::endl;
120 for (Index i = 0; i < 3; i ++)
121 str << vec[6 + i] << " ";
122 str << std::endl;
123 return str;
124}
125
126template < class ValueType > \
127Pos operator * (const Matrix3 < ValueType > & A, const Pos & b) {
128 return Pos (A[0] * b[0] + A[1] * b[1] + A[2] * b[2],
129 A[3] * b[0] + A[4] * b[1] + A[5] * b[2],
130 A[6] * b[0] + A[7] * b[1] + A[8] * b[2]);
131}
132
134
137class DLLEXPORT MatrixBase{
138public:
139
141 MatrixBase(bool verbose=false) : verbose_(verbose) {}
142
144 virtual ~MatrixBase(){}
145
147 virtual uint rtti() const { return GIMLI_MATRIXBASE_RTTI; }
148
149 void setVerbose(bool verbose){ verbose_ = verbose; }
150
151 bool verbose() const { return verbose_; }
152
154 inline Index size() const { return this->rows(); }
155
157 virtual Index rows() const {
158 log(Warning, "no rows() implemented for: ", typeid(*this).name());
159 return 0;
160 }
161
163 virtual Index cols() const {
164 log(Warning, "no cols() implemented for: ", typeid(*this).name());
165 return 0;
166 }
167
169 virtual void resize(Index rows, Index cols){
170 log(Warning, "no resize(Index rows, Index cols) implemented for: ", typeid(*this).name());
171 }
172
174 virtual void clean() {
175 log(Warning, "no clean() implemented for: ", typeid(*this).name());
176 }
177
179 virtual void clear() {
180 log(Warning, "no clear() implemented for: ", typeid(*this).name());
181 }
182
184 virtual RVector dot(const RVector & a) const {
185 return mult(a);
186 }
187
189 virtual RVector mult(const RVector & a) const {
190 log(Warning, "no RVector mult(const RVector & a) implemented for: ", typeid(*this).name());
191 return RVector(rows());
192 }
193
195 virtual CVector mult(const CVector & a) const {
196 log(Warning, "no CVector mult(const CVector & a) implemented for: ", typeid(*this).name());
197 return CVector(rows());
198 }
199
200 virtual RVector mult(const RVector & b, Index startI, Index endI) const {
201 log(Warning, "no RVector mult(const RVector & b, Index startI, Index endI) implemented for: ", typeid(*this).name());
202 return RVector(rows());
203 }
204 virtual CVector mult(const CVector & b, Index startI, Index endI) const {
205 log(Warning, "no CVector mult(const CVector & b, Index startI, Index endI) implemented for: ", typeid(*this).name());
206 return CVector(rows());
207 }
208
210 virtual RVector transMult(const RVector & a) const {
211 log(Warning, "no RVector transMult(const RVector & a) implemented for: ", typeid(*this).name());
212 return RVector(cols());
213 }
214
216 virtual CVector transMult(const CVector & a) const {
217 log(Warning, "no CVector transMult(const CVector & a) implemented for: ", typeid(*this).name());
218 return CVector(cols());
219 }
220/*
221 virtual void setCol(Index col, const RVector & v) const {
222 THROW_TO_IMPL
223 }
224
225 virtual void setCol(Index col, const CVector & v) const {
226 THROW_TO_IMPL
227 }*/
228
231 //template< class ValueType > virtual const RVector col(Index r) const{
232// __M
233// ASSERT_RANGE(r, 0, cols())
234// RVector b(cols(), 0.0);
235// b[r] = 1.0;
236// return this->mult(b);
237// }
238
239// /*! Brute force row separation fallback .. should be overwriten if you
240// * need performance for your onw matrix type. */
241// template< class ValueType > const Vector < ValueType > row(Index r) const{
242// __M
243// ASSERT_RANGE(r, 0, rows())
244// Vector < ValueType > b(rows(), 0.0);
245// b[r] = 1.0;
246// return this->transMult(b);
247// }
248 // these template function above will not work until MatrixBase is a non template function
251// virtual const RVector col(Index r) const{
252// __M
253// ASSERT_RANGE(r, 0, cols())
254// RVector b(cols(), 0.0);
255// b[r] = 1.0;
256// return this->mult(b);
257// }
258//
259// /*! Brute force row separation fallback .. should be overwriten if you
260// * need performance for your onw matrix type. */
261// virtual const RVector row(Index r) const {
262// __M
263// ASSERT_RANGE(r, 0, rows())
264// RVector b(rows(), 0.0);
265// b[r] = 1.0;
266// return this->transMult(b);
267// }
268
269
271 virtual void save(const std::string & filename) const {
272 log(Warning, "no save(const std::string & filename) implemented for: ", typeid(*this).name());
273 }
274
275protected:
276 bool verbose_;
277};
278
280class DLLEXPORT IdentityMatrix : public MatrixBase {
281public:
284 : MatrixBase(), nrows_(0), val_(0.0){}
285
287 IdentityMatrix(Index nrows, double val=1.0)
288 : MatrixBase(), nrows_(nrows), val_(val){}
289
291 virtual ~IdentityMatrix(){}
292
294 virtual Index rows() const { return nrows_; }
295
297 virtual Index cols() const { return nrows_; }
298
300 virtual RVector mult(const RVector & a) const {
301 if (a.size() != nrows_) {
302 throwLengthError(WHERE_AM_I + " vector/matrix lengths do not match " +
303 str(nrows_) + " " + str(a.size()));
304 }
305 return a * val_;
306 }
307
309 virtual RVector transMult(const RVector & a) const {
310 if (a.size() != nrows_) {
311 throwLengthError(WHERE_AM_I + " matrix/vector lengths do not match " +
312 str(a.size()) + " " + str(nrows_));
313 }
314 return a * val_;
315 }
316
317protected:
318 Index nrows_;
319 double val_;
320};
321
323
324template < class ValueType > class DLLEXPORT Matrix : public MatrixBase {
325public:
328 : MatrixBase() {
329 resize(0, 0);
330 }
331 Matrix(Index rows)
332 : MatrixBase() {
333 resize(rows, 0);
334 }
335 // no default arg here .. pygimli@win64 linker bug
336 Matrix(Index rows, Index cols)
337 : MatrixBase() {
338 resize(rows, cols);
339 }
340 Matrix(Index rows, Index cols, ValueType *src)
341 : MatrixBase() {
342 fromData(src, rows, cols);
343 }
345
346 Matrix(const std::vector < Vector< ValueType > > & mat)
347 : MatrixBase(){ copy_(mat); }
348
350 Matrix(const std::string & filename)
351 : MatrixBase() { load(*this, filename); }
352
354 Matrix(const Matrix < ValueType > & mat)
355 : MatrixBase() { copy_(mat); }
356
358 Matrix < ValueType > & operator = (const Matrix< ValueType > & mat){
359 if (this != & mat){
360 copy_(mat);
361 } return *this;
362 }
363
365 virtual ~Matrix(){}
366
368 inline void copy(const Matrix < ValueType > & mat){ copy_(mat); }
369
371 virtual uint rtti() const { return GIMLI_MATRIX_RTTI; }
372
373 #define DEFINE_UNARY_MOD_OPERATOR__(OP, NAME) \
374 inline Matrix < ValueType > & operator OP##=(const Matrix < ValueType>&A){\
375 for (Index i = 0; i < mat_.size(); i ++) mat_[i] OP##= A[i]; return *this;}\
376 inline Matrix < ValueType > & operator OP##= (const ValueType & val) { \
377 for (Index i = 0; i < mat_.size(); i ++) mat_[i] OP##= val; return*this;}\
378
379 DEFINE_UNARY_MOD_OPERATOR__(+, PLUS)
380 DEFINE_UNARY_MOD_OPERATOR__(-, MINUS)
381 DEFINE_UNARY_MOD_OPERATOR__(/, DIVID)
382 DEFINE_UNARY_MOD_OPERATOR__(*, MULT)
383
384 #undef DEFINE_UNARY_MOD_OPERATOR__
385
386// Index col = cols();
387// for (Index i = 0; i < mat_.size(); i ++) {
388// ValueType * Aj = &mat_[i][0];
389// ValueType * Aje = &mat_[i][col];
390// for (; Aj != Aje;) *Aj++ OP##= val;
391// } return *this; }
392
394 Vector< ValueType > & operator [] (Index i) {
395 return rowRef(i);
396 }
397
399 const Vector< ValueType > & operator [] (Index i) const {
400 return row(i);
401 }
402
404 template < class T > operator Matrix< T >(){
405 Matrix< T > f(this->rows());
406 for (uint i = 0; i < this->rows(); i ++){ f[i] = Vector < T >(mat_[i]); }
407 return f;
408 }
409
411 virtual void resize(Index rows, Index cols){ allocate_(rows, cols); }
412
414 inline void clear() { mat_.clear(); }
415
417 inline void clean() {
418 for (Index i = 0; i < mat_.size(); i ++) mat_[i].clear();
419 }
420
422 inline Index rows() const {
423 return mat_.size();
424 }
425
427 inline Index cols() const {
428 if (mat_.size() > 0) return mat_[0].size();
429 return 0;
430 }
431
433 // inline void setRow(const Vector < ValueType > & val, Index i) {
434 // log(Warning, "deprecated use setRow(i, val)");
435 // ASSERT_THIS_SIZE(i)
436 // mat_[i] = val;
437 // }
438 inline void setRow(Index i, const Vector < ValueType > & val) {
439 ASSERT_THIS_SIZE(i)
440 mat_[i] = val;
441 }
442
444 // inline void setVal(const Vector < ValueType > & val, Index i) {
445 // log(Warning, "deprecated, use setVal(i, val)");
446 // return setRow(i, val);
447 // }
448 inline void setVal(Index i, const Vector < ValueType > & val) {
449 return this->setRow(i, val);
450 }
451 inline void setVal(Index i, Index j, const ValueType & val) {
452 this->rowRef(i).setVal(val, j);
453 }
454 inline void addVal(Index i, Index j, const ValueType & val) {
455 this->rowRef(i).addVal(val, j);
456 }
457
459 inline const Vector < ValueType > & row(Index i) const {
460 ASSERT_THIS_SIZE(i)
461 return mat_[i];
462 }
463
465 inline Vector < ValueType > & rowRef(Index i) {
466 ASSERT_THIS_SIZE(i)
467 return mat_[i];
468 }
469
471 virtual const Vector< ValueType > col(Index i) const {
472 //__M
473 if (i < 0 || i > this->cols()-1) {
474 throwLengthError(WHERE_AM_I + " col bounds out of range " +
475 str(i) + " " + str(this->cols())) ;
476 }
477 Vector < ValueType > col(this->rows());
478 for (Index j = 0, jmax = rows(); j < jmax; j ++) col[j] = mat_[j][i];
479 return col;
480 }
481
483 inline void push_back(const Vector < ValueType > & vec) {
484 //**!!! length check necessary
485 mat_.push_back(vec);
486 rowFlag_.resize(rowFlag_.size() + 1);
487 }
488
490 inline Vector< ValueType > & back() { return mat_.back(); }
491
493 inline void setCol(Index col, const Vector < ValueType > & v){
494 if (col < 0 || col > this->cols()-1) {
495 throwLengthError(WHERE_AM_I + " col bounds out of range " +
496 str(col) + " " + str(this->cols())) ;
497 }
498 if (v.size() > this->rows()) {
499 throwLengthError(WHERE_AM_I + " rows bounds out of range " +
500 str(v.size()) + " " + str(this->rows())) ;
501 }
502 for (Index i = 0; i < v.size(); i ++) mat_[i][col] = v[i];
503 }
504
506 inline void addCol(Index col, const Vector < ValueType > & v){
507 if (col < 0 || col > this->cols()-1) {
508 throwLengthError(WHERE_AM_I + " col bounds out of range " +
509 str(col) + " " + str(this->cols())) ;
510 }
511 if (v.size() > this->rows()) {
512 throwLengthError(WHERE_AM_I + " rows bounds out of range " +
513 str(v.size()) + " " + str(this->rows())) ;
514 }
515 for (Index i = 0; i < v.size(); i ++) mat_[i][col] += v[i];
516 }
517
519 BVector & rowFlag(){ return rowFlag_; }
520
522 inline Matrix < ValueType > & add(const Matrix < ValueType > & a){
523 return (*this)+=a;
524 }
525
527 Matrix < ValueType > & transAdd(const Matrix < ValueType > & a);
528
529
531 Vector < ValueType > mult(const Vector < ValueType > & b) const;
532 // {
533 // Index cols = this->cols();
534 // Index rows = this->rows();
535
536 // Vector < ValueType > ret(rows, 0.0);
537
538 // //ValueType tmpval = 0;
539 // if (b.size() == cols){
540 // for (Index i = 0; i < rows; ++i){
541 // ret[i] = sum(mat_[i] * b);
542 // }
543 // } else {
544 // throwLengthError(WHERE_AM_I + " " + str(cols) + " != " + str(b.size()));
545 // }
546 // return ret;
547 // }
548
550 Vector < ValueType > mult(const Vector < ValueType > & b, Index startI, Index endI) const;
551 // {
552 // Index cols = this->cols();
553 // Index rows = this->rows();
554 // Index bsize = Index(endI - startI);
555
556 // if (bsize != cols) {
557 // throwLengthError(WHERE_AM_I + " " + str(cols) + " < " + str(endI) + "-" + str(startI));
558 // }
559 // Vector < ValueType > ret(rows, 0.0);
560 // for (Index i = 0; i < rows; ++i){
561 // for (Index j = startI; j < endI; j++) {
562 // ret[i] += mat_[i][j] * b[j];
563 // }
564 // }
565 // return ret;
566 // }
567
569 Vector< ValueType > transMult(const Vector < ValueType > & b) const;
570 // {
571 // Index cols = this->cols();
572 // Index rows = this->rows();
573 // Vector < ValueType > ret(cols, 0.0);
574 // //ValueType tmpval = 0;
575
576 // if (b.size() == rows){
577 // for(Index i = 0; i < rows; i++){
578 // for(Index j = 0; j < cols; j++){
579 // ret[j] += mat_[i][j] * b[i];
580 // }
581 // }
582 // } else {
583 // throwLengthError(WHERE_AM_I + " " + str(rows) + " != " + str(b.size()));
584 // }
585 // return ret;
586 // }
587
589 virtual void save(const std::string & filename) const {
590 saveMatrix(*this, filename);
591 }
592
594 void round(const ValueType & tolerance){
595 for (Index i = 0; i < mat_.size(); i ++) mat_[i].round(tolerance);
596 // ??? std::for_each(mat_.begin, mat_.end, boost::bind(&Vector< ValueType >::round, tolerance));
597 }
598 std::vector < Vector< ValueType > > mat_;
599
600 void dumpData(ValueType * target) const{
601 //target.resize(this.rows(), this.cols());
602 for (Index i = 0; i < mat_.size(); i ++) {
603 std::memcpy(&target[i*this->cols()], &mat_[i][0], sizeof(ValueType) * this->cols());
604 }
605 }
606 void fromData(ValueType * src, Index m, Index n){
607 this->resize(m, n);
608 for (Index i = 0; i < m; i ++) {
609 std::memcpy(&mat_[i][0], &src[i*n], sizeof(ValueType) * n);
610 }
611 }
612protected:
613
614 void allocate_(Index rows, Index cols){
615// __MS(rows << " " << cols)
616 if (mat_.size() != rows) mat_.resize(rows);
617 for (Index i = 0; i < mat_.size(); i ++) {
618// __MS(this << " " << &mat_[i] << " "<< cols)
619 mat_[i].resize(cols);
620// __MS(&mat_[i] << " " <<mat_[i].size())
621 }
622 rowFlag_.resize(rows);
623 }
624
625 void copy_(const Matrix < ValueType > & mat){
626 allocate_(mat.rows(), mat.cols());
627 for (Index i = 0; i < mat_.size(); i ++) mat_[i] = mat[i];
628 }
629
630
632 BVector rowFlag_;
633};
634
635template <> DLLEXPORT Vector<double>
636Matrix<double>::mult(const Vector < double > & b, Index startI, Index endI) const;
637template <> DLLEXPORT Vector<Complex>
638Matrix<Complex>::mult(const Vector < Complex > & b, Index startI, Index endI) const;
639
640template <> DLLEXPORT Vector<double>
641Matrix<double>::mult(const Vector < double > & b) const;
642template <> DLLEXPORT Vector<Complex>
643Matrix<Complex>::mult(const Vector < Complex > & b) const;
644
645template <> DLLEXPORT Vector<double>
646Matrix<double>::transMult(const Vector < double > & b) const;
647template <> DLLEXPORT Vector<Complex>
648Matrix<Complex>::transMult(const Vector < Complex > & b) const;
649
650template <> DLLEXPORT Matrix<double> &
651Matrix<double>::transAdd(const Matrix < double > & a);
652template <> DLLEXPORT Matrix<Complex> &
653Matrix<Complex>::transAdd(const Matrix < Complex > & a);
654
655
656#define DEFINE_BINARY_OPERATOR__(OP, NAME) \
657template < class ValueType > \
658Matrix < ValueType > operator OP (const Matrix < ValueType > & A, const Matrix < ValueType > & B) { \
659Matrix < ValueType > tmp(A); \
660return tmp OP##= B; } \
661template < class ValueType > \
662Matrix < ValueType > operator OP (const Matrix < ValueType > & A, const ValueType & v) { \
663Matrix < ValueType > tmp(A); \
664return tmp OP##= v; }
665
666DEFINE_BINARY_OPERATOR__(+, PLUS)
667DEFINE_BINARY_OPERATOR__(-, MINUS)
668DEFINE_BINARY_OPERATOR__(/, DIVID)
669DEFINE_BINARY_OPERATOR__(*, MULT)
670
671#undef DEFINE_BINARY_OPERATOR__
672
673template< class ValueType > class DLLEXPORT Mult{
674public:
675 Mult(Vector< ValueType > & x, const Vector< ValueType > & b, const Matrix < ValueType > & A, Index start, Index end) :
676 x_(&x), b_(&b), A_(&A), start_(start), end_(end){
677 }
678 void operator()() {
679 for (Index i = start_; i < end_; i++) (*x_)[i] = sum((*A_)[i] * *b_);
680 }
681
683 const Vector< ValueType > * b_;
684 const Matrix< ValueType > * A_;
685 Index start_;
686 Index end_;
687};
688
689template < class ValueType >
690Vector < ValueType > multMT(const Matrix < ValueType > & A, const Vector < ValueType > & b){
691#ifdef USE_THREADS
692 Index cols = A.cols();
693 Index rows = A.rows();
694
695 Vector < ValueType > ret(rows);
696 boost::thread_group threads;
697 Index nThreads = 2;
698 Index singleCalcCount = Index(ceil((double)rows / (double)nThreads));
699 // CycleCounter cc;
700
701 for (Index i = 0; i < nThreads; i ++){
702// Vector < ValueType > *start = &A[singleCalcCount * i];
703// Vector < ValueType > *end = &A[singleCalcCount * (i + 1)];
704 Index start = singleCalcCount * i;
705 Index end = singleCalcCount * (i + 1);
706 if (i == nThreads -1) end = A.rows();
707// cc.tic();
708 threads.create_thread(Mult< ValueType >(ret, b, A, start, end));
709 // std::cout << cc.toc() << std::endl;
710 }
711 threads.join_all();
712#else
713 return mult(A, b);
714#endif
715}
716
717template < class ValueType >
718bool operator == (const Matrix< ValueType > & A, const Matrix< ValueType > & B){
719 if (A.rows() != B.rows() || A.cols() != B.cols()) return false;
720 for (Index i = 0; i < A.rows(); i ++){
721 if (A[i] != B[i]) return false;
722 }
723 return true;
724}
725
726template < class ValueType >
727void scaleMatrix(Matrix < ValueType >& A,
728 const Vector < ValueType > & l, const Vector < ValueType > & r){
729 Index rows = A.rows();
730 Index cols = A.cols();
731 if (rows != l.size()){
732 throwLengthError(WHERE_AM_I + " " + str(rows) + " != " + str(l.size()));
733 };
734 if (cols != r.size()){
735 throwLengthError(WHERE_AM_I + " " + str(cols) + " != " + str(r.size()));
736 }
737
738 for (Index i = 0 ; i < rows ; i++) {
739 //for (Index j = 0 ; j < cols ; j++) A[i][j] *= (l[i] * r[j]);
740 A[i] *= r * l[i];
741 }
742}
743
744template < class ValueType >
745void rank1Update(Matrix < ValueType > & A,
746 const Vector < ValueType > & u, const Vector < ValueType > & v) {
747 Index rows = A.rows();
748 Index cols = A.cols();
749 if (rows != u.size()){
750 throwLengthError(WHERE_AM_I + " " + str(rows) + " != " + str(u.size()));
751 };
752
753 if (cols != v.size()){
754 throwLengthError(WHERE_AM_I + " " + str(cols) + " != " + str(v.size()));
755 }
756
757 for (Index i = 0 ; i < rows ; i++) {
758 //for (Index j = 0 ; j < ncols ; j++) A[i][j] += (u[i] * v[j]);
759 A[i] += v * u[i];
760 }
761 return;
762}
763
764template < class ValueType >
765Matrix < ValueType > fliplr(const Matrix< ValueType > & m){
766 Matrix < ValueType > n;
767 for (Index i = 0; i < m.rows(); i ++) n.push_back(fliplr(m[i]));
768 return n;
769}
770
771template < class ValueType >
772Matrix < ValueType > real(const Matrix < std::complex< ValueType > > & cv){
773 Matrix < ValueType > v(cv.rows());
774 for (Index i = 0; i < cv.rows(); i ++) v[i] = real(cv[i]);
775 return v;
776}
777
778template < class ValueType >
779Matrix < ValueType > imag(const Matrix < std::complex< ValueType > > & cv){
780 Matrix < ValueType > v(cv.rows());
781 for (Index i = 0; i < cv.rows(); i ++) v[i] = imag(cv[i]);
782 return v;
783}
784
785//********************* MATRIX I/O *******************************
786
792template < class ValueType >
793bool saveMatrix(const Matrix < ValueType > & A, const std::string & filename, IOFormat format = Binary){
794 if (format == Ascii) return saveMatrixRow(A, filename);
795 std::string fname(filename);
796 if (fname.rfind('.') == std::string::npos) fname += MATRIXBINSUFFIX;
797
798 FILE *file; file = fopen(fname.c_str(), "w+b");
799
800 if (!file){
801 std::cerr << fname << ": " << strerror(errno) << " " << errno << std::endl;
802 return false;
803 }
804
805 uint32 rows = A.rows();
806 uint ret = fwrite(& rows, sizeof(uint32), 1, file);
807 if (ret == 0) {
808 fclose(file);
809 return false;
810 }
811 uint32 cols = A.cols();
812 ret = fwrite(& cols, sizeof(uint32), 1, file);
813
814 for (uint i = 0; i < rows; i ++){
815 for (uint j = 0; j < cols; j ++){
816 ret = fwrite(&A[i][j], sizeof(ValueType), 1, file);
817 }
818 }
819 fclose(file);
820 return true;
821}
822
827template < class ValueType >
828bool load(Matrix < ValueType > & A, const std::string & filename){
829
831 if (filename.rfind(".matrix") != std::string::npos ||
832 filename.rfind(".mat") != std::string::npos ||
833 filename.rfind(MATRIXBINSUFFIX) != std::string::npos) {
835 return loadMatrixSingleBin(A, filename);
836 }
837
839 if (fileExist(filename + ".matrix")) return loadMatrixSingleBin(A, filename + ".matrix");
840 if (fileExist(filename + ".mat")) return loadMatrixSingleBin(A, filename + ".mat");
841 if (fileExist(filename + MATRIXBINSUFFIX))
843 return loadMatrixSingleBin(A, filename + MATRIXBINSUFFIX);
844
846 return loadMatrixVectorsBin(A, filename);
847}
848
849
850DLLEXPORT bool loadMatrixSingleBin(RMatrix & A, const std::string & filename);
851DLLEXPORT bool loadMatrixSingleBin(CMatrix & A, const std::string & filename);
852
859DLLEXPORT bool loadMatrixVectorsBin(RMatrix & A, const std::string & filenameBody, uint kCount=1);
860DLLEXPORT bool loadMatrixVectorsBin(CMatrix & A, const std::string & filenameBody, uint kCount=1);
861
863template < class ValueType >
864bool saveMatrixCol(const Matrix < ValueType > & A, const std::string & filename){
865 return saveMatrixCol(A, filename, "");
866}
867
869template < class ValueType >
870bool saveMatrixCol(const Matrix < ValueType > & A, const std::string & filename,
871 const std::string & comments){
872 std::fstream file; openOutFile(filename, & file, true);
873 if (comments.length() > 0){
874 file << "#" << comments << std::endl;
875 }
876
877 for (uint i = 0; i < A.cols(); i ++){
878 for (uint j = 0; j < A.rows(); j ++){
879 file << A[j][i] << "\t";
880 }
881 file << std::endl;
882 }
883 file.close();
884 return true;
885}
886
888template < class ValueType >
889bool loadMatrixCol(Matrix < ValueType > & A, const std::string & filename){
890 std::vector < std::string > comments;
891 return loadMatrixCol(A, filename, comments);
892}
893
895template < class ValueType >
896bool loadMatrixCol(Matrix < ValueType > & A, const std::string & filename,
897 std::vector < std::string > & comments){
898
899 uint commentCount = 0;
900 uint cols = countColumnsInFile(filename, commentCount);
901// Index rows = countRowsInFile(filename);
902// // get length of file:
903// std::fstream file; openInFile(filename, & file, true);
904// Index length = fileLength(file);
905//
906// // allocate memory:
907// char * buffer = new char[length];
908// file.read(buffer, length);
909// file.close();
910//
911// delete buffer;
912// return true;
913
914 Vector < ValueType > tmp;
915 Vector < ValueType > row(cols);
916 std::fstream file; openInFile(filename, & file, true);
917 for (uint i = 0; i < commentCount; i ++) {
918 std::string str;
919 getline(file, str);
920 comments = getSubstrings(str.substr(str.find('#'), -1));
921 }
922
923 double val;
924 while(file >> val) tmp.push_back(val);
925
926 file.close();
927 Index rows = tmp.size() / cols ;
928 A.resize(cols, rows);
929
930 for (uint i = 0; i < rows; i ++){
931 for (uint j = 0; j < cols; j ++){
932 A[j][i] = tmp[i * cols + j];
933 }
934 }
935 return true;
936}
937
939template < class ValueType >
940bool saveMatrixRow(const Matrix < ValueType > & A, const std::string & filename){
941 return saveMatrixRow(A, filename, "");
942}
943
945template < class ValueType >
946bool saveMatrixRow(const Matrix < ValueType > & A, const std::string & filename,
947 const std::string & comments){
948 std::fstream file; openOutFile(filename, & file, true);
949 if (comments.length() > 0){
950 file << "#" << comments << std::endl;
951 }
952
953 for (uint i = 0; i < A.rows(); i ++){
954 for (uint j = 0; j < A.cols(); j ++){
955 file << A[i][j] << "\t";
956 }
957 file << std::endl;
958 }
959 file.close();
960 return true;
961}
962
964template < class ValueType >
965bool loadMatrixRow(Matrix < ValueType > & A, const std::string & filename){
966
967 std::vector < std::string > comments;
968 return loadMatrixRow(A, filename, comments);
969}
970
972template < class ValueType >
973bool loadMatrixRow(Matrix < ValueType > & A,
974 const std::string & filename,
975 std::vector < std::string > & comments){
976
977 uint commentCount = 0;
978 uint cols = countColumnsInFile(filename, commentCount);
979
980 Vector < ValueType > row(cols);
981 std::fstream file; openInFile(filename, & file, true);
982 for (uint i = 0; i < commentCount; i ++) {
983 std::string str;
984 getline(file, str);
985 comments = getSubstrings(str.substr(str.find('#'), -1));
986 }
987
988 double val;
989 Vector < ValueType > tmp;
990 while(file >> val) tmp.push_back(val);
991
992 file.close();
993 Index rows = tmp.size() / cols ;
994 A.resize(rows, cols);
995
996 for (uint i = 0; i < rows; i ++){
997 for (uint j = 0; j < cols; j ++){
998 A[i][j] = tmp[i * cols + j];
999 }
1000 }
1001 return true;
1002}
1003
1007DLLEXPORT void matMultABA(const RMatrix & A, const RMatrix & B, RMatrix & C, RMatrix & AtB, double a=1.0, double b=0.0);
1008
1010DLLEXPORT void matMult(const RMatrix & A, const RMatrix & B, RMatrix & C, double a=1.0, double b=0.0);
1011
1013DLLEXPORT void matTransMult(const RMatrix & A, const RMatrix & B, RMatrix & C, double a=1.0, double b=0.0);
1014
1016template < class T > inline T det(const T & a, const T & b, const T & c, const T & d){
1017 return a * d - b * c;
1018}
1019
1021template < class ValueType > double det(const Matrix3< ValueType > & A){
1022 return A.det();
1023}
1024
1026template < class Matrix > double det(const Matrix & A){
1027 //** das geht viel schoener, aber nicht mehr heute.;
1028 double det = 0.0;
1029 switch (A.rows()){
1030 case 2: det = A[0][0] * A[1][1] - A[0][1] * A[1][0];
1031 break;
1032 case 3:
1033 det = A[0][0] * (A[1][1] * A[2][2] - A[1][2] * A[2][1]) -
1034 A[0][1] * (A[1][0] * A[2][2] - A[1][2] * A[2][0]) +
1035 A[0][2] * (A[1][0] * A[2][1] - A[1][1] * A[2][0]);
1036
1037 // .T
1038 // det = A[0][0] * (A[1][1] * A[2][2] - A[2][1] * A[1][2])-
1039 // A[1][0] * (A[0][1] * A[2][2] - A[2][1] * A[0][2])+
1040 // A[2][0] * (A[0][1] * A[1][2] - A[1][1] * A[0][2]);
1041
1042 break;
1043 default:
1044 std::cerr << WHERE_AM_I << " matrix determinant of dim not yet implemented -- dim: " << A.rows() << std::endl;
1045 break;
1046 }
1047 return det;
1048}
1049
1051template < class ValueType > inline Matrix3<ValueType> inv(const Matrix3< ValueType > & A){
1053 inv(A, I);
1054 return I;
1055}
1056
1058template < class ValueType > inline void inv(const Matrix3< ValueType > & A,
1060// __M
1061// std::cout << A << std::endl;
1062 I[0] = (A[4] * A[8] - A[5] * A[7]);
1063 I[3] = -(A[3] * A[8] - A[5] * A[6]);
1064 I[6] = (A[3] * A[7] - A[4] * A[6]);
1065 I[1] = -(A[1] * A[8] - A[2] * A[7]);
1066 I[4] = (A[0] * A[8] - A[2] * A[6]);
1067 I[7] = -(A[0] * A[7] - A[1] * A[6]);
1068 I[2] = (A[1] * A[5] - A[2] * A[4]);
1069 I[5] = -(A[0] * A[5] - A[2] * A[3]);
1070 I[8] = (A[0] * A[4] - A[1] * A[3]);
1071// std::cout << I << std::endl;
1072// std::cout << (A[0] * I[0] + A[1] * I[3] + A[2] * I[6]) << std::endl;
1073// std::cout << det(A) << std::endl;
1074 I /= (A[0] * I[0] + A[1] * I[3] + A[2] * I[6]);
1075}
1076
1078template < class Matrix > Matrix inv(const Matrix & A){
1079 //** das geht viel schoener, aber nicht mehr heute.; Wie?
1080 Matrix I(A.rows(), A.cols());
1081 inv(A, I);
1082 return I;
1083}
1084
1086template < class Matrix > void inv(const Matrix & A, Matrix & I){
1087 //** das geht viel schoener, aber nicht mehr heute.; Wie?
1088
1089 switch (I.rows()){
1090 case 2:
1091 I[0][0] = A[1][1];
1092 I[1][0] = -A[1][0];
1093 I[0][1] = -A[0][1];
1094 I[1][1] = A[0][0];
1095 break;
1096 case 3:
1097 I[0][0] = (A[1][1] * A[2][2] - A[1][2] * A[2][1]);
1098 I[1][0] = -(A[1][0] * A[2][2] - A[1][2] * A[2][0]);
1099 I[2][0] = (A[1][0] * A[2][1] - A[1][1] * A[2][0]);
1100 I[0][1] = -(A[0][1] * A[2][2] - A[0][2] * A[2][1]);
1101 I[1][1] = (A[0][0] * A[2][2] - A[0][2] * A[2][0]);
1102 I[2][1] = -(A[0][0] * A[2][1] - A[0][1] * A[2][0]);
1103 I[0][2] = (A[0][1] * A[1][2] - A[0][2] * A[1][1]);
1104 I[1][2] = -(A[0][0] * A[1][2] - A[0][2] * A[1][0]);
1105 I[2][2] = (A[0][0] * A[1][1] - A[0][1] * A[1][0]);
1106 break;
1107 default:
1108 std::cerr << WHERE_AM_I << " matrix determinant of dim not yet implemented -- dim: " << A.rows() << std::endl;
1109 break;
1110 }
1111 I /= det(A);
1112}
1113
1114inline void save(const MatrixBase & A, const std::string & filename){
1115 A.save(filename);
1116}
1117
1118inline void save(MatrixBase & A, const std::string & filename){
1119 A.save(filename);
1120}
1121
1122inline RVector operator * (const MatrixBase & A, const RVector & b){
1123 return A.mult(b);
1124}
1125
1126inline RVector transMult(const MatrixBase & A, const RVector & b){
1127 return A.transMult(b);
1128}
1129
1130inline RVector operator * (const RMatrix & A, const RVector & b){
1131 return A.mult(b);
1132}
1133inline CVector operator * (const CMatrix & A, const CVector & b){
1134 return A.mult(b);
1135}
1136inline RVector transMult(const RMatrix & A, const RVector & b){
1137 return A.transMult(b);
1138}
1139inline CVector transMult(const CMatrix & A, const CVector & b){
1140 return A.transMult(b);
1141}
1142
1143inline RMatrix real(const CMatrix & A){
1144 RMatrix R(A.rows(), A.cols());
1145 for (Index i = 0; i < A.rows(); i ++) R[i] = real(A[i]);
1146 return R;
1147}
1148inline RMatrix imag(const CMatrix & A){
1149 RMatrix R(A.rows(), A.cols());
1150 for (Index i = 0; i < A.rows(); i ++) R[i] = imag(A[i]);
1151 return R;
1152}
1153
1154template < class T >
1155std::ostream & operator << (std::ostream & str, const Matrix < T > & M){
1156 for (Index i = 0; i < M.rows(); i ++) {
1157 str << M[i] << std::endl;
1158 }
1159 return str;
1160}
1161
1162} //namespace GIMLI
1163
1164#endif // _GIMLI_MATRIX__H
1165
virtual Index cols() const
Definition matrix.h:297
virtual RVector transMult(const RVector &a) const
Definition matrix.h:309
virtual RVector mult(const RVector &a) const
Definition matrix.h:300
IdentityMatrix()
Definition matrix.h:283
virtual Index rows() const
Definition matrix.h:294
virtual ~IdentityMatrix()
Definition matrix.h:291
IdentityMatrix(Index nrows, double val=1.0)
Definition matrix.h:287
Definition matrix.h:39
Interface class for matrices.
Definition matrix.h:137
virtual CVector mult(const CVector &a) const
Definition matrix.h:195
virtual RVector dot(const RVector &a) const
Definition matrix.h:184
virtual ~MatrixBase()
Definition matrix.h:144
virtual uint rtti() const
Definition matrix.h:147
Index size() const
Definition matrix.h:154
virtual void resize(Index rows, Index cols)
Definition matrix.h:169
virtual void clean()
Definition matrix.h:174
virtual RVector mult(const RVector &a) const
Definition matrix.h:189
virtual void clear()
Definition matrix.h:179
virtual RVector transMult(const RVector &a) const
Definition matrix.h:210
virtual CVector transMult(const CVector &a) const
Definition matrix.h:216
virtual void save(const std::string &filename) const
Definition matrix.h:271
MatrixBase(bool verbose=false)
Definition matrix.h:141
virtual Index cols() const
Definition matrix.h:163
virtual Index rows() const
Definition matrix.h:157
Simple row-based dense matrix based on Vector.
Definition matrix.h:324
virtual uint rtti() const
Definition matrix.h:371
Vector< ValueType > mult(const Vector< ValueType > &b, Index startI, Index endI) const
Vector< ValueType > & back()
Definition matrix.h:490
void addCol(Index col, const Vector< ValueType > &v)
Definition matrix.h:506
Vector< ValueType > mult(const Vector< ValueType > &b) const
Vector< double > & rowRef(Index i)
Definition matrix.h:465
BVector rowFlag_
Definition matrix.h:632
Matrix< ValueType > & add(const Matrix< ValueType > &a)
Definition matrix.h:522
virtual ~Matrix()
Definition matrix.h:365
void setVal(Index i, const Vector< ValueType > &val)
Definition matrix.h:448
Matrix()
Definition matrix.h:327
Vector< ValueType > transMult(const Vector< ValueType > &b) const
virtual void save(const std::string &filename) const
Definition matrix.h:589
BVector & rowFlag()
Definition matrix.h:519
void copy(const Matrix< ValueType > &mat)
Definition matrix.h:368
void setCol(Index col, const Vector< ValueType > &v)
Definition matrix.h:493
void clear()
Definition matrix.h:414
Index rows() const
Definition matrix.h:422
Index cols() const
Definition matrix.h:427
void setRow(Index i, const Vector< ValueType > &val)
Definition matrix.h:438
Matrix(const std::vector< Vector< ValueType > > &mat)
Definition matrix.h:346
void push_back(const Vector< ValueType > &vec)
Definition matrix.h:483
const Vector< double > & row(Index i) const
Definition matrix.h:459
virtual void resize(Index rows, Index cols)
Definition matrix.h:411
virtual const Vector< ValueType > col(Index i) const
Definition matrix.h:471
Matrix(const Matrix< ValueType > &mat)
Definition matrix.h:354
void clean()
Definition matrix.h:417
void round(const ValueType &tolerance)
Definition matrix.h:594
Matrix< ValueType > & transAdd(const Matrix< ValueType > &a)
Matrix(const std::string &filename)
Definition matrix.h:350
Definition matrix.h:673
One dimensional array aka Vector of limited size.
Definition vector.h:186
GIMLi main namespace for the Geophyiscal Inversion and Modelling Library.
Definition baseentity.h:24
bool saveMatrixRow(const Matrix< ValueType > &A, const std::string &filename)
Definition matrix.h:940
Matrix3< ValueType > inv(const Matrix3< ValueType > &A)
Definition matrix.h:1051
T det(const T &a, const T &b, const T &c, const T &d)
Definition matrix.h:1016
bool saveMatrix(const Matrix< ValueType > &A, const std::string &filename, IOFormat format=Binary)
Definition matrix.h:793
RVector x(const R3Vector &rv)
Definition pos.cpp:107
void matTransMult(const RMatrix &A, const RMatrix &B, RMatrix &C, double a, double b)
Definition matrix.cpp:201
void matMultABA(const RMatrix &A, const RMatrix &B, RMatrix &C, RMatrix &AtB, double a, double b)
Definition matrix.cpp:140
void matMult(const RMatrix &A, const RMatrix &B, RMatrix &C, double a, double b)
Definition matrix.cpp:154
bool loadMatrixCol(Matrix< ValueType > &A, const std::string &filename)
Definition matrix.h:889
bool saveMatrixCol(const Matrix< ValueType > &A, const std::string &filename)
Definition matrix.h:864
bool loadMatrixRow(Matrix< ValueType > &A, const std::string &filename)
Definition matrix.h:965
IOFormat
Definition gimli.h:289
bool loadMatrixVectorsBin(RMatrix &A, const std::string &filenameBody, uint kCount)
Definition matrix.cpp:377
bool load(Matrix< ValueType > &A, const std::string &filename)
Definition matrix.h:828