C++ Utilities  5.10.5
Useful C++ classes and routines such as argument parser, IO and conversion utilities
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 
8 namespace CppUtilities {
9 
11 namespace Detail {
12 template <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 };
23 template <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 
37 template <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 
46 template <> 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 
55 template <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 
76 template <typename T, typename UnderlyingContainer, typename... Dimensions> class MultiArray {
77 public:
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 
88 private:
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 
98 template <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 
107 template <typename T, typename UnderlyingContainer, typename... Dimensions>
109 {
110  return m_size;
111 }
112 
114 template <typename T, typename UnderlyingContainer, typename... Dimensions>
116 {
117  return std::tuple_size<std::tuple<Dimensions...>>::value;
118 }
119 
121 template <typename T, typename UnderlyingContainer, typename... Dimensions>
122 template <std::size_t index>
124 {
125  return static_cast<std::size_t>(std::get<index>(m_dims));
126 }
127 
130 template <typename T, typename UnderlyingContainer, typename... Dimensions>
132 {
133  return m_buff[HelperType::offset(m_dims, std::make_tuple(indices...), 1)];
134 }
135 
138 template <typename T, typename UnderlyingContainer, typename... Dimensions>
139 const 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 
146 template <typename T, typename UnderlyingContainer, typename... Dimensions> T *MultiArray<T, UnderlyingContainer, Dimensions...>::data()
147 {
148  return m_buff.data();
149 }
150 
153 template <typename T, typename UnderlyingContainer, typename... Dimensions> const T *MultiArray<T, UnderlyingContainer, Dimensions...>::data() const
154 {
155  return m_buff.data();
156 }
157 
160 template <typename T, typename UnderlyingContainer, typename... Dimensions>
161 typename UnderlyingContainer::template Type<T> &MultiArray<T, UnderlyingContainer, Dimensions...>::buffer()
162 {
163  return m_buff;
164 }
165 
169 template <typename ValueType, typename... DimensionSizes> inline auto makeMultiArray(DimensionSizes... dimensionSizes)
170 {
171  return MultiArray<ValueType, VectorBasedMultiArray<void>, DimensionSizes...>(dimensionSizes...);
172 }
173 
177 template <typename ValueType, std::size_t size, typename... DimensionSizes> inline auto makeFixedSizeMultiArray(DimensionSizes... dimensionSizes)
178 {
179  return MultiArray<ValueType, ArrayBasedMultiArray<size>, DimensionSizes...>(dimensionSizes...);
180 }
181 
185 template <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
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
static constexpr Type< T > init(std::size_t requiredSize)
Definition: multiarray.h:48
std::vector< T, std::allocator< T > > Type
Definition: multiarray.h:47
The VectorBasedMultiArray struct allows using an std::vector with custom allocator as underlying cont...
Definition: multiarray.h:37
static constexpr Type< T > init(std::size_t requiredSize)
Definition: multiarray.h:39
std::vector< T, Allocator > Type
Definition: multiarray.h:38