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
233 static constexpr
236 Zero () noexcept {
238 return Z;
239 }
240
244 transpose () const
245 {
247 for (int j = StartIndex; j < NRows+StartIndex; ++j) {
248 for (int i = StartIndex; i < NCols+StartIndex; ++i) {
249 r(i,j) = (*this)(j,i);
250 }
251 }
252 return r;
253 }
254
256 template <int MM=NRows, int NN=NCols, std::enable_if_t<MM==NN,int> = 0>
260 {
261 static_assert(StartIndex == 0 || StartIndex == 1);
262 for (int j = 1+StartIndex; j < NCols+StartIndex; ++j) {
263 for (int i = StartIndex; i < j; ++i) {
264 amrex::Swap((*this)(i,j), (*this)(j,i));
265 }
266 }
267 return *this;
268 }
269
272 T product () const
273 {
274 T p = 1;
275 for (auto const& x : m_mat) {
276 p *= x;
277 }
278 return p;
279 }
280
283 T sum () const
284 {
285 T s = 0;
286 for (auto const& x : m_mat) {
287 s += x;
288 }
289 return s;
290 }
291
293 template <int MM=NRows, int NN=NCols, std::enable_if_t<MM==NN,int> = 0>
295 T trace () const
296 {
297 T t = 0;
298 constexpr_for<StartIndex,MM+StartIndex>([&] (int i) { t += (*this)(i,i); });
299 return t;
300 }
301
306 {
307 for (int n = 0; n < NRows*NCols; ++n) {
308 m_mat[n] += rhs.m_mat[n];
309 }
310 return *this;
311 }
312
318 {
319 lhs += rhs;
320 return lhs;
321 }
322
327 {
328 for (int n = 0; n < NRows*NCols; ++n) {
329 m_mat[n] -= rhs.m_mat[n];
330 }
331 return *this;
332 }
333
339 {
340 lhs -= rhs;
341 return lhs;
342 }
343
348 {
349 return (*this) * T(-1);
350 }
351
356 {
357 for (auto& x : m_mat) {
358 x *= a;
359 }
360 return *this;
361 }
362
367 {
368 m *= a;
369 return m;
370 }
371
376 {
377 m *= a;
378 return m;
379 }
380
382 template <class U, class V, int N1, int N2, int N3, Order Ord, int SI>
384 friend decltype(auto)
385 operator* (SmallMatrix<U,N1,N2,Ord,SI> const& lhs,
386 SmallMatrix<V,N2,N3,Ord,SI> const& rhs);
387
391 {
392 T r = 0;
393 for (int n = 0; n < NRows*NCols; ++n) {
394 r += m_mat[n] * rhs.m_mat[n];
395 }
396 return r;
397 }
398
399 template <int N, std::enable_if_t<(N<NRows*NCols),int> = 0>
400 [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
401 constexpr T const& get () const { return m_mat[N]; }
402
403 template <int N, std::enable_if_t<(N<NRows*NCols),int> = 0>
404 [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
405 constexpr T& get () { return m_mat[N]; }
406
407 private:
408 T m_mat[NRows*NCols];
409 };
410
411 template <class U, class V, int N1, int N2, int N3, Order Ord, int SI>
413 decltype(auto)
414 operator* (SmallMatrix<U,N1,N2,Ord,SI> const& lhs,
416 {
417 static_assert(SI == 0 || SI == 1);
418
419 using P = decltype(std::declval<U>() * std::declval<V>());
421
422 if constexpr (Ord == Order::F) {
423 for (int j = SI; j < N3+SI; ++j) {
424 constexpr_for<SI,N1+SI>([&] (int i) { r(i,j) = P(0); });
425 for (int k = SI; k < N2+SI; ++k) {
426 auto b = rhs(k,j);
427 constexpr_for<SI,N1+SI>([&] (int i)
428 {
429 r(i,j) += lhs(i,k) * b;
430 });
431 }
432 }
433 } else {
434 for (int i = SI; i < N1+SI; ++i) {
435 constexpr_for<SI,N3+SI>([&] (int j) { r(i,j) = P(0); });
436 for (int k = SI; k < N2+SI; ++k) {
437 auto a = lhs(i,k);
438 constexpr_for<SI,N3+SI>([&] (int j)
439 {
440 r(i,j) += a * rhs(k,j);
441 });
442 }
443 }
444 }
445 return r;
446 }
447
448 template <class T, int NRows, int NCols, Order ORDER, int SI>
449 std::ostream& operator<< (std::ostream& os,
451 {
452 for (int i = SI; i < NRows+SI; ++i) {
453 os << mat(i,SI);
454 for (int j = 1+SI; j < NCols+SI; ++j) {
455 os << " " << mat(i,j);
456 }
457 os << "\n";
458 }
459 return os;
460 }
461
462 template <class T, int N, int StartIndex = 0>
464
465 template <class T, int N, int StartIndex = 0>
467}
468
469template <class T, int NRows, int NCols, amrex::Order ORDER, int StartIndex>
470struct std::tuple_size<amrex::SmallMatrix<T,NRows,NCols,ORDER,StartIndex> >
471 : std::integral_constant<std::size_t,NRows*NCols> {};
472
473template <std::size_t N, class T, int NRows, int NCols, amrex::Order ORDER, int StartIndex>
474struct std::tuple_element<N, amrex::SmallMatrix<T,NRows,NCols,ORDER,StartIndex> >
475{
476 using type = T;
477};
478
479#endif
480
481/*
482 * Notes on why SmallMatrix matrix{} is zero initialized.
483 *
484 * SmallMatrix is not an aggregate, because it has a user declared default
485 * constructor. The rule is that, for `SmallMatrix matrix{}` with an empty
486 * brace-enclosed initializer list, value-initialization is performed. The
487 * effects of value-initialization of SmallMatrix (which has a user-declared
488 * but not user-provided default constructor) are that the matrix object is
489 * first zero-initialized and then the object's default constructor is
490 * applied. Since the default constructor does nothing, the final result is
491 * the object is zero-initialized.
492 *
493 * Why is SmallMatrix's default constructor user-declared not user-provided?
494 * It's because we first declare it with `SmallMatrix () = default`.
495 *
496 * Reference:
497 * https://en.cppreference.com/w/cpp/language/list_initialization
498 * https://en.cppreference.com/w/cpp/language/value_initialization
499 * https://en.cppreference.com/w/cpp/language/zero_initialization
500 */
#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
__host__ __device__ void Swap(T &t1, T &t2) noexcept
Definition AMReX_Algorithm.H:93
Order
Definition AMReX_Order.H:7
std::ostream & operator<<(std::ostream &os, AmrMesh const &amr_mesh)
Definition AMReX_AmrMesh.cpp:1237
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:272
__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:366
__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:337
__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:326
__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:236
__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:305
__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:355
__host__ __device__ T trace() const
Returns the trace of a square matrix.
Definition AMReX_SmallMatrix.H:295
__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: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 addition, lhs+rhs.
Definition AMReX_SmallMatrix.H:316
__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:259
__host__ __device__ T sum() const
Returns the sum of all elements in the matrix.
Definition AMReX_SmallMatrix.H:283
__host__ __device__ SmallMatrix< T, NCols, NRows, ORDER, StartIndex > transpose() const
Returns transposed matrix.
Definition AMReX_SmallMatrix.H:244