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  this->v_ = ListPolicy::allocate<Type>(len);
42 
43  }
44 }
45 
46 
47 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
48 
49 template<class Form, class Type>
51 :
52  mRows_(0),
53  nCols_(0),
54  v_(nullptr)
55 {}
56 
57 
58 template<class Form, class Type>
60 :
61  Matrix<Form, Type>(dims.first(), dims.second())
62 {}
63 
64 
65 template<class Form, class Type>
67 :
68  Matrix<Form, Type>(dims.first(), dims.second(), Foam::zero{})
69 {}
70 
71 
72 template<class Form, class Type>
73 inline Foam::Matrix<Form, Type>::Matrix(const labelPair& dims, const Type& val)
74 :
75  Matrix<Form, Type>(dims.first(), dims.second(), val)
76 {}
77 
78 
79 template<class Form, class Type>
82 {
84 }
85 
86 
87 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
88 
89 template<class Form, class Type>
90 inline Foam::label Foam::Matrix<Form, Type>::size() const noexcept
91 {
92  return (mRows_ * nCols_);
93 }
94 
95 
96 template<class Form, class Type>
98 {
99  return labelPair(mRows_, nCols_);
100 }
101 
102 
103 template<class Form, class Type>
105 {
106  return !mRows_ || !nCols_;
107 }
108 
109 
110 template<class Form, class Type>
111 inline void Foam::Matrix<Form, Type>::checki(const label i) const
112 {
113  if (!mRows_ || !nCols_)
114  {
116  << "Attempt to access element from empty matrix"
117  << abort(FatalError);
118  }
119  if (i < 0 || mRows_ <= i)
120  {
122  << "Index " << i << " out of range 0 ... " << mRows_-1
123  << abort(FatalError);
124  }
125 }
126 
127 
128 template<class Form, class Type>
129 inline void Foam::Matrix<Form, Type>::checkj(const label j) const
130 {
131  if (!mRows_ || !nCols_)
132  {
134  << "Attempt to access element from empty matrix"
135  << abort(FatalError);
136  }
137  if (j < 0 || nCols_ <= j)
138  {
140  << "index " << j << " out of range 0 ... " << nCols_-1
141  << abort(FatalError);
142  }
143 }
144 
145 
146 template<class Form, class Type>
147 inline void Foam::Matrix<Form, Type>::checkSize() const
148 {
149  if (mRows_ < 0 || nCols_ < 0)
150  {
152  << "Incorrect size (" << mRows_ << ", " << nCols_ << ')' << nl
154  }
155  // Could also check for odd sizes, like (0, N) and make (0,0)
156 }
157 
158 
159 template<class Form, class Type>
160 inline bool Foam::Matrix<Form, Type>::uniform() const
161 {
162  const label len = size();
163 
164  if (!len)
165  {
166  return false;
167  }
168 
169  // std::all_of()
170  for (label idx = 1; idx < len; ++idx)
171  {
172  if (v_[0] != v_[idx])
173  {
174  return false;
175  }
176  }
177 
178  return true;
179 }
180 
181 
182 template<class Form, class Type>
183 inline const Type* Foam::Matrix<Form, Type>::cdata() const noexcept
184 {
185  return v_;
186 }
187 
188 
189 template<class Form, class Type>
191 {
192  return v_;
193 }
194 
195 
196 template<class Form, class Type>
198 {
199  return reinterpret_cast<const char*>(v_);
200 }
201 
202 
203 template<class Form, class Type>
205 {
206  return reinterpret_cast<char*>(v_);
207 }
208 
209 
210 template<class Form, class Type>
211 inline std::streamsize Foam::Matrix<Form, Type>::size_bytes() const noexcept
212 {
213  return std::streamsize(mRows_*nCols_)*sizeof(Type);
214 }
215 
216 
217 template<class Form, class Type>
218 inline const Type* Foam::Matrix<Form, Type>::rowData(const label irow) const
219 {
220  #ifdef FULLDEBUG
221  checki(irow);
222  #endif
223  return (v_ + irow*nCols_);
224 }
225 
226 
227 template<class Form, class Type>
228 inline Type* Foam::Matrix<Form, Type>::rowData(const label irow)
229 {
230  #ifdef FULLDEBUG
231  checki(irow);
232  #endif
233  return (v_ + irow*nCols_);
234 }
235 
236 
237 template<class Form, class Type>
238 inline const Type& Foam::Matrix<Form, Type>::at(const label idx) const
239 {
240  #ifdef FULLDEBUG
241  if (idx < 0 || this->size() <= idx)
242  {
244  << "index " << idx << " out of range 0 ... " << this->size()
245  << abort(FatalError);
246  }
247  #endif
248  return *(v_ + idx);
249 }
250 
251 
252 template<class Form, class Type>
253 inline Type& Foam::Matrix<Form, Type>::at(const label idx)
254 {
255  #ifdef FULLDEBUG
256  if (idx < 0 || this->size() <= idx)
257  {
259  << "index " << idx << " out of range 0 ... " << this->size()
260  << abort(FatalError);
261  }
262  #endif
263  return *(v_ + idx);
264 }
265 
266 
267 template<class Form, class Type>
270 (
271  const label colIndex,
272  const label rowIndex,
273  label len
274 ) const
275 {
276  if (len < 0)
277  {
278  len = mRows_ - rowIndex;
279  }
280 
281  return ConstMatrixBlock<mType>
282  (
283  *this,
284  len, // rows
285  1,
286  rowIndex,
287  colIndex
288  );
289 }
290 
291 
292 template<class Form, class Type>
295 (
296  const label rowIndex,
297  const label colIndex,
298  label len
299 ) const
300 {
301  if (len < 0)
302  {
303  len = nCols_ - colIndex;
304  }
305 
306  return ConstMatrixBlock<mType>
307  (
308  *this,
309  1,
310  len, // columns
311  rowIndex,
312  colIndex
313  );
314 }
315 
316 
317 template<class Form, class Type>
320 (
321  const label rowIndex,
322  const label colIndex,
323  label szRows,
324  label szCols
325 ) const
326 {
327  if (szRows < 0) szRows = mRows_ - rowIndex;
328  if (szCols < 0) szCols = nCols_ - colIndex;
329 
331  (
332  *this,
333  szRows,
334  szCols,
335  rowIndex,
336  colIndex
337  );
338 }
339 
340 
341 template<class Form, class Type>
342 template<class VectorSpace>
345 (
346  const label rowIndex,
347  const label colIndex
348 ) const
349 {
351  (
352  *this,
353  VectorSpace::mRows,
354  VectorSpace::nCols,
355  rowIndex,
356  colIndex
357  );
358 }
359 
360 
361 template<class Form, class Type>
364 (
365  const label colIndex,
366  const label rowIndex,
367  label len
368 )
369 {
370  if (len < 0)
371  {
372  len = mRows_ - rowIndex;
373  }
374 
375  return MatrixBlock<mType>
376  (
377  *this,
378  len, // rows
379  1,
380  rowIndex,
381  colIndex
382  );
383 }
384 
385 
386 template<class Form, class Type>
389 (
390  const label rowIndex,
391  const label colIndex,
392  label len
393 )
394 {
395  if (len < 0)
396  {
397  len = nCols_ - colIndex;
398  }
399 
400  return MatrixBlock<mType>
401  (
402  *this,
403  1,
404  len, // columns
405  rowIndex,
406  colIndex
407  );
408 }
409 
410 
411 template<class Form, class Type>
414 (
415  const label rowIndex,
416  const label colIndex,
417  label szRows,
418  label szCols
419 )
420 {
421  if (szRows < 0) szRows = mRows_ - rowIndex;
422  if (szCols < 0) szCols = nCols_ - colIndex;
423 
424  return MatrixBlock<mType>
425  (
426  *this,
427  szRows,
428  szCols,
429  rowIndex,
430  colIndex
431  );
432 }
433 
434 
435 template<class Form, class Type>
436 template<class VectorSpace>
439 (
440  const label rowIndex,
441  const label colIndex
442 )
443 {
444  return MatrixBlock<mType>
445  (
446  *this,
447  VectorSpace::mRows,
448  VectorSpace::nCols,
449  rowIndex,
450  colIndex
451  );
452 }
453 
454 
455 template<class Form, class Type>
456 inline void Foam::Matrix<Form, Type>::setSize(const label m, const label n)
457 {
458  resize(m, n);
459 }
460 
461 
462 template<class Form, class Type>
463 void Foam::Matrix<Form, Type>::shallowResize(const label m, const label n)
464 {
465  mRows_ = m;
466  nCols_ = n;
467 }
468 
469 
470 template<class Form, class Type>
472 (
473  const UList<Type>& x
474 ) const
475 {
476  return this->AmulImpl(x);
477 }
478 
479 
480 template<class Form, class Type>
481 template<class Addr>
483 (
485 ) const
486 {
487  return this->AmulImpl(x);
488 }
489 
490 
491 template<class Form, class Type>
493 (
494  const UList<Type>& x
495 ) const
496 {
497  return this->TmulImpl(x);
498 }
499 
500 
501 template<class Form, class Type>
502 template<class Addr>
504 (
506 ) const
507 {
508  return this->TmulImpl(x);
509 }
510 
511 
512 // * * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * //
513 
514 template<class Form, class Type>
517 {
518  return v_;
519 }
520 
521 
522 template<class Form, class Type>
525 {
526  return v_ + (mRows_ * nCols_);
527 }
528 
529 
530 template<class Form, class Type>
533 {
534  return v_;
535 }
536 
537 
538 template<class Form, class Type>
541 {
542  return v_ + (mRows_ * nCols_);
543 }
544 
545 
546 template<class Form, class Type>
549 {
550  return v_;
551 }
552 
553 
554 template<class Form, class Type>
557 {
558  return v_ + (mRows_ * nCols_);
559 }
560 
561 
562 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
563 
564 template<class Form, class Type>
565 inline const Type& Foam::Matrix<Form, Type>::operator()
566 (
567  const label irow,
568  const label jcol
569 ) const
570 {
571  #ifdef FULLDEBUG
572  checki(irow);
573  checkj(jcol);
574  #endif
575  return v_[irow*nCols_ + jcol];
576 }
577 
578 
579 template<class Form, class Type>
581 (
582  const label irow,
583  const label jcol
584 )
585 {
586  #ifdef FULLDEBUG
587  checki(irow);
588  checkj(jcol);
589  #endif
590  return v_[irow*nCols_ + jcol];
591 }
592 
593 
594 template<class Form, class Type>
595 inline const Type* Foam::Matrix<Form, Type>::operator[](const label irow) const
596 {
597  #ifdef FULLDEBUG
598  checki(irow);
599  #endif
600  return v_ + irow*nCols_;
601 }
602 
603 
604 template<class Form, class Type>
605 inline Type* Foam::Matrix<Form, Type>::operator[](const label irow)
606 {
607  #ifdef FULLDEBUG
608  checki(irow);
609  #endif
610  return v_ + irow*nCols_;
611 }
612 
613 
614 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
615 
616 namespace Foam
617 {
618 
619 // * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * //
620 
621 //- Matrix-vector multiplication (A * x), where x is a column vector
622 template<class Form, class Type>
623 inline tmp<Field<Type>> operator*
624 (
625  const Matrix<Form, Type>& mat,
626  const UList<Type>& x
627 )
628 {
629  return mat.Amul(x);
630 }
631 
632 
633 //- Matrix-vector multiplication (A * x), where x is a column vector
634 template<class Form, class Type, class Addr>
635 inline tmp<Field<Type>> operator*
636 (
637  const Matrix<Form, Type>& mat,
639 )
640 {
641  return mat.Amul(x);
642 }
643 
644 
645 //- Vector-Matrix multiplication (x * A), where x is a row vector
646 template<class Form, class Type>
647 inline tmp<Field<Type>> operator*
648 (
649  const UList<Type>& x,
650  const Matrix<Form, Type>& mat
651 )
652 {
653  return mat.Tmul(x);
654 }
655 
656 
657 //- Vector-Matrix multiplication (x * A), where x is a row vector
658 template<class Form, class Type, class Addr>
659 inline tmp<Field<Type>> operator*
660 (
662  const Matrix<Form, Type>& mat
663 )
664 {
665  return mat.Tmul(x);
666 }
667 
668 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
669 
670 } // End namespace Foam
671 
672 // ************************************************************************* //
void shallowResize(const label m, const label n)
Resize Matrix without reallocating storage (unsafe)
Definition: MatrixI.H:456
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:263
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:288
autoPtr< mType > clone() const
Clone.
Definition: MatrixI.H:74
constexpr Matrix() noexcept
Default construct (empty matrix)
Definition: MatrixI.H:43
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:486
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:600
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:465
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:449
const Type * operator[](const label irow) const
Return const pointer to data in the specified row - rowData().
Definition: MatrixI.H:588
iterator begin() noexcept
Return an iterator to begin traversing a Matrix.
Definition: MatrixI.H:509
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:97
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:313
char * data_bytes() noexcept
Return pointer to the underlying array serving as data storage, reinterpreted as byte data...
Definition: MatrixI.H:197
labelPair sizes() const noexcept
Return row/column sizes.
Definition: MatrixI.H:90
const Type & at(const label idx) const
Linear addressing const element access.
Definition: MatrixI.H:231
Type * iterator
Random access iterator for traversing a Matrix.
Definition: Matrix.H:138
bool uniform() const
True if all entries have identical values, and Matrix is non-empty.
Definition: MatrixI.H:153
iterator end() noexcept
Return an iterator to end traversing a Matrix.
Definition: MatrixI.H:517
label size() const noexcept
The number of elements in Matrix (m*n)
Definition: MatrixI.H:83
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:176
void checki(const label irow) const
Check index i is within valid range [0, m)
Definition: MatrixI.H:104
A templated (m x n) matrix of objects of <T>. The layout is (mRows x nCols) - row-major order: ...
const direction noexcept
Definition: scalarImpl.H:255
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:204
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:190
const Type * const_iterator
Random access iterator for traversing a Matrix.
Definition: Matrix.H:143
const_iterator cend() const noexcept
Return const_iterator to end traversing a constant Matrix.
Definition: MatrixI.H:533
const Type * rowData(const label irow) const
Return const pointer to data in the specified row.
Definition: MatrixI.H:211
void checkj(const label jcol) const
Check index j is within valid range [0, n)
Definition: MatrixI.H:122
Type * data() noexcept
Return pointer to the first data element, which can also be used to address into Matrix contents...
Definition: MatrixI.H:183
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:525
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:140