Volume Cartographer 2.27.0
NDArray.hpp
Go to the documentation of this file.
1#pragma once
2
5#include <cstddef>
6#include <exception>
7#include <functional>
8#include <iostream>
9#include <iterator>
10#include <numeric>
11#include <vector>
12
13namespace volcart
14{
27template <typename T>
29{
30public:
32 using Container = std::vector<T>;
34 using IndexType = typename Container::size_type;
36 using Extent = std::vector<IndexType>;
38 using Index = std::vector<IndexType>;
40 using iterator = typename Container::iterator;
42 using const_iterator = typename Container::const_iterator;
43
46 explicit NDArray(std::size_t n) : dim_(n) {}
47
49 explicit NDArray(std::size_t n, Extent e) : dim_(n), extents_(std::move(e))
50 {
51 if (extents_.size() != dim_) {
52 throw std::invalid_argument("Extents of wrong dimension");
53 }
54
56 }
57
59 template <typename... Es>
60 explicit NDArray(std::size_t n, Es... extents)
61 : dim_(n), extents_{static_cast<IndexType>(extents)...}
62 {
63 if (sizeof...(extents) != dim_) {
64 throw std::invalid_argument("Extents of wrong dimension");
65 }
67 }
68
70 template <typename InputIt>
71 explicit NDArray(std::size_t n, Extent e, InputIt first, InputIt last)
72 : dim_(n), extents_(std::move(e)), data_{first, last}
73 {
74 if (extents_.size() != dim_) {
75 throw std::invalid_argument("Extents of wrong dimension");
76 }
77
78 auto size = std::accumulate(
79 extents_.begin(), extents_.end(), IndexType(1),
80 std::multiplies<IndexType>());
81
82 if (size != data_.size()) {
83 throw std::invalid_argument(
84 "Array extent does not match size of input data");
85 }
86 }
96 {
97 if (e.size() != dim_) {
98 throw std::invalid_argument("Extents of wrong dimension");
99 }
100
101 extents_ = std::move(e);
103 }
104
106 template <typename... Es>
107 void setExtents(Es... extents)
108 {
109 return setExtents({static_cast<IndexType>(extents)...});
110 }
111
113 auto dims() const -> std::size_t { return dim_; }
114
116 auto extents() const -> Extent { return extents_; }
117
119 auto size() const -> std::size_t { return data_.size(); }
124 auto operator()(Index index) -> T&
125 {
126
127 if (index.size() != dim_) {
128 throw std::invalid_argument("Index of wrong dimension");
129 }
130 return data_.at(index_to_data_index_(index));
131 }
132
134 auto operator()(Index index) const -> const T&
135 {
136 if (index.size() != dim_) {
137 throw std::invalid_argument("Index of wrong dimension");
138 }
139 return data_.at(index_to_data_index_(index));
140 }
141
143 template <typename... Is>
144 auto operator()(Is... indices) -> T&
145 {
146 return operator()(Index{static_cast<IndexType>(indices)...});
147 }
148
150 template <typename... Is>
151 auto operator()(Is... indices) const -> const T&
152 {
153 return operator()(Index{static_cast<IndexType>(indices)...});
154 }
155
157 auto slice(IndexType index) -> NDArray
158 {
159 auto offset = std::accumulate(
160 std::next(extents_.begin(), 1), extents_.end(), IndexType(1),
161 std::multiplies<IndexType>());
162
163 auto b = std::next(data_.begin(), index * offset);
164 auto e = std::next(data_.begin(), (index + 1) * offset);
165
166 Extent newExtent{std::next(extents_.begin(), 1), extents_.end()};
167
168 return NDArray(dim_ - 1, newExtent, b, e);
169 }
174 auto as_vector() -> Container { return data_; }
175
177 auto as_vector() const -> Container { return data_; }
178
180 auto data() -> typename Container::value_type* { return data_.data(); }
181
183 auto data() const -> typename Container::value_type*
184 {
185 return data_.data();
186 }
187
191 auto begin() -> iterator { return std::begin(data_); }
192
194 auto begin() const -> const_iterator { return std::begin(data_); }
195
200 auto end() -> iterator { return std::end(data_); }
201
203 auto end() const -> const_iterator { return std::end(data_); }
204
206 auto front() -> T& { return data_.front(); }
207
209 auto front() const -> const T& { return data_.front(); }
210
212 auto back() -> T& { return data_.back(); }
213
215 auto back() const -> const T& { return data_.back(); }
222 static void Flatten(NDArray& a, std::size_t dim)
223 {
224 if (dim == a.dim_) {
225 return;
226 } else if (dim > a.dim_) {
227 throw std::invalid_argument("Dimension higher than that of array");
228 }
229
230 Extent newExtent;
231
232 auto flattened = std::accumulate(
233 a.extents_.begin(), std::next(a.extents_.begin(), a.dim_ - dim + 1),
234 IndexType(1), std::multiplies<IndexType>());
235 newExtent.push_back(flattened);
236
237 newExtent.insert(
238 newExtent.end(), std::next(a.extents_.begin(), a.dim_ - dim + 1),
239 a.extents_.end());
240
241 a.dim_ = dim;
242 a.extents_ = newExtent;
243 }
244
245private:
247 std::size_t dim_{1};
252
255 {
256 auto size = std::accumulate(
257 extents_.begin(), extents_.end(), IndexType(1),
258 std::multiplies<IndexType>());
259
260 if (size == 0) {
261 throw std::range_error("Array extent is zero");
262 }
263
264 data_.resize(size);
265 }
266
268 inline auto index_to_data_index_(Index i) const -> IndexType
269 {
270 IndexType idx{0};
271 for (std::size_t it = 0; it < extents_.size(); it++) {
272 auto begin = std::next(extents_.begin(), it + 1);
273 auto offset = std::accumulate(
274 begin, extents_.end(), IndexType(1),
275 std::multiplies<IndexType>());
276 idx += i[it] * offset;
277 }
278
279 return idx;
280 }
281};
282} // namespace volcart
Dynamically-allocated N-Dimensional Array.
Definition: NDArray.hpp:29
auto as_vector() -> Container
Return copy of raw data.
Definition: NDArray.hpp:174
NDArray(std::size_t n)
Default constructor.
Definition: NDArray.hpp:46
void resize_container_()
Definition: NDArray.hpp:254
auto end() const -> const_iterator
Return an iterator that points to the past-the-end element in the array.
Definition: NDArray.hpp:203
typename Container::const_iterator const_iterator
Definition: NDArray.hpp:42
auto index_to_data_index_(Index i) const -> IndexType
Definition: NDArray.hpp:268
auto data() -> typename Container::value_type *
Get a pointer to the start of the underlying data.
Definition: NDArray.hpp:180
auto extents() const -> Extent
Get the extent (size) of the array's dimensions.
Definition: NDArray.hpp:116
auto front() -> T &
Return a reference to the first element in the array.
Definition: NDArray.hpp:206
auto front() const -> const T &
Return a reference to the first element in the array.
Definition: NDArray.hpp:209
auto operator()(Index index) -> T &
Per-element access.
Definition: NDArray.hpp:124
auto size() const -> std::size_t
Get the total number of elements in the array.
Definition: NDArray.hpp:119
Container data_
Definition: NDArray.hpp:251
void setExtents(Extent e)
Set the extent of the array's dimensions.
Definition: NDArray.hpp:95
NDArray(std::size_t n, Extent e)
Constructor with dimensions.
Definition: NDArray.hpp:49
std::vector< IndexType > Index
Definition: NDArray.hpp:38
std::vector< IndexType > Extent
Definition: NDArray.hpp:36
typename Container::iterator iterator
Definition: NDArray.hpp:40
auto back() -> T &
Return a reference to the last element in the array.
Definition: NDArray.hpp:212
auto back() const -> const T &
Return a reference to the last element in the array.
Definition: NDArray.hpp:215
std::vector< T > Container
Definition: NDArray.hpp:32
auto begin() -> iterator
Return an iterator that points to the first element in the array.
Definition: NDArray.hpp:191
auto dims() const -> std::size_t
Get the number of dimensions of the array.
Definition: NDArray.hpp:113
auto begin() const -> const_iterator
Return an iterator that points to the first element in the array.
Definition: NDArray.hpp:194
NDArray(std::size_t n, Extent e, InputIt first, InputIt last)
Constructor with range initialization.
Definition: NDArray.hpp:71
auto end() -> iterator
Return an iterator that points to the past-the-end element in the array.
Definition: NDArray.hpp:200
auto slice(IndexType index) -> NDArray
Get slice of array by dropping highest dimension.
Definition: NDArray.hpp:157
static void Flatten(NDArray &a, std::size_t dim)
Flatten an array by dropping a dimension and appending the data to the next highest dimension.
Definition: NDArray.hpp:222
std::size_t dim_
Definition: NDArray.hpp:247
typename Container::size_type IndexType
Definition: NDArray.hpp:34
Volume Cartographer library