IFEM 90A354
matrixnd.h
Go to the documentation of this file.
1// $Id$
2//==============================================================================
12//==============================================================================
13
14#ifndef UTL_MATRIX_ND_H
15#define UTL_MATRIX_ND_H
16
17#include "matrix.h"
18
19
20namespace utl
21{
29 template<class T> class matrix3d : public matrixBase<T>
30 {
31 public:
35 explicit matrix3d(vector<T>& vec) : matrixBase<T>(vec) {}
38 matrix3d(size_t n_1, size_t n_2, size_t n_3) : matrixBase<T>(n_1,n_2,n_3) {}
40 matrix3d(const matrix3d<T>& mat) : matrixBase<T>(mat) {}
42 explicit matrix3d(std::istream& is, std::streamsize max = 10)
43 {
44 // Read size
45 size_t n0 = 0, n1 = 0, n2 = 0;
46 is.ignore(10, ':');
47 is.ignore(1);
48 is >> n0 >> n1 >> n2;
49 is.ignore(1, '\n');
50
51 // Read contents
52 this->resize(n0,n1,n2,1);
53 for (size_t k = 0; k < n2; k++) {
54 is.ignore(max, '\n');
55 for (size_t i = 0; i < n0; i++) {
56 is.ignore(max, ':');
57 for (size_t j = 0; j < n1; j++)
58 is >> this->elem[n0*(n1*k + j) + i];
59 is.ignore(1, '\n');
60 }
61 }
62 }
63
65 virtual ~matrix3d() {}
66
74 void resize(size_t n_1, size_t n_2, size_t n_3, bool forceClear = false)
75 {
76 this->redim(n_1,n_2,n_3,1,forceClear);
77 }
78
81 {
82 if (&A == this)
83 return *this;
84
85 memcpy(this->n,A.n,sizeof(A.n));
86 this->elem = A.elem;
87 return *this;
88 }
89
92 T& operator()(size_t i1, size_t i2, size_t i3)
93 {
94 CHECK_INDEX("matrix3d::operator(): First index " ,i1,this->n[0]);
95 CHECK_INDEX("matrix3d::operator(): Second index ",i2,this->n[1]);
96 CHECK_INDEX("matrix3d::operator(): Third index " ,i3,this->n[2]);
97 return this->elem[i1-1 + this->n[0]*((i2-1) + this->n[1]*(i3-1))];
98 }
99
102 const T& operator()(size_t i1, size_t i2, size_t i3) const
103 {
104 CHECK_INDEX("matrix3d::operator(): First index " ,i1,this->n[0]);
105 CHECK_INDEX("matrix3d::operator(): Second index ",i2,this->n[1]);
106 CHECK_INDEX("matrix3d::operator(): Third index " ,i3,this->n[2]);
107 return this->elem[i1-1 + this->n[0]*((i2-1) + this->n[1]*(i3-1))];
108 }
109
111 vector<T> getColumn(size_t i2, size_t i3) const
112 {
113 CHECK_INDEX("matrix3d::getColumn: Second index ",i2,this->n[1]);
114 CHECK_INDEX("matrix3d::getColumn: Third index " ,i3,this->n[2]);
115 if (this->n[1] < 2 && this->n[2] < 2) return this->elem;
116 vector<T> col(this->n[0]);
117 memcpy(col.ptr(),this->ptr(i2-1+this->n[1]*(i3-1)),col.size()*sizeof(T));
118 return col;
119 }
120
122 void fillColumn(size_t i2, size_t i3, const std::vector<T>& data)
123 {
124 CHECK_INDEX("matrix3d::fillColumn: Second index ",i2,this->n[1]);
125 CHECK_INDEX("matrix3d::fillColumn: Third index " ,i3,this->n[2]);
126 size_t ndata = this->n[0] > data.size() ? data.size() : this->n[0];
127 memcpy(this->ptr(i2-1+this->n[1]*(i3-1)),data.data(),ndata*sizeof(T));
128 }
129
131 T trace(size_t i1) const
132 {
133 CHECK_INDEX("matrix3d::trace(): Index ",i1,this->n[0]);
134 return this->elem.sum(i1-1,this->n[0]*(this->n[1]+1));
135 }
136
138 matrix3d<T>& operator+=(const matrix3d<T>& X) { return this->add(X); }
140 matrix3d<T>& operator-=(const matrix3d<T>& X) { return this->add(X,T(-1)); }
142 matrix3d<T>& add(const matrix3d<T>& X, T alfa = T(1))
143 {
144 return static_cast<matrix3d<T>&>(this->matrixBase<T>::add(X,alfa));
145 }
146
149 {
150 return static_cast<matrix3d<T>&>(this->matrixBase<T>::multiply(c));
151 }
152
160 bool multiply(const matrix<T>& A, const matrix3d<T>& B,
161 bool transA = false, bool addTo = false);
162
173 bool multiplyMat(const std::vector<T>& A, const matrix3d<T>& B,
174 bool addTo = false);
175
176 private:
178 bool compatible(const matrix<T>& A, const matrix3d<T>& B,
179 bool transA, size_t& M, size_t& N, size_t& K)
180 {
181 M = transA ? A.cols() : A.rows();
182 N = B.n[1]*B.n[2];
183 K = transA ? A.rows() : A.cols();
184 if (K == B.n[0]) return true;
185
186 std::cerr <<"matrix3d::multiply: Incompatible matrices: A("
187 << A.rows() <<','<< A.cols() <<"), B("
188 << B.n[0] <<','<< B.n[1] <<','<< B.n[2] <<")\n"
189 <<" when computing C = "
190 << (transA ? "A^t":"A") <<" * B"<< std::endl;
191 ABORT_ON_INDEX_CHECK;
192 return false;
193 }
194
197 bool compatible(const std::vector<T>& A, const matrix3d<T>& B,
198 size_t& M, size_t& N, size_t& K)
199 {
200 N = B.n[1]*B.n[2];
201 K = B.n[0];
202 M = K > 0 ? A.size() / K : 0;
203 if (M*K == A.size() && !A.empty()) return true;
204
205 std::cerr <<"matrix3d::multiply: Incompatible matrices: A(r*c="<< A.size()
206 <<"), B("<< B.n[0] <<","<< B.n[1] <<","<< B.n[2] <<")\n"
207 <<" when computing C = A * B"<< std::endl;
208 ABORT_ON_INDEX_CHECK;
209 return false;
210 }
211
212 protected:
214 virtual void clearIfNrowChanged(size_t n1, size_t n2, size_t)
215 {
216 if (n1 != this->n[0] || n2 != this->n[1]) this->elem.clear();
217 }
218 };
219
220
225 template<class T> class matrix4d : public matrixBase<T>
226 {
227 public:
231 explicit matrix4d(vector<T>& vec) : matrixBase<T>(vec) {}
234 matrix4d(size_t n_1, size_t n_2, size_t n_3, size_t n_4)
235 : matrixBase<T>(n_1,n_2,n_3,n_4) {}
237 matrix4d(const matrix4d<T>& mat) : matrixBase<T>(mat) {}
238
240 virtual ~matrix4d() {}
241
250 void resize(size_t n_1, size_t n_2, size_t n_3, size_t n_4,
251 bool forceClear = false)
252 {
253 this->redim(n_1,n_2,n_3,n_4,forceClear);
254 }
255
258 {
259 if (&A == this)
260 return *this;
261
262 memcpy(this->n,A.n,sizeof(A.n));
263 this->elem = A.elem;
264 return *this;
265 }
266
269 T& operator()(size_t i1, size_t i2, size_t i3, size_t i4)
270 {
271 CHECK_INDEX("matrix4d::operator(): First index " ,i1,this->n[0]);
272 CHECK_INDEX("matrix4d::operator(): Second index ",i2,this->n[1]);
273 CHECK_INDEX("matrix4d::operator(): Third index " ,i3,this->n[2]);
274 CHECK_INDEX("matrix4d::operator(): Fourth index ",i4,this->n[3]);
275 return this->elem[i1-1 + this->n[0]*((i2-1) + this->n[1]*((i3-1) + this->n[2]*(i4-1)))];
276 }
277
280 const T& operator()(size_t i1, size_t i2, size_t i3, size_t i4) const
281 {
282 CHECK_INDEX("matrix4d::operator(): First index " ,i1,this->n[0]);
283 CHECK_INDEX("matrix4d::operator(): Second index ",i2,this->n[1]);
284 CHECK_INDEX("matrix4d::operator(): Third index " ,i3,this->n[2]);
285 CHECK_INDEX("matrix4d::operator(): Fourth index ",i4,this->n[3]);
286 return this->elem[i1-1 + this->n[0]*((i2-1) + this->n[1]*((i3-1) + this->n[2]*(i4-1)))];
287 }
288
290 matrix4d<T>& operator+=(const matrix4d<T>& X) { return this->add(X); }
292 matrix4d<T>& operator-=(const matrix4d<T>& X) { return this->add(X,T(-1)); }
294 matrix4d<T>& add(const matrix4d<T>& X, T alfa = T(1))
295 {
296 return static_cast<matrix4d<T>&>(this->matrixBase<T>::add(X,alfa));
297 }
298
301 {
302 return static_cast<matrix4d<T>&>(this->matrixBase<T>::multiply(c));
303 }
304
306 vector<T> getColumn(size_t i2, size_t i3, size_t i4) const
307 {
308 CHECK_INDEX("matrix4d::getColumn: Second index ",i2,this->n[1]);
309 CHECK_INDEX("matrix4d::getColumn: Third index " ,i3,this->n[2]);
310 CHECK_INDEX("matrix4d::getColumn: Fourth index ",i4,this->n[3]);
311 if (this->n[1] < 2 && this->n[2] < 2 && this->n[3] < 2) return this->elem;
312 vector<T> col(this->n[0]);
313 memcpy(col.ptr(),
314 this->ptr(i2-1 + this->n[1]*((i3-1) + this->n[2]*(i4-1))),
315 col.size()*sizeof(T));
316 return col;
317 }
318
320 void fillColumn(size_t i2, size_t i3, size_t i4, const std::vector<T>& data)
321 {
322 CHECK_INDEX("matrix4d::fillColumn: Second index ",i2,this->n[1]);
323 CHECK_INDEX("matrix4d::fillColumn: Third index " ,i3,this->n[2]);
324 CHECK_INDEX("matrix4d::fillColumn: Fourth index ",i4,this->n[3]);
325 size_t ndata = this->n[0] > data.size() ? data.size() : this->n[0];
326 memcpy(this->ptr(i2-1 + this->n[1]*((i3-1)) + this->n[2]*(i4-1)),
327 data.data(),ndata*sizeof(T));
328 }
329
330 protected:
332 virtual void clearIfNrowChanged(size_t n1, size_t n2, size_t n3)
333 {
334 if (n1 != this->n[0] || n2 != this->n[1] || n3 != this->n[2])
335 this->elem.clear();
336 }
337 };
338
339
340#ifdef HAS_BLAS
341 //============================================================================
342 //=== BLAS-implementation of the matrix/vector multiplication methods ====
343 //============================================================================
344
345 template<> inline
346 bool matrix3d<float>::multiply(const matrix<float>& A,
347 const matrix3d<float>& B,
348 bool transA, bool addTo)
349 {
350 size_t M, N, K;
351 if (!this->compatible(A,B,transA,M,N,K)) return false;
352 if (!addTo) this->resize(M,B.n[1],B.n[2]);
353
354 cblas_sgemm(CblasColMajor,
355 transA ? CblasTrans : CblasNoTrans, CblasNoTrans,
356 M, N, K, 1.0f,
357 A.ptr(), A.rows(),
358 B.ptr(), B.n[0],
359 addTo ? 1.0f : 0.0f,
360 this->ptr(), n[0]);
361
362 return true;
363 }
364
365 template<> inline
366 bool matrix3d<double>::multiply(const matrix<double>& A,
367 const matrix3d<double>& B,
368 bool transA, bool addTo)
369 {
370 size_t M, N, K;
371 if (!this->compatible(A,B,transA,M,N,K)) return false;
372 if (!addTo) this->resize(M,B.n[1],B.n[2]);
373
374 cblas_dgemm(CblasColMajor,
375 transA ? CblasTrans : CblasNoTrans, CblasNoTrans,
376 M, N, K, 1.0,
377 A.ptr(), A.rows(),
378 B.ptr(), B.n[0],
379 addTo ? 1.0 : 0.0,
380 this->ptr(), n[0]);
381
382 return true;
383 }
384
385 template<> inline
386 bool matrix3d<float>::multiplyMat(const std::vector<float>& A,
387 const matrix3d<float>& B, bool addTo)
388 {
389 size_t M, N, K;
390 if (!this->compatible(A,B,M,N,K)) return false;
391 if (!addTo) this->resize(M,B.n[1],B.n[2]);
392
393 cblas_sgemm(CblasColMajor, CblasNoTrans, CblasNoTrans,
394 M, N, K, 1.0f,
395 A.data(), M,
396 B.ptr(), B.n[0],
397 addTo ? 1.0f : 0.0f,
398 this->ptr(), n[0]);
399
400 return true;
401 }
402
403 template<> inline
404 bool matrix3d<double>::multiplyMat(const std::vector<double>& A,
405 const matrix3d<double>& B, bool addTo)
406 {
407 size_t M, N, K;
408 if (!this->compatible(A,B,M,N,K)) return false;
409 if (!addTo) this->resize(M,B.n[1],B.n[2]);
410
411 cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans,
412 M, N, K, 1.0,
413 A.data(), M,
414 B.ptr(), B.n[0],
415 addTo ? 1.0 : 0.0,
416 this->ptr(), n[0]);
417
418 return true;
419 }
420
421#else
422 //============================================================================
423 //=== Non-BLAS inlined implementations (slow...) =========================
424 //============================================================================
425
426 template<class T> inline
428 bool transA, bool addTo)
429 {
430 size_t M, N, K;
431 if (!this->compatible(A,B,transA,M,N,K)) return false;
432 if (!addTo) this->resize(M,B.n[1],B.n[2],true);
433
434 for (size_t i = 1; i <= this->n[0]; i++)
435 for (size_t j = 1; j <= this->n[1]; j++)
436 for (size_t k = 1; k <= K; k++)
437 for (size_t l = 1; l <= this->n[2]; l++)
438 if (transA)
439 this->operator()(i,j,l) += A(k,i)*B(k,j,l);
440 else
441 this->operator()(i,j,l) += A(i,k)*B(k,j,l);
442
443 return true;
444 }
445
446 template<class T> inline
447 bool matrix3d<T>::multiplyMat(const std::vector<T>& A, const matrix3d<T>& B,
448 bool addTo)
449 {
450 size_t M, N, K;
451 if (!this->compatible(A,B,M,N,K)) return false;
452 if (!addTo) this->resize(M,B.n[1],B.n[2],true);
453
454 for (size_t i = 1; i <= this->n[0]; i++)
455 for (size_t j = 1; j <= this->n[1]; j++)
456 for (size_t k = 1; k <= K; k++)
457 for (size_t l = 1; l <= this->n[2]; l++)
458 this->operator()(i,j,l) += A[i-1+M*(k-1)]*B(k,j,l);
459
460 return true;
461 }
462#endif
463
467 template<class T> std::ostream& operator<<(std::ostream& s,
468 const matrix3d<T>& A)
469 {
470 if (A.empty())
471 return s <<" (empty)"<< std::endl;
472
473 s <<" Dimension: "<< A.dim(1) <<" "<< A.dim(2) <<" "<< A.dim(3);
474 matrix<T> B(A.dim(1),A.dim(2));
475 const T* Aptr = A.ptr();
476 for (size_t k = 0; k < A.dim(3); k++, Aptr += B.size())
477 {
478 B.fill(Aptr);
479 if (k == 0) s <<"\n";
480 s <<"i3="<< k+1 <<":"<< B;
481 }
482
483 return s;
484 }
485
489 template<class T> std::ostream& operator<<(std::ostream& s,
490 const matrix4d<T>& A)
491 {
492 if (A.empty())
493 return s <<" (empty)"<< std::endl;
494
495 s <<" Dimension: "<< A.dim(1) <<" "<< A.dim(2)
496 <<" "<< A.dim(3) <<" "<< A.dim(4);
497 matrix<T> B(A.dim(1),A.dim(2));
498 const T* Aptr = A.ptr();
499 for (size_t k = 0; k < A.dim(3); k++)
500 for (size_t l = 0; l < A.dim(4); l++, Aptr += B.size())
501 {
502 B.fill(Aptr);
503 if (k == 0 && l == 0) s <<"\n";
504 s <<"i3="<< k+1 <<", i4="<< l+1 <<":"<< B;
505 }
506
507 return s;
508 }
509}
510
511#endif
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
Three-dimensional rectangular matrix with some algebraic operations.
Definition matrixnd.h:30
matrix3d(size_t n_1, size_t n_2, size_t n_3)
Constructor creating a matrix of dimension .
Definition matrixnd.h:38
matrix3d(vector< T > &vec)
Constructor using an external vector for matrix element storage.
Definition matrixnd.h:35
bool compatible(const std::vector< T > &A, const matrix3d< T > &B, 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 matrixnd.h:197
vector< T > getColumn(size_t i2, size_t i3) const
Extract a column from the matrix.
Definition matrixnd.h:111
void resize(size_t n_1, size_t n_2, size_t n_3, bool forceClear=false)
Resize the matrix to dimension .
Definition matrixnd.h:74
matrix3d< T > & multiply(T c)
Multiplication of this matrix by a scalar c.
Definition matrixnd.h:148
T trace(size_t i1) const
Return the trace of the i1'th sub-matrix.
Definition matrixnd.h:131
virtual void clearIfNrowChanged(size_t n1, size_t n2, size_t)
Clears the content if any of the first two dimensions changed.
Definition matrixnd.h:214
matrix3d< T > & operator-=(const matrix3d< T > &X)
Subtract the given matrix X from *this.
Definition matrixnd.h:140
void fillColumn(size_t i2, size_t i3, const std::vector< T > &data)
Fill a column of the matrix.
Definition matrixnd.h:122
matrix3d< T > & add(const matrix3d< T > &X, T alfa=T(1))
Add the given matrix X scaled by alfa to *this.
Definition matrixnd.h:142
virtual ~matrix3d()
Empty destructor.
Definition matrixnd.h:65
matrix3d()
Constructor creating an empty matrix.
Definition matrixnd.h:33
matrix3d(std::istream &is, std::streamsize max=10)
Constructor to read a matrix from a stream.
Definition matrixnd.h:42
matrix3d< T > & operator+=(const matrix3d< T > &X)
Add the given matrix X to *this.
Definition matrixnd.h:138
matrix3d< T > & operator=(const matrix3d< T > &A)
Assignment operator.
Definition matrixnd.h:80
T & operator()(size_t i1, size_t i2, size_t i3)
Index-1 based element access.
Definition matrixnd.h:92
bool compatible(const matrix< T > &A, const matrix3d< T > &B, bool transA, size_t &M, size_t &N, size_t &K)
Check dimension compatibility for matrix-matrix multiplication.
Definition matrixnd.h:178
bool multiplyMat(const std::vector< T > &A, const matrix3d< T > &B, bool addTo=false)
Matrix-matrix multiplication.
Definition matrixnd.h:447
matrix3d(const matrix3d< T > &mat)
Copy constructor.
Definition matrixnd.h:40
const T & operator()(size_t i1, size_t i2, size_t i3) const
Index-1 based element access.
Definition matrixnd.h:102
bool multiply(const matrix< T > &A, const matrix3d< T > &B, bool transA=false, bool addTo=false)
Matrix-matrix multiplication.
Definition matrixnd.h:427
Four-dimensional rectangular matrix with some algebraic operations.
Definition matrixnd.h:226
virtual void clearIfNrowChanged(size_t n1, size_t n2, size_t n3)
Clears the content if any of the first three dimensions changed.
Definition matrixnd.h:332
matrix4d(size_t n_1, size_t n_2, size_t n_3, size_t n_4)
Constructor creating a matrix of dimension .
Definition matrixnd.h:234
T & operator()(size_t i1, size_t i2, size_t i3, size_t i4)
Index-1 based element access.
Definition matrixnd.h:269
matrix4d< T > & add(const matrix4d< T > &X, T alfa=T(1))
Add the given matrix X scaled by alfa to *this.
Definition matrixnd.h:294
void fillColumn(size_t i2, size_t i3, size_t i4, const std::vector< T > &data)
Fill a column of the matrix.
Definition matrixnd.h:320
matrix4d< T > & operator+=(const matrix4d< T > &X)
Add the given matrix X to *this.
Definition matrixnd.h:290
void resize(size_t n_1, size_t n_2, size_t n_3, size_t n_4, bool forceClear=false)
Resize the matrix to dimension .
Definition matrixnd.h:250
matrix4d()
Constructor creating an empty matrix.
Definition matrixnd.h:229
matrix4d< T > & operator-=(const matrix4d< T > &X)
Subtract the given matrix X from *this.
Definition matrixnd.h:292
vector< T > getColumn(size_t i2, size_t i3, size_t i4) const
Extract a column from the matrix.
Definition matrixnd.h:306
virtual ~matrix4d()
Empty destructor.
Definition matrixnd.h:240
matrix4d(vector< T > &vec)
Constructor using an external vector for matrix element storage.
Definition matrixnd.h:231
matrix4d(const matrix4d< T > &mat)
Copy constructor.
Definition matrixnd.h:237
const T & operator()(size_t i1, size_t i2, size_t i3, size_t i4) const
Index-1 based element access.
Definition matrixnd.h:280
matrix4d< T > & operator=(const matrix4d< T > &A)
Assignment operator.
Definition matrixnd.h:257
matrix4d< T > & multiply(T c)
Multiplication of this matrix by a scalar c.
Definition matrixnd.h:300
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
vector< T > & elem
Actual matrix elements, stored column by column.
Definition matrix.h:441
size_t size() const
Query total matrix size.
Definition matrix.h:378
bool empty() const
Check if the matrix is empty.
Definition matrix.h:380
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< 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
size_t cols() const
Query number of matrix columns.
Definition matrix.h:572
size_t rows() const
Query number of matrix rows.
Definition matrix.h:570
void fill(const std::vector< T > &v, size_t n, size_t m=0)
Fill the matrix with vector data.
Definition matrix.h:640
A vector class with some added algebraic operations.
Definition matrix.h:64
size_t size() const
Size of the vector.
Definition matrix.h:88
T * ptr()
Access through pointer.
Definition matrix.h:83
Simple template classes for dense rectangular matrices and vectors.
General utility classes and functions.
Definition SIMoptions.h:22
std::ostream & operator<<(std::ostream &s, const vector< T > &X)
Print the vector X to the stream s.
Definition matrix.h:1849