MatrixI.H
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2019-2021 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "MatrixBlock.H"
30 
31 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
32 
33 template<class Form, class Type>
35 {
36  const label len = size();
37 
38  if (len > 0)
39  {
40  // With sign-check to avoid spurious -Walloc-size-larger-than
41  v_ = new Type[len];
42  }
43 }
44 
45 
46 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
47 
48 template<class Form, class Type>
50 :
51  mRows_(0),
52  nCols_(0),
53  v_(nullptr)
54 {}
55 
56 
57 template<class Form, class Type>
59 :
60  Matrix<Form, Type>(dims.first(), dims.second())
61 {}
62 
63 
64 template<class Form, class Type>
66 :
67  Matrix<Form, Type>(dims.first(), dims.second(), Foam::zero{})
68 {}
69 
70 
71 template<class Form, class Type>
72 inline Foam::Matrix<Form, Type>::Matrix(const labelPair& dims, const Type& val)
73 :
74  Matrix<Form, Type>(dims.first(), dims.second(), val)
75 {}
76 
77 
78 template<class Form, class Type>
81 {
83 }
84 
85 
86 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
87 
88 template<class Form, class Type>
89 inline Foam::label Foam::Matrix<Form, Type>::size() const
90 {
91  return mRows_ * nCols_;
92 }
93 
94 
95 template<class Form, class Type>
97 {
98  return labelPair(mRows_, nCols_);
99 }
100 
101 
102 template<class Form, class Type>
104 {
105  return !mRows_ || !nCols_;
106 }
107 
108 
109 template<class Form, class Type>
110 inline void Foam::Matrix<Form, Type>::checki(const label i) const
111 {
112  if (!mRows_ || !nCols_)
113  {
115  << "Attempt to access element from empty matrix"
116  << abort(FatalError);
117  }
118  if (i < 0 || mRows_ <= i)
119  {
121  << "Index " << i << " out of range 0 ... " << mRows_-1
122  << abort(FatalError);
123  }
124 }
125 
126 
127 template<class Form, class Type>
128 inline void Foam::Matrix<Form, Type>::checkj(const label j) const
129 {
130  if (!mRows_ || !nCols_)
131  {
133  << "Attempt to access element from empty matrix"
134  << abort(FatalError);
135  }
136  if (j < 0 || nCols_ <= j)
137  {
139  << "index " << j << " out of range 0 ... " << nCols_-1
140  << abort(FatalError);
141  }
142 }
143 
144 
145 template<class Form, class Type>
146 inline void Foam::Matrix<Form, Type>::checkSize() const
147 {
148  if (mRows_ < 0 || nCols_ < 0)
149  {
151  << "Incorrect size (" << mRows_ << ", " << nCols_ << ')' << nl
153  }
154  // Could also check for odd sizes, like (0, N) and make (0,0)
155 }
156 
157 
158 template<class Form, class Type>
159 inline bool Foam::Matrix<Form, Type>::uniform() const
160 {
161  const label len = size();
162 
163  if (!len)
164  {
165  return false;
166  }
167 
168  // std::all_of()
169  for (label idx = 1; idx < len; ++idx)
170  {
171  if (v_[0] != v_[idx])
172  {
173  return false;
174  }
175  }
176 
177  return true;
178 }
179 
180 
181 template<class Form, class Type>
182 inline const Type* Foam::Matrix<Form, Type>::cdata() const noexcept
183 {
184  return v_;
185 }
186 
187 
188 template<class Form, class Type>
190 {
191  return v_;
192 }
193 
194 
195 template<class Form, class Type>
197 {
198  return reinterpret_cast<const char*>(v_);
199 }
200 
201 
202 template<class Form, class Type>
204 {
205  return reinterpret_cast<char*>(v_);
206 }
207 
208 
209 template<class Form, class Type>
210 inline std::streamsize Foam::Matrix<Form, Type>::size_bytes() const noexcept
211 {
212  return mRows_*nCols_*sizeof(Type);
213 }
214 
215 
216 template<class Form, class Type>
217 inline const Type* Foam::Matrix<Form, Type>::rowData(const label irow) const
218 {
219  #ifdef FULLDEBUG
220  checki(irow);
221  #endif
222  return (v_ + irow*nCols_);
223 }
224 
225 
226 template<class Form, class Type>
227 inline Type* Foam::Matrix<Form, Type>::rowData(const label irow)
228 {
229  #ifdef FULLDEBUG
230  checki(irow);
231  #endif
232  return (v_ + irow*nCols_);
233 }
234 
235 
236 template<class Form, class Type>
237 inline const Type& Foam::Matrix<Form, Type>::at(const label idx) const
238 {
239  #ifdef FULLDEBUG
240  if (idx < 0 || this->size() <= idx)
241  {
243  << "index " << idx << " out of range 0 ... " << this->size()
244  << abort(FatalError);
245  }
246  #endif
247  return *(v_ + idx);
248 }
249 
250 
251 template<class Form, class Type>
252 inline Type& Foam::Matrix<Form, Type>::at(const label idx)
253 {
254  #ifdef FULLDEBUG
255  if (idx < 0 || this->size() <= idx)
256  {
258  << "index " << idx << " out of range 0 ... " << this->size()
259  << abort(FatalError);
260  }
261  #endif
262  return *(v_ + idx);
263 }
264 
265 
266 template<class Form, class Type>
269 (
270  const label colIndex,
271  const label rowIndex,
272  label len
273 ) const
274 {
275  if (len < 0)
276  {
277  len = mRows_ - rowIndex;
278  }
279 
280  return ConstMatrixBlock<mType>
281  (
282  *this,
283  len, // rows
284  1,
285  rowIndex,
286  colIndex
287  );
288 }
289 
290 
291 template<class Form, class Type>
294 (
295  const label rowIndex,
296  const label colIndex,
297  label len
298 ) const
299 {
300  if (len < 0)
301  {
302  len = nCols_ - colIndex;
303  }
304 
305  return ConstMatrixBlock<mType>
306  (
307  *this,
308  1,
309  len, // columns
310  rowIndex,
311  colIndex
312  );
313 }
314 
315 
316 template<class Form, class Type>
319 (
320  const label rowIndex,
321  const label colIndex,
322  label szRows,
323  label szCols
324 ) const
325 {
326  if (szRows < 0) szRows = mRows_ - rowIndex;
327  if (szCols < 0) szCols = nCols_ - colIndex;
328 
330  (
331  *this,
332  szRows,
333  szCols,
334  rowIndex,
335  colIndex
336  );
337 }
338 
339 
340 template<class Form, class Type>
341 template<class VectorSpace>
344 (
345  const label rowIndex,
346  const label colIndex
347 ) const
348 {
350  (
351  *this,
352  VectorSpace::mRows,
353  VectorSpace::nCols,
354  rowIndex,
355  colIndex
356  );
357 }
358 
359 
360 template<class Form, class Type>
363 (
364  const label colIndex,
365  const label rowIndex,
366  label len
367 )
368 {
369  if (len < 0)
370  {
371  len = mRows_ - rowIndex;
372  }
373 
374  return MatrixBlock<mType>
375  (
376  *this,
377  len, // rows
378  1,
379  rowIndex,
380  colIndex
381  );
382 }
383 
384 
385 template<class Form, class Type>
388 (
389  const label rowIndex,
390  const label colIndex,
391  label len
392 )
393 {
394  if (len < 0)
395  {
396  len = nCols_ - colIndex;
397  }
398 
399  return MatrixBlock<mType>
400  (
401  *this,
402  1,
403  len, // columns
404  rowIndex,
405  colIndex
406  );
407 }
408 
409 
410 template<class Form, class Type>
413 (
414  const label rowIndex,
415  const label colIndex,
416  label szRows,
417  label szCols
418 )
419 {
420  if (szRows < 0) szRows = mRows_ - rowIndex;
421  if (szCols < 0) szCols = nCols_ - colIndex;
422 
423  return MatrixBlock<mType>
424  (
425  *this,
426  szRows,
427  szCols,
428  rowIndex,
429  colIndex
430  );
431 }
432 
433 
434 template<class Form, class Type>
435 template<class VectorSpace>
438 (
439  const label rowIndex,
440  const label colIndex
441 )
442 {
443  return MatrixBlock<mType>
444  (
445  *this,
446  VectorSpace::mRows,
447  VectorSpace::nCols,
448  rowIndex,
449  colIndex
450  );
451 }
452 
453 
454 template<class Form, class Type>
455 inline void Foam::Matrix<Form, Type>::setSize(const label m, const label n)
456 {
457  resize(m, n);
458 }
459 
460 
461 template<class Form, class Type>
462 void Foam::Matrix<Form, Type>::shallowResize(const label m, const label n)
463 {
464  mRows_ = m;
465  nCols_ = n;
466 }
467 
468 
469 template<class Form, class Type>
471 (
472  const UList<Type>& x
473 ) const
474 {
475  return this->AmulImpl(x);
476 }
477 
478 
479 template<class Form, class Type>
480 template<class Addr>
482 (
484 ) const
485 {
486  return this->AmulImpl(x);
487 }
488 
489 
490 template<class Form, class Type>
492 (
493  const UList<Type>& x
494 ) const
495 {
496  return this->TmulImpl(x);
497 }
498 
499 
500 template<class Form, class Type>
501 template<class Addr>
503 (
505 ) const
506 {
507  return this->TmulImpl(x);
508 }
509 
510 
511 // * * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * //
512 
513 template<class Form, class Type>
516 {
517  return v_;
518 }
519 
520 
521 template<class Form, class Type>
524 {
525  return v_ + (mRows_ * nCols_);
526 }
527 
528 
529 template<class Form, class Type>
532 {
533  return v_;
534 }
535 
536 
537 template<class Form, class Type>
540 {
541  return v_ + (mRows_ * nCols_);
542 }
543 
544 
545 template<class Form, class Type>
548 {
549  return v_;
550 }
551 
552 
553 template<class Form, class Type>
556 {
557  return v_ + (mRows_ * nCols_);
558 }
559 
560 
561 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
562 
563 template<class Form, class Type>
564 inline const Type& Foam::Matrix<Form, Type>::operator()
565 (
566  const label irow,
567  const label jcol
568 ) const
569 {
570  #ifdef FULLDEBUG
571  checki(irow);
572  checkj(jcol);
573  #endif
574  return v_[irow*nCols_ + jcol];
575 }
576 
577 
578 template<class Form, class Type>
580 (
581  const label irow,
582  const label jcol
583 )
584 {
585  #ifdef FULLDEBUG
586  checki(irow);
587  checkj(jcol);
588  #endif
589  return v_[irow*nCols_ + jcol];
590 }
591 
592 
593 template<class Form, class Type>
594 inline const Type* Foam::Matrix<Form, Type>::operator[](const label irow) const
595 {
596  #ifdef FULLDEBUG
597  checki(irow);
598  #endif
599  return v_ + irow*nCols_;
600 }
601 
602 
603 template<class Form, class Type>
604 inline Type* Foam::Matrix<Form, Type>::operator[](const label irow)
605 {
606  #ifdef FULLDEBUG
607  checki(irow);
608  #endif
609  return v_ + irow*nCols_;
610 }
611 
612 
613 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
614 
615 namespace Foam
616 {
617 
618 // * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * //
619 
620 //- Matrix-vector multiplication (A * x), where x is a column vector
621 template<class Form, class Type>
622 inline tmp<Field<Type>> operator*
623 (
624  const Matrix<Form, Type>& mat,
625  const UList<Type>& x
626 )
627 {
628  return mat.Amul(x);
629 }
630 
631 
632 //- Matrix-vector multiplication (A * x), where x is a column vector
633 template<class Form, class Type, class Addr>
634 inline tmp<Field<Type>> operator*
635 (
636  const Matrix<Form, Type>& mat,
638 )
639 {
640  return mat.Amul(x);
641 }
642 
643 
644 //- Vector-Matrix multiplication (x * A), where x is a row vector
645 template<class Form, class Type>
646 inline tmp<Field<Type>> operator*
647 (
648  const UList<Type>& x,
649  const Matrix<Form, Type>& mat
650 )
651 {
652  return mat.Tmul(x);
653 }
654 
655 
656 //- Vector-Matrix multiplication (x * A), where x is a row vector
657 template<class Form, class Type, class Addr>
658 inline tmp<Field<Type>> operator*
659 (
661  const Matrix<Form, Type>& mat
662 )
663 {
664  return mat.Tmul(x);
665 }
666 
667 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
668 
669 } // End namespace Foam
670 
671 // ************************************************************************* //
void shallowResize(const label m, const label n)
Resize Matrix without reallocating storage (unsafe)
Definition: MatrixI.H:455
ConstMatrixBlock< mType > subColumn(const label colIndex, const label rowIndex=0, label len=-1) const
Return const column or column&#39;s subset of Matrix.
Definition: MatrixI.H:262
ConstMatrixBlock< mType > subRow(const label rowIndex, const label colIndex=0, label len=-1) const
Return const row or const row&#39;s subset of Matrix.
Definition: MatrixI.H:287
autoPtr< mType > clone() const
Clone.
Definition: MatrixI.H:73
patchWriters resize(patchIds.size())
tmp< Field< Type > > Tmul(const UList< Type > &x) const
Left-multiply Matrix by a row vector (x * A)
Definition: MatrixI.H:485
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:608
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
tmp< Field< Type > > Amul(const UList< Type > &x) const
Right-multiply Matrix by a column vector (A * x)
Definition: MatrixI.H:464
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
A templated block of an (m x n) matrix of type <MatrixType>.
Definition: Matrix.H:62
void setSize(const label m, const label n)
Change Matrix dimensions, preserving the elements.
Definition: MatrixI.H:448
const Type * operator[](const label irow) const
Return const pointer to data in the specified row - rowData().
Definition: MatrixI.H:587
iterator begin() noexcept
Return an iterator to begin traversing a Matrix.
Definition: MatrixI.H:508
Base for lists with indirect addressing, templated on the list contents type and the addressing type...
bool empty() const noexcept
Return true if Matrix is empty (i.e., size() is zero)
Definition: MatrixI.H:96
ConstMatrixBlock< mType > subMatrix(const label rowIndex, const label colIndex, label szRows=-1, label szCols=-1) const
Return const sub-block of Matrix.
Definition: MatrixI.H:312
char * data_bytes() noexcept
Return pointer to the underlying array serving as data storage, reinterpreted as byte data...
Definition: MatrixI.H:196
label size() const
The number of elements in Matrix (m*n)
Definition: MatrixI.H:82
const Type & at(const label idx) const
Linear addressing const element access.
Definition: MatrixI.H:230
Type * iterator
Random access iterator for traversing a Matrix.
Definition: Matrix.H:141
labelPair sizes() const
Return row/column sizes.
Definition: MatrixI.H:89
bool uniform() const
True if all entries have identical values, and Matrix is non-empty.
Definition: MatrixI.H:152
iterator end() noexcept
Return an iterator to end traversing a Matrix.
Definition: MatrixI.H:516
errorManip< error > abort(error &err)
Definition: errorManip.H:139
const Type * cdata() const noexcept
Return const pointer to the first data element, which can also be used to address into Matrix content...
Definition: MatrixI.H:175
void checki(const label irow) const
Check index i is within valid range [0, m)
Definition: MatrixI.H:103
A templated (m x n) matrix of objects of <T>. The layout is (mRows x nCols) - row-major order: ...
const direction noexcept
Definition: Scalar.H:258
std::streamsize size_bytes() const noexcept
Number of contiguous bytes for the Matrix data, no runtime check that the type is actually contiguous...
Definition: MatrixI.H:203
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:51
const char * cdata_bytes() const noexcept
Return pointer to the underlying array serving as data storage, reinterpreted as byte data...
Definition: MatrixI.H:189
const Type * const_iterator
Random access iterator for traversing a Matrix.
Definition: Matrix.H:146
const_iterator cend() const noexcept
Return const_iterator to end traversing a constant Matrix.
Definition: MatrixI.H:532
const Type * rowData(const label irow) const
Return const pointer to data in the specified row.
Definition: MatrixI.H:210
void checkj(const label jcol) const
Check index j is within valid range [0, n)
Definition: MatrixI.H:121
Matrix() noexcept
Default construct (empty matrix)
Definition: MatrixI.H:42
Type * data() noexcept
Return pointer to the first data element, which can also be used to address into Matrix contents...
Definition: MatrixI.H:182
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:57
label n
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
const_iterator cbegin() const noexcept
Return const_iterator to begin traversing a constant Matrix.
Definition: MatrixI.H:524
A class for managing temporary objects.
Definition: HashPtrTable.H:50
ConstMatrixBlock< mType > block(const label rowIndex, const label colIndex) const
Access Field as a ConstMatrixBlock.
Namespace for OpenFOAM.
void checkSize() const
Check that dimensions are positive, non-zero.
Definition: MatrixI.H:139