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>
61 requires (NRows==1 || NCols==1)
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
132 const T& operator() (int i) const noexcept
133 requires (NRows==1 || NCols==1)
134 {
135 static_assert(StartIndex == 0 || StartIndex == 1);
136 if constexpr (StartIndex == 1) {
137 --i;
138 }
139 AMREX_ASSERT(i >= 0);
140 AMREX_ASSERT(i < NRows*NCols);
141 return m_mat[i];
142 }
143
146 T& operator() (int i) noexcept
147 requires (NRows==1 || NCols==1)
148 {
149 static_assert(StartIndex == 0 || StartIndex == 1);
150 if constexpr (StartIndex == 1) {
151 --i;
152 }
153 AMREX_ASSERT(i >= 0);
154 AMREX_ASSERT(i < NRows*NCols);
155 return m_mat[i];
156 }
157
160 const T& operator[] (int i) const noexcept
161 requires (NRows==1 || NCols==1)
162 {
163 static_assert(StartIndex == 0 || StartIndex == 1);
164 if constexpr (StartIndex == 1) {
165 --i;
166 }
167 AMREX_ASSERT(i >= 0);
168 AMREX_ASSERT(i < NRows*NCols);
169 return m_mat[i];
170 }
171
174 T& operator[] (int i) noexcept
175 requires (NRows==1 || NCols==1)
176 {
177 static_assert(StartIndex == 0 || StartIndex == 1);
178 if constexpr (StartIndex == 1) {
179 --i;
180 }
181 AMREX_ASSERT(i >= 0);
182 AMREX_ASSERT(i < NRows*NCols);
183 return m_mat[i];
184 }
185
191 const T* begin () const noexcept { return m_mat; }
192
198 const T* end () const noexcept { return m_mat + NRows*NCols; }
199
205 T* begin () noexcept { return m_mat; }
206
212 T* end () noexcept { return m_mat + NRows*NCols; }
213
217 setVal (T val)
218 {
219 for (auto& x : m_mat) { x = val; }
220 return *this;
221 }
222
224 static constexpr
227 Identity () noexcept requires (NRows==NCols)
228 {
229 static_assert(StartIndex == 0 || StartIndex == 1);
231 constexpr_for<StartIndex,NRows+StartIndex>(
232 [&] (int i) { I(i,i) = T(1); });
233 return I;
234 }
235
244 static constexpr
247 Omega () noexcept
248 requires (NRows==NCols && NRows%2==0 && std::is_floating_point_v<T>)
249 {
250 static_assert(StartIndex == 0 || StartIndex == 1);
252 constexpr_for<0,NRows/2>(
253 [&] (int i) {
254 omega(2*i + StartIndex, 2*i+1 + StartIndex) = T(1);
255 omega(2*i+1 + StartIndex, 2*i + StartIndex) = -T(1);
256 });
257 return omega;
258 }
259
261 static constexpr
264 Zero () noexcept {
266 return Z;
267 }
268
272 transpose () const
273 {
275 for (int j = StartIndex; j < NRows+StartIndex; ++j) {
276 for (int i = StartIndex; i < NCols+StartIndex; ++i) {
277 r(i,j) = (*this)(j,i);
278 }
279 }
280 return r;
281 }
282
286 transposeInPlace () requires (NRows==NCols)
287 {
288 static_assert(StartIndex == 0 || StartIndex == 1);
289 for (int j = 1+StartIndex; j < NCols+StartIndex; ++j) {
290 for (int i = StartIndex; i < j; ++i) {
291 amrex::Swap((*this)(i,j), (*this)(j,i));
292 }
293 }
294 return *this;
295 }
296
299 T product () const
300 {
301 T p = 1;
302 for (auto const& x : m_mat) {
303 p *= x;
304 }
305 return p;
306 }
307
310 T sum () const
311 {
312 T s = 0;
313 for (auto const& x : m_mat) {
314 s += x;
315 }
316 return s;
317 }
318
321 T trace () const requires (NRows==NCols)
322 {
323 T t = 0;
324 constexpr_for<StartIndex,NRows+StartIndex>([&] (int i) { t += (*this)(i,i); });
325 return t;
326 }
327
332 {
333 for (int n = 0; n < NRows*NCols; ++n) {
334 m_mat[n] += rhs.m_mat[n];
335 }
336 return *this;
337 }
338
344 {
345 lhs += rhs;
346 return lhs;
347 }
348
353 {
354 for (int n = 0; n < NRows*NCols; ++n) {
355 m_mat[n] -= rhs.m_mat[n];
356 }
357 return *this;
358 }
359
365 {
366 lhs -= rhs;
367 return lhs;
368 }
369
374 {
375 return (*this) * T(-1);
376 }
377
382 {
383 for (auto& x : m_mat) {
384 x *= a;
385 }
386 return *this;
387 }
388
393 {
394 m *= a;
395 return m;
396 }
397
402 {
403 m *= a;
404 return m;
405 }
406
408 template <class U, class V, int N1, int N2, int N3, Order Ord, int SI>
410 friend decltype(auto)
411 operator* (SmallMatrix<U,N1,N2,Ord,SI> const& lhs,
412 SmallMatrix<V,N2,N3,Ord,SI> const& rhs);
413
417 {
418 T r = 0;
419 for (int n = 0; n < NRows*NCols; ++n) {
420 r += m_mat[n] * rhs.m_mat[n];
421 }
422 return r;
423 }
424
425 template <int N>
426 requires (N<NRows*NCols)
428 constexpr T const& get () const { return m_mat[N]; }
429
430 template <int N>
431 requires (N<NRows*NCols)
433 constexpr T& get () { return m_mat[N]; }
434
435 private:
436 T m_mat[NRows*NCols];
437 };
438
439 template <class U, class V, int N1, int N2, int N3, Order Ord, int SI>
441 decltype(auto)
442 operator* (SmallMatrix<U,N1,N2,Ord,SI> const& lhs,
444 {
445 static_assert(SI == 0 || SI == 1);
446
447 using P = decltype(std::declval<U>() * std::declval<V>());
449
450 if constexpr (Ord == Order::F) {
451 for (int j = SI; j < N3+SI; ++j) {
452 constexpr_for<SI,N1+SI>([&] (int i) { r(i,j) = P(0); });
453 for (int k = SI; k < N2+SI; ++k) {
454 auto b = rhs(k,j);
455 constexpr_for<SI,N1+SI>([&] (int i)
456 {
457 r(i,j) += lhs(i,k) * b;
458 });
459 }
460 }
461 } else {
462 for (int i = SI; i < N1+SI; ++i) {
463 constexpr_for<SI,N3+SI>([&] (int j) { r(i,j) = P(0); });
464 for (int k = SI; k < N2+SI; ++k) {
465 auto a = lhs(i,k);
466 constexpr_for<SI,N3+SI>([&] (int j)
467 {
468 r(i,j) += a * rhs(k,j);
469 });
470 }
471 }
472 }
473 return r;
474 }
475
476 template <class T, int NRows, int NCols, Order ORDER, int SI>
477 std::ostream& operator<< (std::ostream& os,
479 {
480 for (int i = SI; i < NRows+SI; ++i) {
481 os << mat(i,SI);
482 for (int j = 1+SI; j < NCols+SI; ++j) {
483 os << " " << mat(i,j);
484 }
485 os << "\n";
486 }
487 return os;
488 }
489
490 template <class T, int N, int StartIndex = 0>
492
493 template <class T, int N, int StartIndex = 0>
495}
496
497template <class T, int NRows, int NCols, amrex::Order ORDER, int StartIndex>
498struct std::tuple_size<amrex::SmallMatrix<T,NRows,NCols,ORDER,StartIndex> >
499 : std::integral_constant<std::size_t,NRows*NCols> {};
500
501template <std::size_t N, class T, int NRows, int NCols, amrex::Order ORDER, int StartIndex>
502struct std::tuple_element<N, amrex::SmallMatrix<T,NRows,NCols,ORDER,StartIndex> >
503{
504 using type = T;
505};
506
507#endif
508
509/*
510 * Notes on why SmallMatrix matrix{} is zero initialized.
511 *
512 * SmallMatrix is not an aggregate, because it has a user declared default
513 * constructor. The rule is that, for `SmallMatrix matrix{}` with an empty
514 * brace-enclosed initializer list, value-initialization is performed. The
515 * effects of value-initialization of SmallMatrix (which has a user-declared
516 * but not user-provided default constructor) are that the matrix object is
517 * first zero-initialized and then the object's default constructor is
518 * applied. Since the default constructor does nothing, the final result is
519 * the object is zero-initialized.
520 *
521 * Why is SmallMatrix's default constructor user-declared not user-provided?
522 * It's because we first declare it with `SmallMatrix () = default`.
523 *
524 * Reference:
525 * https://en.cppreference.com/w/cpp/language/list_initialization
526 * https://en.cppreference.com/w/cpp/language/value_initialization
527 * https://en.cppreference.com/w/cpp/language/zero_initialization
528 */
#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:50
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:94
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:198
__host__ __device__ const T & operator[](int i) const noexcept
Returns a const reference to element i of a vector.
Definition AMReX_SmallMatrix.H:160
__host__ __device__ SmallMatrix< T, NRows, NCols, ORDER, StartIndex > & transposeInPlace()
Transposes a square matrix in-place.
Definition AMReX_SmallMatrix.H:286
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:299
static constexpr __host__ __device__ SmallMatrix< T, NRows, NCols, ORDER, StartIndex > Identity() noexcept
Returns an identity matrix.
Definition AMReX_SmallMatrix.H:227
__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:392
__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:363
__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:352
__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:264
__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:331
__host__ __device__ T * end() noexcept
Definition AMReX_SmallMatrix.H:212
__host__ __device__ T * begin() noexcept
Definition AMReX_SmallMatrix.H:205
__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:381
__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:217
T value_type
Definition AMReX_SmallMatrix.H:37
__host__ __device__ constexpr T const & get() const
Definition AMReX_SmallMatrix.H:428
__host__ __device__ T trace() const
Returns the trace of a square matrix.
Definition AMReX_SmallMatrix.H:321
static constexpr int column_size
Definition AMReX_SmallMatrix.H:40
__host__ __device__ T dot(SmallMatrix< T, NRows, NCols, ORDER, StartIndex > const &rhs) const
Returns the dot product of two vectors.
Definition AMReX_SmallMatrix.H:416
__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:342
__host__ __device__ const T * begin() const noexcept
Definition AMReX_SmallMatrix.H:191
T & reference_type
Definition AMReX_SmallMatrix.H:38
static constexpr __host__ __device__ SmallMatrix< T, NRows, NCols, ORDER, StartIndex > Omega() noexcept
Definition AMReX_SmallMatrix.H:247
__host__ __device__ T sum() const
Returns the sum of all elements in the matrix.
Definition AMReX_SmallMatrix.H:310
__host__ __device__ SmallMatrix< T, NCols, NRows, ORDER, StartIndex > transpose() const
Returns transposed matrix.
Definition AMReX_SmallMatrix.H:272