C++ Utilities  4.17.0
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 MiscUtilities {
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) * 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 * std::get<N - 1>(dimensions))
20  + (factor * 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 std::get<0>(dimensionSizes);
27  }
28  static std::size_t offset(const Tuple &, const Tuple &indices, std::size_t factor)
29  {
30  return factor * 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 
73 template <typename T, typename UnderlyingContainer, typename... Dimensions> class MultiArray {
74 public:
75  MultiArray(Dimensions... dimensionSizes);
76  std::size_t totalSize() const;
77  static constexpr std::size_t dimensionCount();
78  template <std::size_t index> std::size_t dimensionSize() const;
79  T &at(Dimensions... indices);
80  const T &at(Dimensions... indices) const;
81  T *data();
82  const T *data() const;
83  typename UnderlyingContainer::template Type<T> &buffer();
84 
85 private:
86  using HelperType = Detail::DimensionsHelper<std::tuple<Dimensions...>, dimensionCount()>;
87  const std::tuple<Dimensions...> m_dims;
88  const std::size_t m_size;
89  typename UnderlyingContainer::template Type<T> m_buff;
90 };
91 
95 template <typename T, typename UnderlyingContainer, typename... Dimensions>
97  : m_dims(std::make_tuple(dimensionSizes...))
98  , m_size(HelperType::requiredSize(m_dims))
99  , m_buff(UnderlyingContainer::template init<T>(m_size))
100 {
101 }
102 
104 template <typename T, typename UnderlyingContainer, typename... Dimensions>
106 {
107  return m_size;
108 }
109 
111 template <typename T, typename UnderlyingContainer, typename... Dimensions>
113 {
114  return std::tuple_size<std::tuple<Dimensions...>>::value;
115 }
116 
118 template <typename T, typename UnderlyingContainer, typename... Dimensions>
119 template <std::size_t index>
121 {
122  return std::get<index>(m_dims);
123 }
124 
127 template <typename T, typename UnderlyingContainer, typename... Dimensions>
129 {
130  return m_buff[HelperType::offset(m_dims, std::make_tuple(indices...), 1)];
131 }
132 
135 template <typename T, typename UnderlyingContainer, typename... Dimensions>
136 const T &MultiArray<T, UnderlyingContainer, Dimensions...>::at(Dimensions... indices) const
137 {
138  return m_buff[HelperType::offset(m_dims, std::make_tuple(indices...), 1)];
139 }
140 
143 template <typename T, typename UnderlyingContainer, typename... Dimensions> T *MultiArray<T, UnderlyingContainer, Dimensions...>::data()
144 {
145  return m_buff.data();
146 }
147 
150 template <typename T, typename UnderlyingContainer, typename... Dimensions> const T *MultiArray<T, UnderlyingContainer, Dimensions...>::data() const
151 {
152  return m_buff.data();
153 }
154 
157 template <typename T, typename UnderlyingContainer, typename... Dimensions>
158 typename UnderlyingContainer::template Type<T> &MultiArray<T, UnderlyingContainer, Dimensions...>::buffer()
159 {
160  return m_buff;
161 }
162 
166 template <typename ValueType, typename... DimensionSizes> inline auto makeMultiArray(DimensionSizes... dimensionSizes)
167 {
168  return MultiArray<ValueType, VectorBasedMultiArray<void>, DimensionSizes...>(dimensionSizes...);
169 }
170 
174 template <typename ValueType, std::size_t size, typename... DimensionSizes> inline auto makeFixedSizeMultiArray(DimensionSizes... dimensionSizes)
175 {
176  return MultiArray<ValueType, ArrayBasedMultiArray<size>, DimensionSizes...>(dimensionSizes...);
177 }
178 
182 template <typename ValueType, typename... DimensionSizes> inline auto makeNoneOwningMultiArray(DimensionSizes... dimensionSizes)
183 {
184  return MultiArray<ValueType, NoneOwningMultiArray, DimensionSizes...>(dimensionSizes...);
185 }
186 
187 } // namespace MiscUtilities
188 
189 #endif // CPP_UTILITIES_MULTI_ARRAY_H
std::vector< T, Allocator > Type
Definition: multiarray.h:38
std::array< T, size > Type
Definition: multiarray.h:56
static constexpr Type< T > init(std::size_t requiredSize)
Definition: multiarray.h:48
The NoneOwningMultiArray struct allows using a caller-managed buffer array as underlying container fo...
Definition: multiarray.h:64
UnderlyingContainer::template Type< T > & buffer()
Allows accessing the underlying buffer directly.
Definition: multiarray.h:158
The VectorBasedMultiArray struct allows using an std::vector with custom allocator as underlying cont...
Definition: multiarray.h:37
T * data()
Returns a pointer to the raw data.
Definition: multiarray.h:143
The ArrayBasedMultiArray struct allows using a fixed size array as underlying container for the Multi...
Definition: multiarray.h:55
auto makeNoneOwningMultiArray(DimensionSizes... dimensionSizes)
Constructs a new N-dimensional array using a caller-managed buffer as underlying container....
Definition: multiarray.h:182
static constexpr Type< T > init(std::size_t requiredSize)
Definition: multiarray.h:39
std::size_t totalSize() const
Returns the total number of elements.
Definition: multiarray.h:105
auto makeFixedSizeMultiArray(DimensionSizes... dimensionSizes)
Constructs a new N-dimensional array using a fixed size array as underlying container....
Definition: multiarray.h:174
static constexpr std::size_t dimensionCount()
Returns the number of dimensions for that type of array.
Definition: multiarray.h:112
std::vector< T, std::allocator< T > > Type
Definition: multiarray.h:47
static constexpr Type< T > init(std::size_t)
Definition: multiarray.h:66
std::size_t dimensionSize() const
Returns the number of elements in the specified dimension.
Definition: multiarray.h:120
auto makeMultiArray(DimensionSizes... dimensionSizes)
Constructs a new N-dimensional array using an std::vector with std::allocator as underlying container...
Definition: multiarray.h:166
static constexpr Type< T > init(std::size_t)
Definition: multiarray.h:57
MultiArray(Dimensions... dimensionSizes)
Constructs a new N-dimensional array. The sizes for the dimensions are passed as arguments.
Definition: multiarray.h:96
Contains various utilities such as computing Damerau–Levenshtein distance and N-dimensional arrays.
Definition: multiarray.h:8
The MultiArray class provides an N-dimensional array.
Definition: multiarray.h:73
T & at(Dimensions... indices)
Returns the element at the position specified via indices.
Definition: multiarray.h:128