19 template <
typename T,
typename = std::array<std::
size_t, T::rank>>
25 struct has_shape<T, decltype(T::shape)> : std::true_type
29 template <
typename T, std::
size_t N>
34 template <
typename T, std::
size_t N,
class Allocator = std::allocator<T>>
40 using allocator_type = Allocator;
41 using size_type =
typename std::vector<T, Allocator>::size_type;
42 using reference =
typename std::vector<T, Allocator>::reference;
43 using const_reference =
typename std::vector<T, Allocator>::const_reference;
44 using pointer =
typename std::vector<T, Allocator>::pointer;
45 using iterator =
typename std::vector<T, Allocator>::iterator;
46 using const_iterator =
typename std::vector<T, Allocator>::const_iterator;
54 const Allocator& alloc = Allocator())
58 std::multiplies<size_type>());
59 _storage = std::vector<T, Allocator>(
size, value, alloc);
67 template <std::
size_t _N = N,
typename = std::enable_if_t<_N == 2>>
68 ndarray(size_type rows, size_type cols, value_type value = T(),
69 const Allocator& alloc = Allocator())
72 _storage = std::vector<T, Allocator>(
shape[0] *
shape[1], value, alloc);
76 template <
typename Vector,
77 typename = std::enable_if_t<std::is_class<Vector>::value>>
79 :
shape(
shape), _storage(std::forward<Vector>(x))
87 template <
typename = std::enable_if_t<N == 2>>
88 constexpr
ndarray(std::initializer_list<std::initializer_list<T>> list)
89 :
shape({list.size(), (*list.begin()).
size()})
92 for (std::initializer_list<T> l : list)
94 _storage.push_back(val);
99 template <typename Span, typename = std::enable_if_t<has_shape<Span>::value>>
126 template <std::
size_t _N = N,
typename = std::enable_if_t<_N == 2>>
129 return _storage[i *
shape[1] + j];
138 template <std::
size_t _N = N,
typename = std::enable_if_t<_N == 2>>
139 constexpr const_reference
operator()(size_type i, size_type j)
const
141 return _storage[i *
shape[1] + j];
145 template <std::
size_t _N = N,
typename = std::enable_if_t<_N == 3>>
146 constexpr reference
operator()(size_type i, size_type j, size_type k)
148 return _storage[
shape[2] * (i *
shape[1] + j) + k];
152 template <std::
size_t _N = N,
typename = std::enable_if_t<_N == 3>>
153 constexpr const_reference
operator()(size_type i, size_type j,
156 return _storage[
shape[2] * (i *
shape[1] + j) + k];
162 template <std::
size_t _N = N,
typename = std::enable_if_t<_N == 2>>
163 constexpr tcb::span<value_type>
row(size_type i)
165 return tcb::span<value_type>(std::next(_storage.data(), i *
shape[1]),
172 template <std::
size_t _N = N,
typename = std::enable_if_t<_N == 2>>
173 constexpr tcb::span<const value_type>
row(size_type i)
const
175 return tcb::span<const value_type>(std::next(_storage.data(), i *
shape[1]),
180 template <std::
size_t _N = N,
typename = std::enable_if_t<_N == 3>>
184 std::next(_storage.data(), i *
shape[2] *
shape[1]),
185 {shape[1], shape[2]});
189 template <std::
size_t _N = N,
typename = std::enable_if_t<_N == 3>>
193 std::next(_storage.data(), i *
shape[2] *
shape[1]),
194 {shape[1], shape[2]});
199 constexpr value_type*
data() noexcept {
return _storage.data(); }
204 constexpr
const value_type*
data() const noexcept {
return _storage.data(); };
210 constexpr size_type
size() const noexcept {
return _storage.size(); }
213 template <
int _N = N,
typename = std::enable_if_t<_N == 2>>
214 constexpr std::array<size_type, 2>
strides() const noexcept
216 return {
shape[1] *
sizeof(T),
sizeof(T)};
221 constexpr
bool empty() const noexcept {
return _storage.empty(); }
227 static constexpr size_type
rank = size_type(N);
230 template <
typename Array>
231 friend std::ostream&
operator<<(std::ostream& out,
const Array& array);
234 std::vector<T, Allocator> _storage;
238 template <
typename T, std::
size_t N = 2>
243 using value_type = T;
244 using size_type = std::size_t;
245 using reference = T&;
246 using const_reference =
const T&;
248 using const_pointer =
const T*;
261 template <
typename Array,
262 typename = std::enable_if_t<has_shape<Array>::value>>
273 template <std::
size_t _N = N,
typename = std::enable_if_t<_N == 2>>
276 return _storage[i *
shape[1] + j];
285 template <std::
size_t _N = N,
typename = std::enable_if_t<_N == 2>>
286 constexpr reference
operator()(size_type i, size_type j)
const
288 return _storage[i *
shape[1] + j];
292 template <std::
size_t _N = N,
typename = std::enable_if_t<_N == 3>>
293 constexpr reference
operator()(size_type i, size_type j, size_type k)
295 return _storage[
shape[2] * (i *
shape[1] + j) + k];
299 template <std::
size_t _N = N,
typename = std::enable_if_t<_N == 3>>
300 constexpr const_reference
operator()(size_type i, size_type j,
303 return _storage[
shape[2] * (i *
shape[1] + j) + k];
309 template <std::
size_t _N = N,
typename = std::enable_if_t<_N == 2>>
310 constexpr tcb::span<value_type>
row(size_type i)
312 return tcb::span<value_type>(_storage + i *
shape[1],
shape[1]);
318 template <std::
size_t _N = N,
typename = std::enable_if_t<_N == 2>>
319 constexpr tcb::span<const value_type>
row(size_type i)
const
321 return tcb::span<const value_type>(_storage + i *
shape[1],
shape[1]);
325 template <std::
size_t _N = N,
typename = std::enable_if_t<_N == 3>>
333 template <std::
size_t _N = N,
typename = std::enable_if_t<_N == 3>>
347 constexpr value_type*
data() const noexcept {
return _storage; };
353 template <std::
size_t _N = N,
typename = std::enable_if_t<_N == 2>>
354 constexpr size_type
size() const noexcept
356 return std::accumulate(
shape.begin(),
shape.end(), 1,
357 std::multiplies<size_type>());
361 template <std::
size_t _N = N,
typename = std::enable_if_t<_N == 2>>
362 constexpr std::array<size_type, 2>
strides() const noexcept
364 return {
shape[1] *
sizeof(T),
sizeof(T)};
371 static constexpr size_type
rank = size_type(N);
374 template <
typename Span>
375 friend std::ostream&
operator<<(std::ostream& out,
const Span& array);
382 template <
typename Array>
385 if constexpr (array.rank == 2)
386 for (std::size_t i = 0; i < array.shape[0]; i++)
389 for (std::size_t j = 0; j < array.shape[1]; j++)
390 out << array(i, j) <<
", ";
391 out <<
"}" << std::endl;
394 if constexpr (array.rank == 3)
395 for (std::size_t i = 0; i < array.shape[0]; i++)
397 for (std::size_t j = 0; j < array.shape[1]; j++)
400 for (std::size_t k = 0; k < array.shape[2]; k++)
401 out << array(i, j, k) <<
", ";
402 out <<
"}" << std::endl;
411 template <
typename T, std::
size_t N>
418 template <
typename T, std::
size_t N>
constexpr tcb::span< value_type > row(size_type i)
Definition: ndarray.h:163
constexpr ndspan< value_type, 2 > row(size_type i)
Access a row in the array.
Definition: ndarray.h:181
ndarray & operator=(ndarray &&x)=default
Move assignment.
friend std::ostream & operator<<(std::ostream &out, const Array &array)
Pretty printing, useful for debuging.
ndarray(ndarray &&x)=default
Move constructor.
constexpr reference operator()(size_type i, size_type j)
Definition: ndarray.h:127
ndarray(std::array< size_type, N > shape, value_type value=T(), const Allocator &alloc=Allocator())
Definition: ndarray.h:53
constexpr ndspan< const value_type, 2 > row(size_type i) const
Access a row in the array (const version)
Definition: ndarray.h:190
constexpr const value_type * data() const noexcept
Definition: ndarray.h:204
constexpr ndarray(Span &s)
Definition: ndarray.h:100
constexpr size_type size() const noexcept
Definition: ndarray.h:210
constexpr std::array< size_type, 2 > strides() const noexcept
Returns the strides of the array.
Definition: ndarray.h:214
ndarray(std::array< size_type, N > shape, Vector &&x)
Constructs an n-dimensional array from a vector.
Definition: ndarray.h:78
constexpr const_reference operator()(size_type i, size_type j, size_type k) const
Return a reference to the element at specified location (i, j, k)
Definition: ndarray.h:153
ndarray(const ndarray &x)=default
Copy constructor.
static constexpr size_type rank
The rank of the array.
Definition: ndarray.h:227
constexpr ndarray(std::initializer_list< std::initializer_list< T >> list)
Definition: ndarray.h:88
constexpr value_type * data() noexcept
Definition: ndarray.h:199
constexpr tcb::span< const value_type > row(size_type i) const
Definition: ndarray.h:173
constexpr reference operator()(size_type i, size_type j, size_type k)
Return a reference to the element at specified location (i, j, k)
Definition: ndarray.h:146
constexpr const_reference operator()(size_type i, size_type j) const
Definition: ndarray.h:139
constexpr bool empty() const noexcept
Definition: ndarray.h:221
ndarray(size_type rows, size_type cols, value_type value=T(), const Allocator &alloc=Allocator())
Definition: ndarray.h:68
~ndarray()=default
Destructor.
ndarray & operator=(const ndarray &x)=default
Copy assignment.
std::array< size_type, N > shape
The shape of the array.
Definition: ndarray.h:224
This class provides a view into an n-dimensional row-wise array of data.
Definition: ndarray.h:240
constexpr ndspan< value_type, 2 > row(size_type i)
Access a row in the array.
Definition: ndarray.h:326
constexpr tcb::span< value_type > row(size_type i)
Definition: ndarray.h:310
constexpr value_type * data() const noexcept
Definition: ndarray.h:347
std::array< size_type, N > shape
The shape of the span.
Definition: ndarray.h:368
constexpr ndspan(Array &x)
Construct an n-dimensional span from an n-dimensional array.
Definition: ndarray.h:263
static constexpr size_type rank
The rank of the span.
Definition: ndarray.h:371
constexpr ndspan(T *data, std::array< size_type, N > shape)
Definition: ndarray.h:254
constexpr reference operator()(size_type i, size_type j) const
Definition: ndarray.h:286
constexpr const_reference operator()(size_type i, size_type j, size_type k) const
Return a reference to the element at specified location (i, j, k)
Definition: ndarray.h:300
constexpr tcb::span< const value_type > row(size_type i) const
Definition: ndarray.h:319
constexpr std::array< size_type, 2 > strides() const noexcept
Returns the strides of the span.
Definition: ndarray.h:362
constexpr ndspan< const value_type, 2 > row(size_type i) const
Access a row in the array (const version)
Definition: ndarray.h:334
friend std::ostream & operator<<(std::ostream &out, const Span &array)
Pretty printing, useful for debuging.
constexpr reference operator()(size_type i, size_type j)
Definition: ndarray.h:274
constexpr reference operator()(size_type i, size_type j, size_type k)
Return a reference to the element at specified location (i, j, k)
Definition: ndarray.h:293
constexpr size_type size() const noexcept
Definition: ndarray.h:354
Placeholder.
Definition: basix.h:10
std::ostream & operator<<(std::ostream &out, const ndarray< T, N > &array)
Pretty printing, useful for debuging.
Definition: ndarray.h:412
std::ostream & print_array(std::ostream &out, const Array &array)
Convenience function for outputting arrays.
Definition: ndarray.h:383