Block-Structured AMR Software Framework
Loading...
Searching...
No Matches
AMReX_SmallMatrix.H
Go to the documentation of this file.
1#ifndef AMREX_SMALL_MATRIX_H_
2#define AMREX_SMALL_MATRIX_H_
3#include <AMReX_Config.H>
4
5#include <AMReX_Algorithm.H>
6#include <AMReX_BLassert.H>
7#include <AMReX_Extension.H>
10#include <AMReX_Order.H>
11
12#include <algorithm>
13#include <initializer_list>
14#include <iostream>
15#include <tuple>
16#include <type_traits>
17#include <utility>
18
19
20namespace amrex {
21
34 template <class T, int NRows, int NCols, Order ORDER = Order::F, int StartIndex = 0>
36 {
37 using value_type = T;
38 using reference_type = T&;
39 static constexpr int row_size = NRows;
40 static constexpr int column_size = NCols;
41 static constexpr Order ordering = ORDER;
42 static constexpr int starting_index = StartIndex;
43
51 constexpr SmallMatrix () = default;
52
60 template <typename... Ts, int MM=NRows, int NN=NCols,
61 std::enable_if_t<MM==1 || NN==1, int> = 0>
63 constexpr explicit SmallMatrix (Ts... vs)
64 : m_mat{vs...}
65 {
66 static_assert(sizeof...(vs) <= std::max(NRows,NCols));
67 }
68
81 explicit SmallMatrix (std::initializer_list<std::initializer_list<T>> const& init)
82 {
83 AMREX_ASSERT(NRows == init.size());
84 int i = StartIndex;
85 for (auto const& row : init) {
86 AMREX_ASSERT(NCols == row.size());
87 int j = StartIndex;
88 for (auto const& x : row) {
89 (*this)(i,j) = x;
90 ++j;
91 }
92 ++i;
93 }
94 }
95
98 const T& operator() (int i, int j) const noexcept {
99 static_assert(StartIndex == 0 || StartIndex == 1);
100 if constexpr (StartIndex == 1) {
101 --i;
102 --j;
103 }
104 AMREX_ASSERT(i >= 0 && j >= 0);
105 AMREX_ASSERT(i < NRows && j < NCols);
106 if constexpr (ORDER == Order::F) {
107 return m_mat[i+j*NRows];
108 } else {
109 return m_mat[j+i*NCols];
110 }
111 }
112
115 T& operator() (int i, int j) noexcept {
116 static_assert(StartIndex == 0 || StartIndex == 1);
117 if constexpr (StartIndex == 1) {
118 --i;
119 --j;
120 }
121 AMREX_ASSERT(i >= 0 && j >= 0);
122 AMREX_ASSERT(i < NRows && j < NCols);
123 if constexpr (ORDER == Order::F) {
124 return m_mat[i+j*NRows];
125 } else {
126 return m_mat[j+i*NCols];
127 }
128 }
129
131 template <int MM=NRows, int NN=NCols, std::enable_if_t<(MM==1 || NN==1), int> = 0>
133 const T& operator() (int i) const noexcept {
134 static_assert(StartIndex == 0 || StartIndex == 1);
135 if constexpr (StartIndex == 1) {
136 --i;
137 }
138 AMREX_ASSERT(i >= 0);
139 AMREX_ASSERT(i < NRows*NCols);
140 return m_mat[i];
141 }
142
144 template <int MM=NRows, int NN=NCols, std::enable_if_t<(MM==1 || NN==1), int> = 0>
146 T& operator() (int i) noexcept {
147 static_assert(StartIndex == 0 || StartIndex == 1);
148 if constexpr (StartIndex == 1) {
149 --i;
150 }
151 AMREX_ASSERT(i >= 0);
152 AMREX_ASSERT(i < NRows*NCols);
153 return m_mat[i];
154 }
155
157 template <int MM=NRows, int NN=NCols, std::enable_if_t<(MM==1 || NN==1), int> = 0>
159 const T& operator[] (int i) const noexcept {
160 static_assert(StartIndex == 0 || StartIndex == 1);
161 if constexpr (StartIndex == 1) {
162 --i;
163 }
164 AMREX_ASSERT(i >= 0);
165 AMREX_ASSERT(i < NRows*NCols);
166 return m_mat[i];
167 }
168
170 template <int MM=NRows, int NN=NCols, std::enable_if_t<(MM==1 || NN==1), int> = 0>
172 T& operator[] (int i) noexcept {
173 static_assert(StartIndex == 0 || StartIndex == 1);
174 if constexpr (StartIndex == 1) {
175 --i;
176 }
177 AMREX_ASSERT(i >= 0);
178 AMREX_ASSERT(i < NRows*NCols);
179 return m_mat[i];
180 }
181
187 const T* begin () const noexcept { return m_mat; }
188
194 const T* end () const noexcept { return m_mat + NRows*NCols; }
195
201 T* begin () noexcept { return m_mat; }
202
208 T* end () noexcept { return m_mat + NRows*NCols; }
209
213 setVal (T val)
214 {
215 for (auto& x : m_mat) { x = val; }
216 return *this;
217 }
218
220 template <int MM=NRows, int NN=NCols, std::enable_if_t<MM==NN, int> = 0>
221 static constexpr
224 Identity () noexcept {
225 static_assert(StartIndex == 0 || StartIndex == 1);
227 constexpr_for<StartIndex,NRows+StartIndex>(
228 [&] (int i) { I(i,i) = T(1); });
229 return I;
230 }
231
240 template <int MM=NRows, int NN=NCols,
241 std::enable_if_t<MM==NN && MM%2==0 && std::is_floating_point_v<T>, int> = 0>
242 static constexpr
245 Omega () noexcept {
246 static_assert(StartIndex == 0 || StartIndex == 1);
248 constexpr_for<0,NRows/2>(
249 [&] (int i) {
250 omega(2*i + StartIndex, 2*i+1 + StartIndex) = T(1);
251 omega(2*i+1 + StartIndex, 2*i + StartIndex) = -T(1);
252 });
253 return omega;
254 }
255
257 static constexpr
260 Zero () noexcept {
262 return Z;
263 }
264
268 transpose () const
269 {
271 for (int j = StartIndex; j < NRows+StartIndex; ++j) {
272 for (int i = StartIndex; i < NCols+StartIndex; ++i) {
273 r(i,j) = (*this)(j,i);
274 }
275 }
276 return r;
277 }
278
280 template <int MM=NRows, int NN=NCols, std::enable_if_t<MM==NN,int> = 0>
284 {
285 static_assert(StartIndex == 0 || StartIndex == 1);
286 for (int j = 1+StartIndex; j < NCols+StartIndex; ++j) {
287 for (int i = StartIndex; i < j; ++i) {
288 amrex::Swap((*this)(i,j), (*this)(j,i));
289 }
290 }
291 return *this;
292 }
293
296 T product () const
297 {
298 T p = 1;
299 for (auto const& x : m_mat) {
300 p *= x;
301 }
302 return p;
303 }
304
307 T sum () const
308 {
309 T s = 0;
310 for (auto const& x : m_mat) {
311 s += x;
312 }
313 return s;
314 }
315
317 template <int MM=NRows, int NN=NCols, std::enable_if_t<MM==NN,int> = 0>
319 T trace () const
320 {
321 T t = 0;
322 constexpr_for<StartIndex,MM+StartIndex>([&] (int i) { t += (*this)(i,i); });
323 return t;
324 }
325
330 {
331 for (int n = 0; n < NRows*NCols; ++n) {
332 m_mat[n] += rhs.m_mat[n];
333 }
334 return *this;
335 }
336
342 {
343 lhs += rhs;
344 return lhs;
345 }
346
351 {
352 for (int n = 0; n < NRows*NCols; ++n) {
353 m_mat[n] -= rhs.m_mat[n];
354 }
355 return *this;
356 }
357
363 {
364 lhs -= rhs;
365 return lhs;
366 }
367
372 {
373 return (*this) * T(-1);
374 }
375
380 {
381 for (auto& x : m_mat) {
382 x *= a;
383 }
384 return *this;
385 }
386
391 {
392 m *= a;
393 return m;
394 }
395
400 {
401 m *= a;
402 return m;
403 }
404
406 template <class U, class V, int N1, int N2, int N3, Order Ord, int SI>
408 friend decltype(auto)
409 operator* (SmallMatrix<U,N1,N2,Ord,SI> const& lhs,
410 SmallMatrix<V,N2,N3,Ord,SI> const& rhs);
411
415 {
416 T r = 0;
417 for (int n = 0; n < NRows*NCols; ++n) {
418 r += m_mat[n] * rhs.m_mat[n];
419 }
420 return r;
421 }
422
423 template <int N, std::enable_if_t<(N<NRows*NCols),int> = 0>
424 [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
425 constexpr T const& get () const { return m_mat[N]; }
426
427 template <int N, std::enable_if_t<(N<NRows*NCols),int> = 0>
428 [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
429 constexpr T& get () { return m_mat[N]; }
430
431 private:
432 T m_mat[NRows*NCols];
433 };
434
435 template <class U, class V, int N1, int N2, int N3, Order Ord, int SI>
437 decltype(auto)
438 operator* (SmallMatrix<U,N1,N2,Ord,SI> const& lhs,
440 {
441 static_assert(SI == 0 || SI == 1);
442
443 using P = decltype(std::declval<U>() * std::declval<V>());
445
446 if constexpr (Ord == Order::F) {
447 for (int j = SI; j < N3+SI; ++j) {
448 constexpr_for<SI,N1+SI>([&] (int i) { r(i,j) = P(0); });
449 for (int k = SI; k < N2+SI; ++k) {
450 auto b = rhs(k,j);
451 constexpr_for<SI,N1+SI>([&] (int i)
452 {
453 r(i,j) += lhs(i,k) * b;
454 });
455 }
456 }
457 } else {
458 for (int i = SI; i < N1+SI; ++i) {
459 constexpr_for<SI,N3+SI>([&] (int j) { r(i,j) = P(0); });
460 for (int k = SI; k < N2+SI; ++k) {
461 auto a = lhs(i,k);
462 constexpr_for<SI,N3+SI>([&] (int j)
463 {
464 r(i,j) += a * rhs(k,j);
465 });
466 }
467 }
468 }
469 return r;
470 }
471
472 template <class T, int NRows, int NCols, Order ORDER, int SI>
473 std::ostream& operator<< (std::ostream& os,
475 {
476 for (int i = SI; i < NRows+SI; ++i) {
477 os << mat(i,SI);
478 for (int j = 1+SI; j < NCols+SI; ++j) {
479 os << " " << mat(i,j);
480 }
481 os << "\n";
482 }
483 return os;
484 }
485
486 template <class T, int N, int StartIndex = 0>
488
489 template <class T, int N, int StartIndex = 0>
491}
492
493template <class T, int NRows, int NCols, amrex::Order ORDER, int StartIndex>
494struct std::tuple_size<amrex::SmallMatrix<T,NRows,NCols,ORDER,StartIndex> >
495 : std::integral_constant<std::size_t,NRows*NCols> {};
496
497template <std::size_t N, class T, int NRows, int NCols, amrex::Order ORDER, int StartIndex>
498struct std::tuple_element<N, amrex::SmallMatrix<T,NRows,NCols,ORDER,StartIndex> >
499{
500 using type = T;
501};
502
503#endif
504
505/*
506 * Notes on why SmallMatrix matrix{} is zero initialized.
507 *
508 * SmallMatrix is not an aggregate, because it has a user declared default
509 * constructor. The rule is that, for `SmallMatrix matrix{}` with an empty
510 * brace-enclosed initializer list, value-initialization is performed. The
511 * effects of value-initialization of SmallMatrix (which has a user-declared
512 * but not user-provided default constructor) are that the matrix object is
513 * first zero-initialized and then the object's default constructor is
514 * applied. Since the default constructor does nothing, the final result is
515 * the object is zero-initialized.
516 *
517 * Why is SmallMatrix's default constructor user-declared not user-provided?
518 * It's because we first declare it with `SmallMatrix () = default`.
519 *
520 * Reference:
521 * https://en.cppreference.com/w/cpp/language/list_initialization
522 * https://en.cppreference.com/w/cpp/language/value_initialization
523 * https://en.cppreference.com/w/cpp/language/zero_initialization
524 */
#define AMREX_ASSERT(EX)
Definition AMReX_BLassert.H:38
#define AMREX_FORCE_INLINE
Definition AMReX_Extension.H:119
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
Definition AMReX_Amr.cpp:49
std::ostream & operator<<(std::ostream &os, AmrMesh const &amr_mesh)
Stream helper; forwards to the friend declared inside AmrMesh.
Definition AMReX_AmrMesh.cpp:1306
__host__ __device__ void Swap(T &t1, T &t2) noexcept
Definition AMReX_Algorithm.H:93
Order
Definition AMReX_Order.H:7
__host__ __device__ constexpr void constexpr_for(F const &f)
Definition AMReX_ConstexprFor.H:28
Matrix class with compile-time size.
Definition AMReX_SmallMatrix.H:36
__host__ __device__ const T * end() const noexcept
Definition AMReX_SmallMatrix.H:194
static constexpr int row_size
Definition AMReX_SmallMatrix.H:39
__host__ __device__ T product() const
Returns the product of all elements in the matrix.
Definition AMReX_SmallMatrix.H:296
__host__ __device__ friend SmallMatrix< T, NRows, NCols, ORDER, StartIndex > operator*(SmallMatrix< T, NRows, NCols, ORDER, StartIndex > m, T a)
Returns the product of a matrix and a scalar.
Definition AMReX_SmallMatrix.H:390
__host__ __device__ friend SmallMatrix< T, NRows, NCols, ORDER, StartIndex > operator-(SmallMatrix< T, NRows, NCols, ORDER, StartIndex > lhs, SmallMatrix< T, NRows, NCols, ORDER, StartIndex > const &rhs)
Binary operator - returning the result of maxtrix subtraction, lhs-rhs.
Definition AMReX_SmallMatrix.H:361
__host__ __device__ constexpr SmallMatrix()=default
Default constructor.
static constexpr Order ordering
Definition AMReX_SmallMatrix.H:41
__host__ __device__ SmallMatrix< T, NRows, NCols, ORDER, StartIndex > & operator-=(SmallMatrix< T, NRows, NCols, ORDER, StartIndex > const &rhs)
Operator -= performing matrix subtraction as in (*this) -= rhs.
Definition AMReX_SmallMatrix.H:350
__host__ __device__ const T & operator()(int i, int j) const noexcept
Returns a const reference to the element at row i and column j.
Definition AMReX_SmallMatrix.H:98
static constexpr int starting_index
Definition AMReX_SmallMatrix.H:42
static constexpr __host__ __device__ SmallMatrix< T, NRows, NCols, ORDER, StartIndex > Zero() noexcept
Returns a matrix initialized with zeros.
Definition AMReX_SmallMatrix.H:260
__host__ __device__ SmallMatrix< T, NRows, NCols, ORDER, StartIndex > & operator+=(SmallMatrix< T, NRows, NCols, ORDER, StartIndex > const &rhs)
Operator += performing matrix addition as in (*this) += rhs.
Definition AMReX_SmallMatrix.H:329
__host__ __device__ T * end() noexcept
Definition AMReX_SmallMatrix.H:208
__host__ __device__ T * begin() noexcept
Definition AMReX_SmallMatrix.H:201
static constexpr __host__ __device__ SmallMatrix< T, NRows, NCols, ORDER, StartIndex > Identity() noexcept
Returns an identity matrix.
Definition AMReX_SmallMatrix.H:224
__host__ __device__ SmallMatrix(std::initializer_list< std::initializer_list< T > > const &init)
Constructs SmallMatrix with nested std::initializer_list.
Definition AMReX_SmallMatrix.H:81
__host__ __device__ SmallMatrix< T, NRows, NCols, ORDER, StartIndex > & operator*=(T a)
Operator *= that scales this matrix in place by a scalar.
Definition AMReX_SmallMatrix.H:379
__host__ __device__ T trace() const
Returns the trace of a square matrix.
Definition AMReX_SmallMatrix.H:319
__host__ __device__ SmallMatrix< T, NRows, NCols, ORDER, StartIndex > & setVal(T val)
Set all elements in the matrix to the given value.
Definition AMReX_SmallMatrix.H:213
T value_type
Definition AMReX_SmallMatrix.H:37
static constexpr int column_size
Definition AMReX_SmallMatrix.H:40
__host__ __device__ const T & operator[](int i) const noexcept
Returns a const reference to element i of a vector.
Definition AMReX_SmallMatrix.H:159
__host__ __device__ T dot(SmallMatrix< T, NRows, NCols, ORDER, StartIndex > const &rhs) const
Returns the dot product of two vectors.
Definition AMReX_SmallMatrix.H:414
__host__ __device__ friend SmallMatrix< T, NRows, NCols, ORDER, StartIndex > operator+(SmallMatrix< T, NRows, NCols, ORDER, StartIndex > lhs, SmallMatrix< T, NRows, NCols, ORDER, StartIndex > const &rhs)
Binary operator + returning the result of maxtrix addition, lhs+rhs.
Definition AMReX_SmallMatrix.H:340
__host__ __device__ const T * begin() const noexcept
Definition AMReX_SmallMatrix.H:187
T & reference_type
Definition AMReX_SmallMatrix.H:38
__host__ __device__ constexpr SmallMatrix(Ts... vs)
Constructs column- or row-vector.
Definition AMReX_SmallMatrix.H:63
__host__ __device__ SmallMatrix< T, NRows, NCols, ORDER, StartIndex > & transposeInPlace()
Transposes a square matrix in-place.
Definition AMReX_SmallMatrix.H:283
static constexpr __host__ __device__ SmallMatrix< T, NRows, NCols, ORDER, StartIndex > Omega() noexcept
Definition AMReX_SmallMatrix.H:245
__host__ __device__ T sum() const
Returns the sum of all elements in the matrix.
Definition AMReX_SmallMatrix.H:307
__host__ __device__ SmallMatrix< T, NCols, NRows, ORDER, StartIndex > transpose() const
Returns transposed matrix.
Definition AMReX_SmallMatrix.H:268