C++ Utilities 5.26.1
Useful C++ classes and routines such as argument parser, IO and conversion utilities
Loading...
Searching...
No Matches
multiarray.h
Go to the documentation of this file.
1#ifndef CPP_UTILITIES_MULTI_ARRAY_H
2#define CPP_UTILITIES_MULTI_ARRAY_H
3
4#include <array>
5#include <tuple>
6#include <vector>
7
8namespace CppUtilities {
9
11namespace Detail {
12template <class Tuple, std::size_t N> struct DimensionsHelper {
13 static std::size_t requiredSize(const Tuple &dimensionSizes)
14 {
15 return DimensionsHelper<Tuple, N - 1>::requiredSize(dimensionSizes) * static_cast<std::size_t>(std::get<N - 1>(dimensionSizes));
16 }
17 static std::size_t offset(const Tuple &dimensions, const Tuple &indices, std::size_t factor)
18 {
19 return DimensionsHelper<Tuple, N - 1>::offset(dimensions, indices, factor * static_cast<std::size_t>(std::get<N - 1>(dimensions)))
20 + (factor * static_cast<std::size_t>(std::get<N - 1>(indices)));
21 }
22};
23template <class Tuple> struct DimensionsHelper<Tuple, 1> {
24 static std::size_t requiredSize(const Tuple &dimensionSizes)
25 {
26 return static_cast<std::size_t>(std::get<0>(dimensionSizes));
27 }
28 static std::size_t offset(const Tuple &, const Tuple &indices, std::size_t factor)
29 {
30 return factor * static_cast<std::size_t>(std::get<0>(indices));
31 }
32};
33} // namespace Detail
35
37template <typename Allocator> struct VectorBasedMultiArray {
38 template <typename T> using Type = std::vector<T, Allocator>;
39 template <typename T> static constexpr Type<T> init(std::size_t requiredSize)
40 {
41 return Type<T>(requiredSize);
42 }
43};
44
46template <> struct VectorBasedMultiArray<void> {
47 template <typename T> using Type = std::vector<T, std::allocator<T>>;
48 template <typename T> static constexpr Type<T> init(std::size_t requiredSize)
49 {
50 return Type<T>(requiredSize);
51 }
52};
53
55template <std::size_t size> struct ArrayBasedMultiArray {
56 template <typename T> using Type = std::array<T, size>;
57 template <typename T> static constexpr Type<T> init(std::size_t)
58 {
59 return Type<T>();
60 }
61};
62
65 template <typename T> using Type = T *;
66 template <typename T> static constexpr Type<T> init(std::size_t)
67 {
68 return nullptr;
69 }
70};
71
76template <typename T, typename UnderlyingContainer, typename... Dimensions> class MultiArray {
77public:
78 MultiArray(Dimensions... dimensionSizes);
79 std::size_t totalSize() const;
80 static constexpr std::size_t dimensionCount();
81 template <std::size_t index> std::size_t dimensionSize() const;
82 T &at(Dimensions... indices);
83 const T &at(Dimensions... indices) const;
84 T *data();
85 const T *data() const;
86 typename UnderlyingContainer::template Type<T> &buffer();
87
88private:
89 using HelperType = Detail::DimensionsHelper<std::tuple<Dimensions...>, dimensionCount()>;
90 const std::tuple<Dimensions...> m_dims;
91 const std::size_t m_size;
92 typename UnderlyingContainer::template Type<T> m_buff;
93};
94
98template <typename T, typename UnderlyingContainer, typename... Dimensions>
100 : m_dims(std::make_tuple(dimensionSizes...))
101 , m_size(HelperType::requiredSize(m_dims))
102 , m_buff(UnderlyingContainer::template init<T>(m_size))
103{
104}
105
107template <typename T, typename UnderlyingContainer, typename... Dimensions>
109{
110 return m_size;
111}
112
114template <typename T, typename UnderlyingContainer, typename... Dimensions>
116{
117 return std::tuple_size<std::tuple<Dimensions...>>::value;
118}
119
121template <typename T, typename UnderlyingContainer, typename... Dimensions>
122template <std::size_t index>
124{
125 return static_cast<std::size_t>(std::get<index>(m_dims));
126}
127
130template <typename T, typename UnderlyingContainer, typename... Dimensions>
132{
133 return m_buff[HelperType::offset(m_dims, std::make_tuple(indices...), 1)];
134}
135
138template <typename T, typename UnderlyingContainer, typename... Dimensions>
139const T &MultiArray<T, UnderlyingContainer, Dimensions...>::at(Dimensions... indices) const
140{
141 return m_buff[HelperType::offset(m_dims, std::make_tuple(indices...), 1)];
142}
143
146template <typename T, typename UnderlyingContainer, typename... Dimensions> T *MultiArray<T, UnderlyingContainer, Dimensions...>::data()
147{
148 return m_buff.data();
149}
150
153template <typename T, typename UnderlyingContainer, typename... Dimensions> const T *MultiArray<T, UnderlyingContainer, Dimensions...>::data() const
154{
155 return m_buff.data();
156}
157
160template <typename T, typename UnderlyingContainer, typename... Dimensions>
161typename UnderlyingContainer::template Type<T> &MultiArray<T, UnderlyingContainer, Dimensions...>::buffer()
162{
163 return m_buff;
164}
165
169template <typename ValueType, typename... DimensionSizes> inline auto makeMultiArray(DimensionSizes... dimensionSizes)
170{
171 return MultiArray<ValueType, VectorBasedMultiArray<void>, DimensionSizes...>(dimensionSizes...);
172}
173
177template <typename ValueType, std::size_t size, typename... DimensionSizes> inline auto makeFixedSizeMultiArray(DimensionSizes... dimensionSizes)
178{
179 return MultiArray<ValueType, ArrayBasedMultiArray<size>, DimensionSizes...>(dimensionSizes...);
180}
181
185template <typename ValueType, typename... DimensionSizes> inline auto makeNoneOwningMultiArray(DimensionSizes... dimensionSizes)
186{
187 return MultiArray<ValueType, NoneOwningMultiArray, DimensionSizes...>(dimensionSizes...);
188}
189
190} // namespace CppUtilities
191
192#endif // CPP_UTILITIES_MULTI_ARRAY_H
The MultiArray class provides an N-dimensional array.
Definition multiarray.h:76
MultiArray(Dimensions... dimensionSizes)
Constructs a new N-dimensional array. The sizes for the dimensions are passed as arguments and must b...
Definition multiarray.h:99
std::size_t dimensionSize() const
Returns the number of elements in the specified dimension.
Definition multiarray.h:123
std::size_t totalSize() const
Returns the total number of elements.
Definition multiarray.h:108
T & at(Dimensions... indices)
Returns the element at the position specified via indices.
Definition multiarray.h:131
static constexpr std::size_t dimensionCount()
Returns the number of dimensions for that type of array.
Definition multiarray.h:115
T * data()
Returns a pointer to the raw data.
Definition multiarray.h:146
UnderlyingContainer::template Type< T > & buffer()
Allows accessing the underlying buffer directly.
Definition multiarray.h:161
Contains all utilities provides by the c++utilities library.
auto makeNoneOwningMultiArray(DimensionSizes... dimensionSizes)
Constructs a new N-dimensional array using a caller-managed buffer as underlying container....
Definition multiarray.h:185
auto makeFixedSizeMultiArray(DimensionSizes... dimensionSizes)
Constructs a new N-dimensional array using a fixed size array as underlying container....
Definition multiarray.h:177
auto makeMultiArray(DimensionSizes... dimensionSizes)
Constructs a new N-dimensional array using an std::vector with std::allocator as underlying container...
Definition multiarray.h:169
STL namespace.
The ArrayBasedMultiArray struct allows using a fixed size array as underlying container for the Multi...
Definition multiarray.h:55
std::array< T, size > Type
Definition multiarray.h:56
static constexpr Type< T > init(std::size_t)
Definition multiarray.h:57
The NoneOwningMultiArray struct allows using a caller-managed buffer array as underlying container fo...
Definition multiarray.h:64
static constexpr Type< T > init(std::size_t)
Definition multiarray.h:66
std::vector< T, std::allocator< T > > Type
Definition multiarray.h:47
static constexpr Type< T > init(std::size_t requiredSize)
Definition multiarray.h:48
The VectorBasedMultiArray struct allows using an std::vector with custom allocator as underlying cont...
Definition multiarray.h:37
std::vector< T, Allocator > Type
Definition multiarray.h:38
static constexpr Type< T > init(std::size_t requiredSize)
Definition multiarray.h:39