30#include "../toolboxes/allocation_toolbox.hpp"
31#include "../basic_types/datatype_structure.hpp"
32#include "../parallelization/vectorization.hpp"
63template <
typename Index_t,
class Scalar_t, StorageType Store,
size_t AlignSize,
size_t StaticRows,
size_t StaticCols>
66 static_assert(StaticCols != 1 || Store !=
StorageType::RowMajor,
"Column vector should have column-major storage.");
73 alignas(AlignSize) Scalar_t
m_data[StaticRows * StaticCols];
78#define DUMMY_ALLOCATOR \
79 void m_allocate(size_t sz, Index_t rows, Index_t cols) noexcept {} \
80 void m_destroy() noexcept {}
91#define REAL_ALLOCATOR(EXTRA) \
92 static_assert(MemoryAllocation::is_power_of_two(AlignSize), "AlignSize is not a power of two."); \
94 void m_allocate(size_t sz, Index_t rows, Index_t cols) noexcept { \
96 m_data = MemoryAllocation::aligned_alloc<Scalar_t>(AlignSize, sz); \
97 if (!std::is_trivial<Scalar_t>::value) \
98 for (size_t i = 0; i < size(); ++i) new (m_data + i) Scalar_t(); \
101 void m_destroy() noexcept { \
102 if (!std::is_trivial<Scalar_t>::value) \
103 for (size_t i = 0; i < size(); ++i) m_data[i].~Scalar_t(); \
104 MemoryAllocation::aligned_free<Scalar_t>(m_data); \
118#define CUSTOM_CTOR_AND_DTOR_BASE(INIT, MOVE) \
119 AccessorImpl() noexcept : m_data(nullptr) { INIT; } \
121 AccessorImpl(AccessorImpl&& other) noexcept { \
123 m_data = other.m_data; \
124 other.m_data = nullptr; \
127 AccessorImpl& operator=(AccessorImpl&& other) noexcept { \
130 m_data = other.m_data; \
131 other.m_data = nullptr; \
135 ~AccessorImpl() noexcept { m_destroy(); }
140#define CUSTOM_CTOR_AND_DTOR(X) CUSTOM_CTOR_AND_DTOR_BASE(X = 0, X = other.X; other.X = 0)
145#define UNIV_ACCESSORS \
146 bool empty() const noexcept { return size() == 0; } \
147 Scalar_t* data() noexcept { return m_data; } \
148 const Scalar_t* data() const noexcept { return m_data; } \
149 Scalar_t* begin() noexcept { return data(); } \
150 const Scalar_t* begin() const noexcept { return data(); } \
151 Scalar_t* end() noexcept { return data() + size(); } \
152 const Scalar_t* end() const noexcept { return data() + size(); }
158#define MATRIX_ACCESSORS(M, N) \
160 Index_t rows() const noexcept { return M; } \
161 Index_t cols() const noexcept { return N; } \
162 size_t size() const noexcept { return M * N; } \
164 const Scalar_t& operator()(const Index_t i, const Index_t j) const noexcept { \
165 assert(i >= 0 && i < M && j >= 0 && j < N); \
166 if constexpr (Store == StorageType::RowMajor) { \
167 return m_data[i * N + j]; \
169 return m_data[i + j * M]; \
173 Scalar_t& operator()(const Index_t i, const Index_t j) noexcept { \
174 const AccessorImpl& const_this = *this; \
175 return const_cast<Scalar_t&>(const_this(i, j)); \
178 const Scalar_t* operator[](const Index_t k) const noexcept { \
179 if constexpr (Store == StorageType::RowMajor) { \
180 assert(k >= 0 && k < M); \
181 return &m_data[k * N]; \
183 assert(k >= 0 && k < N); \
184 return &m_data[k * M]; \
188 Scalar_t* operator[](const Index_t k) noexcept { \
189 const AccessorImpl& const_this = *this; \
190 return const_cast<Scalar_t*>(const_this[k]); \
196#define VECTOR_ACCESSORS(M, ROWMAJOR) \
198 Index_t rows() const noexcept { return ROWMAJOR ? 1 : M; } \
199 Index_t cols() const noexcept { return ROWMAJOR ? M : 1; } \
200 size_t size() const noexcept { return M; } \
202 Scalar_t& operator()(const Index_t i) noexcept { \
203 assert(i >= 0 && i < M); \
207 const Scalar_t& operator()(const Index_t i) const noexcept { \
208 assert(i >= 0 && i < M); \
212 Scalar_t& operator[](const Index_t i) noexcept { \
213 assert(i >= 0 && i < M); \
217 const Scalar_t& operator[](const Index_t i) const noexcept { \
218 assert(i >= 0 && i < M); \
228template <
typename Index_t,
class Scalar_t, StorageType Store,
size_t AlignSize,
size_t StaticCols>
230 static_assert(StaticCols != 1 || Store !=
StorageType::RowMajor,
"Column vector should have column-major storage.");
247template <typename Index_t, class Scalar_t,
StorageType Store,
size_t AlignSize,
size_t StaticRows>
266template <typename Index_t, class Scalar_t,
StorageType Store,
size_t AlignSize>
284template <
typename Index_t,
class Scalar_t,
size_t AlignSize,
size_t StaticRows>
287 alignas(AlignSize) Scalar_t m_data[StaticRows];
298template <
typename Index_t,
class Scalar_t,
size_t AlignSize>
315template <typename Index_t, class Scalar_t,
size_t AlignSize,
size_t StaticCols>
318 alignas(AlignSize) Scalar_t m_data[StaticCols];
329template <
typename Index_t,
class Scalar_t,
size_t AlignSize>
343#undef CUSTOM_CTOR_AND_DTOR_BASE
344#undef CUSTOM_CTOR_AND_DTOR
345#undef DUMMY_ALLOCATOR
347#undef MATRIX_ACCESSORS
348#undef VECTOR_ACCESSORS
372template <
typename Index_t,
class Scalar_t, StorageType Store,
size_t AlignSize,
size_t StaticRows,
size_t StaticCols>
375 static_assert(std::is_integral<Index_t>::value);
379 using Base::m_allocate;
381 using Base::m_destroy;
390 static constexpr bool IsVector = (StaticRows == 1) || (StaticCols == 1);
393 static constexpr size_t StaticSize = StaticRows * StaticCols;
394 static constexpr size_t StaticNRows = StaticRows;
395 static constexpr size_t StaticNCols = StaticCols;
402 const Index m_increment;
414 m_ptr += m_increment;
423 template <
class IndexSIMD_t>
426 static_assert(std::is_integral<typename IndexSIMD_t::Scalar>::value);
427 enum { Size = IndexSIMD_t::Size };
428 IndexSIMD_t m_offsets;
429 const Index m_increment;
430 const Scalar*
const m_data;
436 : m_offsets(offsets), m_increment(increment), m_data(data) {}
444 m_offsets += m_increment;
453 size_t m_resize(Index_t rows, Index_t cols)
noexcept {
458 if (StaticRows == 1 && IsVector) {
464 if (StaticRows !=
DynamicSize) assert(rows == StaticRows &&
"A static size was asked to change.");
465 if (StaticCols !=
DynamicSize) assert(cols == StaticCols &&
"A static size was asked to change.");
468 rows = (StaticRows !=
DynamicSize) ? StaticRows : rows;
469 cols = (StaticCols !=
DynamicSize) ? StaticCols : cols;
472 size_t reqSize = rows * cols;
477 if (rows == this->rows() && cols == this->cols())
return reqSize;
482 size_t bytes = reqSize *
sizeof(Scalar_t);
483 m_allocate(bytes, rows, cols);
498 C2DContainer(
const Index_t size1,
const Index_t size2 = 1) noexcept :
Base() { m_resize(size1, size2); }
504 size_t sz = m_resize(other.rows(), other.cols());
505 for (
size_t i = 0; i < sz; ++i) m_data[i] = other.m_data[i];
512 size_t sz = m_resize(other.rows(), other.cols());
513 for (
size_t i = 0; i < sz; ++i) m_data[i] = other.m_data[i];
542 m_resize(size1, size2);
552 for (
size_t i = 0; i < size(); ++i) m_data[i] = value;
560 return CInnerIter(&m_data[IsRowMajor ? row * cols() : row], IsRowMajor ? 1 : rows());
566 template <
class T,
size_t N>
576 template <
class StaticContainer>
578 constexpr size_t Size = StaticContainer::StaticSize;
579 static_assert(Size,
"This method requires a static output type.");
580 assert(Size <= cols() - start);
583 for (
size_t i = 0; i < Size; ++i)
584 ret.data()[i] = m_data[IsRowMajor ? row * cols() + i + start : row + (i + start) * rows()];
591 template <
class StaticContainer,
class T,
size_t N>
593 constexpr size_t Size = StaticContainer::StaticSize;
594 static_assert(Size,
"This method requires a static output type.");
595 assert(Size <= cols() - start);
597 for (
size_t k = 0; k < N; ++k) {
599 for (
size_t i = 0; i < Size; ++i)
600 ret.data()[i][k] = m_data[IsRowMajor ? row[k] * cols() + i + start : row[k] + (i + start) * rows()];
#define REAL_ALLOCATOR(EXTRA)
Definition C2DContainer.hpp:91
#define DUMMY_ALLOCATOR
Definition C2DContainer.hpp:78
#define CUSTOM_CTOR_AND_DTOR(X)
Definition C2DContainer.hpp:140
#define VECTOR_ACCESSORS(M, ROWMAJOR)
Definition C2DContainer.hpp:196
#define CUSTOM_CTOR_AND_DTOR_BASE(INIT, MOVE)
Definition C2DContainer.hpp:118
#define MATRIX_ACCESSORS(M, N)
Definition C2DContainer.hpp:158
SIMD iterator to the inner dimension of the container, read-only, generic non-contiguous access.
Definition C2DContainer.hpp:424
CInnerIterGather(const Scalar *data, Index increment, IndexSIMD_t offsets) noexcept
Definition C2DContainer.hpp:435
CInnerIterGather()=delete
simd::Array< Scalar, Size > operator*() const noexcept
Definition C2DContainer.hpp:438
CInnerIterGather operator++(int) noexcept
Definition C2DContainer.hpp:442
Scalar iterator to the inner dimension of the container, read-only.
Definition C2DContainer.hpp:400
CInnerIter operator++(int) noexcept
Definition C2DContainer.hpp:412
CInnerIter(const Scalar *ptr, Index increment) noexcept
Definition C2DContainer.hpp:408
Scalar operator*() const noexcept
Definition C2DContainer.hpp:410
A templated matrix/vector-like object.
Definition C2DContainer.hpp:374
CInnerIterGather< simd::Array< T, N > > innerIter(simd::Array< T, N > row) const noexcept
Get a SIMD gather iterator to the inner dimension of the container.
Definition C2DContainer.hpp:567
C2DContainer(const C2DContainer &other) noexcept
Copy ctor.
Definition C2DContainer.hpp:503
C2DContainer & resize(const Index_t size1, const Index_t size2=1) noexcept
Request a change of size.
Definition C2DContainer.hpp:541
StaticContainer get(Index_t row, Index_t start=0) const noexcept
Return copy of data in a static size container.
Definition C2DContainer.hpp:577
CInnerIter innerIter(Index_t row) const noexcept
Get a scalar iterator to the inner dimension of the container.
Definition C2DContainer.hpp:559
Scalar_t Scalar
Definition C2DContainer.hpp:388
C2DContainer & operator=(const C2DContainer &other) noexcept
Copy assignment operator, no re-allocation if sizes do not change.
Definition C2DContainer.hpp:511
void setConstant(const Scalar_t &value) noexcept
Set value of all entries to "value".
Definition C2DContainer.hpp:549
C2DContainer(C2DContainer &&)=default
Move ctor, implemented by base class (if fully static works as copy).
C2DContainer & operator=(const Scalar_t &value) noexcept
Definition C2DContainer.hpp:530
C2DContainer() noexcept
Default ctor.
Definition C2DContainer.hpp:492
StaticContainer get(simd::Array< T, N > row, Index_t start=0) const noexcept
Return copy of data in a static size container, SIMD version.
Definition C2DContainer.hpp:592
C2DContainer(const Index_t size1, const Index_t size2=1) noexcept
Sizing ctor (no initialization of data). For matrices size1 is rows and size2 columns,...
Definition C2DContainer.hpp:498
Index_t Index
Definition C2DContainer.hpp:387
C2DContainer & operator=(C2DContainer &&)=default
Move assign operator, implemented by base class (if fully static works as copy).
Index_t m_rows
Definition C2DContainer.hpp:301
Scalar_t * m_data
Definition C2DContainer.hpp:302
Scalar_t * m_data
Definition C2DContainer.hpp:333
Index_t m_cols
Definition C2DContainer.hpp:332
Scalar_t * m_data
Definition C2DContainer.hpp:253
Index_t m_cols
Definition C2DContainer.hpp:252
Index_t m_cols
Definition C2DContainer.hpp:269
Scalar_t * m_data
Definition C2DContainer.hpp:270
Scalar_t * m_data
Definition C2DContainer.hpp:234
Index_t m_rows
Definition C2DContainer.hpp:233
Base accessor class and version of template for both sizes known at compile time.
Definition C2DContainer.hpp:64
Index_t cols() const noexcept
Definition C2DContainer.hpp:222
Scalar_t m_data[StaticRows *StaticCols]
Definition C2DContainer.hpp:73
Index_t rows() const noexcept
Definition C2DContainer.hpp:222
A simple SIMD type relying on implicit vectorization, i.e. done by the compiler, explicitly vectorize...
Definition vectorization.hpp:89
#define SU2_IGNORE_WARNING(WARNING)
Definition code_config.hpp:219
#define SU2_RESTORE_WARNING
Definition code_config.hpp:220
#define FORCEINLINE
Definition code_config.hpp:44
StorageType
Supported ways to flatten a matrix into an array. Contiguous rows or contiguous columns respectively.
Definition C2DContainer.hpp:45
SizeType
Special value "DynamicSize" to indicate a dynamic size.
Definition C2DContainer.hpp:51
@ DynamicSize
Definition C2DContainer.hpp:51
Definition C2DContainer.hpp:55
#define SU2_OMP_SIMD
Definition omp_structure.hpp:125
#define SU2_OMP_SIMD_IF_NOT_AD
Definition omp_structure.hpp:129