Visual Computing Library  devel
Loading...
Searching...
No Matches
array.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_SPACE_CORE_ARRAY_H
24#define VCL_SPACE_CORE_ARRAY_H
25
26#include <vclib/base.h>
27
28#include <array>
29#include <cassert>
30#include <iomanip>
31#include <utility>
32#include <vector>
33
34namespace vcl {
35
58template<class T, uint N>
59class Array
60{
61 static_assert(N > 0, "Array dimension must be > 0.");
62 friend Array<T, N + 1>;
63
64 std::array<std::size_t, N> mSizes;
65 std::vector<T> mVec;
66
67public:
69 using ValueType = std::vector<T>::value_type;
70
73
77 using ConstReference = std::vector<T>::const_reference;
78
80 using Reference = std::vector<T>::reference;
81
85 using ConstPointer = std::vector<T>::const_pointer;
86
88 using Pointer = std::vector<T>::pointer;
89
91 using Iterator = std::vector<T>::iterator;
92
94 using ConstIterator = std::vector<T>::const_iterator;
95
97 static constexpr uint DIM = N;
98
104 Array() : mVec(0) { mSizes.fill(0); }
105
119 template<typename... Sizes>
120 Array(Sizes... s) requires (sizeof...(s) == N)
121 {
122 std::size_t args[N] = {static_cast<std::size_t>(s)...};
123 std::size_t totalSize = 1;
124 for (uint i = 0; i < N; i++) {
125 mSizes[i] = args[i];
126 totalSize *= args[i];
127 }
128 mVec.resize(totalSize);
129 }
130
154 {
155 initializeNestedLists(values);
156 }
157
163 bool empty() const { return mVec.empty(); }
164
172 std::size_t size(std::size_t dim) const
173 {
174 assert(dim < N);
175 return mSizes[dim];
176 }
177
185 std::size_t rows() const requires (N == 2) { return mSizes[0]; }
186
194 std::size_t cols() const requires (N == 2) { return mSizes[1]; }
195
204 std::size_t sizeX() const requires (N >= 1) { return mSizes[0]; }
205
214 std::size_t sizeY() const requires (N >= 2) { return mSizes[1]; }
215
224 std::size_t sizeZ() const requires (N >= 3) { return mSizes[2]; }
225
234 std::size_t sizeW() const requires (N >= 4) { return mSizes[3]; }
235
248 template<typename... I>
249 Reference operator()(I... indices) requires (sizeof...(indices) == N)
250 {
251 std::size_t args[N] = {static_cast<std::size_t>(indices)...};
252 return mVec[getIndex(args)];
253 }
254
267 template<typename... I>
268 ConstReference operator()(I... indices) const
269 requires (sizeof...(indices) == N)
270 {
271 std::size_t args[N] = {static_cast<std::size_t>(indices)...};
272 return mVec[getIndex(args)];
273 }
274
303 template<typename... I>
304 Pointer data(I... indices) requires (sizeof...(indices) < N)
305 {
306 return const_cast<Pointer>(std::as_const(*this).data(indices...));
307 }
308
337 template<typename... I>
338 ConstPointer data(I... indices) const requires (sizeof...(indices) < N)
339 {
340 constexpr std::size_t n = sizeof...(indices);
341 if constexpr (n == 0) {
342 return mVec.data();
343 }
344 else {
345 std::size_t args[] = {static_cast<std::size_t>(indices)...};
346 std::size_t ind = args[0];
347 assert(args[0] < mSizes[0]);
348 uint i;
349 for (i = 1; i < n; i++) {
350 assert(args[i] < mSizes[i]);
351 ind *= mSizes[i];
352 ind += args[i];
353 }
354 for (; i < N; i++) {
355 ind *= mSizes[i];
356 }
357 return &mVec[ind];
358 }
359 }
360
368 std::vector<T> stdVector() & { return mVec; }
369
377 std::vector<T>&& stdVector() && { return std::move(mVec); }
378
386 const std::vector<T>& stdVector() const& { return mVec; }
387
393 void fill(const T& t) { std::fill(mVec.begin(), mVec.end(), t); }
394
410 template<Range Rng>
411 void fill(Rng&& r)
412 {
413 uint i = 0;
414 for (auto it = std::ranges::begin(r);
415 it != std::ranges::end(r) && i < mVec.size();
416 ++i, ++it) {
417 mVec[i] = *it;
418 }
419 }
420
430 template<typename... Sizes>
431 void resize(Sizes... s) requires (sizeof...(s) == N)
432 {
433 std::size_t args[N] = {static_cast<std::size_t>(s)...};
434 std::size_t totalSize = 1;
435 for (uint i = 0; i < N; i++) {
436 mSizes[i] = args[i];
437 totalSize *= args[i];
438 }
439 mVec.resize(totalSize);
440 }
441
455 template<typename... Sizes>
456 void conservativeResize(Sizes... s) requires (sizeof...(s) == N)
457 {
458 std::size_t newSizes[N] = {static_cast<std::size_t>(s)...};
459 std::size_t newTotalSize = 1;
460 for (uint i = 0; i < N; i++)
462 std::vector<T> newVector(newTotalSize);
463
464 for (std::size_t i = 0; i < mVec.size(); i++) {
465 std::array<std::size_t, N> indices = reverseIndex(i);
466 bool outOfBound = false;
467 for (std::size_t j = 0; j < N; j++)
468 if (indices[j] >= newSizes[j] || indices[j] >= mSizes[j])
469 outOfBound = true;
470 if (!outOfBound) {
471 newVector[getIndex(indices.data(), newSizes)] = mVec[i];
472 }
473 }
474
475 for (uint i = 0; i < mSizes.size(); i++) {
476 mSizes[i] = newSizes[i];
477 }
478
479 mVec = std::move(newVector);
480 }
481
485 void clear()
486 {
487 mVec.clear();
488 for (uint i = 0; i < N; i++)
489 mSizes[i] = 0;
490 }
491
515 Array<T, N - 1> subArray(uint r) const requires (N > 1)
516 {
517 assert(r < mSizes[0]);
518 Array<T, N - 1> sub;
519 size_t size = 1;
520 for (uint i = 0; i < mSizes.size() - 1; i++) {
521 sub.mSizes[i] = mSizes[i + 1];
522 size *= sub.mSizes[i];
523 }
524 sub.mVec = std::vector<T>(
525 mVec.begin() + r * size, mVec.begin() + (r + 1) * size);
526 return sub;
527 }
528
529 void serialize(std::ostream& os) const
530 {
531 vcl::serialize(os, mSizes);
532 vcl::serialize(os, mVec);
533 }
534
535 void deserialize(std::istream& is)
536 {
537 vcl::deserialize(is, mSizes);
538 vcl::deserialize(is, mVec);
539 }
540
546 Iterator begin() { return mVec.begin(); }
547
553 Iterator end() { return mVec.end(); }
554
560 ConstIterator begin() const { return mVec.begin(); }
561
567 ConstIterator end() const { return mVec.end(); }
568
570 template<typename S>
571 friend std::ostream& operator<<(std::ostream& out, const Array<S, 2>& a);
572
573private:
574 std::size_t getIndex(const std::size_t indices[]) const
575 {
576 std::size_t ind = indices[0];
577 assert(indices[0] < mSizes[0]);
578 for (uint i = 1; i < N; i++) {
579 assert(indices[i] < mSizes[i]);
580 ind *= mSizes[i];
581 ind += indices[i];
582 }
583 return ind;
584 }
585
586 std::array<std::size_t, N> reverseIndex(uint index)
587 {
588 std::array<std::size_t, N> indices;
589 for (long int i = N - 1; i >= 0; i--) {
590 indices[i] = index % mSizes[i];
591 index /= mSizes[i];
592 }
593 return indices;
594 }
595
596 static std::size_t getIndex(
597 const std::size_t indices[],
598 const std::size_t sizes[])
599 {
600 std::size_t ind = indices[0];
601 assert(indices[0] < sizes[0]);
602 for (uint i = 1; i < N; i++) {
603 assert(indices[i] < sizes[i]);
604 ind *= sizes[i];
605 ind += indices[i];
606 }
607 return ind;
608 }
609
610 void initializeNestedLists(NestedInitializerLists<T, N> values)
611 {
612 std::list<std::size_t> szs =
614
615 uint i = 0;
616 size_t totalSize = 1;
617 for (std::size_t s : szs) {
618 totalSize *= s;
619 mSizes[i++] = s;
620 }
621 mVec.resize(totalSize);
622
623 typename std::vector<T>::iterator iterator = mVec.begin();
625 values,
626 [&iterator](T value) {
627 *(iterator++) = value;
628 },
629 szs);
630 }
631};
632
633template<typename Scalar>
634std::ostream& operator<<(std::ostream& out, const Array<Scalar, 2>& a)
635{
636 for (uint i = 0; i < a.sizeX(); i++) {
637 for (uint j = 0; j < a.sizeY(); j++) {
638 out << std::setw(4) << a(i, j) << " ";
639 }
640 out << std::endl;
641 }
642 return out;
643}
644
645/* Specialization Aliases */
646
657template<typename Scalar>
659
670template<typename Scalar>
672
683template<typename Scalar>
685
686/* Concepts */
687
698template<typename T>
699concept ArrayConcept = std::derived_from< // same type or derived type
700 std::remove_cvref_t<T>,
701 Array<typename RemoveRef<T>::ValueType, RemoveRef<T>::DIM>>;
702
713template<typename T>
714concept Array2Concept = ArrayConcept<T> && RemoveRef<T>::DIM == 2;
715
726template<typename T>
727concept Array3Concept = ArrayConcept<T> && RemoveRef<T>::DIM == 3;
728
739template<typename T>
740concept Array4Concept = ArrayConcept<T> && RemoveRef<T>::DIM == 4;
741
742} // namespace vcl
743
744#endif // VCL_SPACE_CORE_ARRAY_H
The Array class is a dynamically allocated N-dimensional array stored in RowWise mode.
Definition array.h:60
std::vector< T > stdVector() &
Returns a std::vector containing the elements of the array in row-major order.
Definition array.h:368
Array()
Default constructor for the Array class.
Definition array.h:104
std::vector< T >::const_pointer ConstPointer
A const pointer to the type of the elements stored in the array.
Definition array.h:85
ConstIterator end() const
Returns a const iterator to the end of the array.
Definition array.h:567
std::size_t sizeZ() const
Returns the size of the Z dimension of the array.
Definition array.h:224
Reference operator()(I... indices)
Operator () that allows to access one element of the array. It can be used as left or right value.
Definition array.h:249
ConstReference operator()(I... indices) const
Operator () that allows to access one element of the array. It can be used only as right value.
Definition array.h:268
Iterator end()
Returns an iterator to the end of the array.
Definition array.h:553
std::size_t size(std::size_t dim) const
Returns the size of the given dimension.
Definition array.h:172
ValueType Scalar
Same of ValueType, just for compatibility with Eigen Matrices.
Definition array.h:72
Pointer data(I... indices)
Allows to get the data of the Array, through a pointer to the first element.
Definition array.h:304
Iterator begin()
Returns an iterator to the beginning of the array.
Definition array.h:546
std::vector< T >::const_reference ConstReference
A const reference to the type of the elements stored in the array.
Definition array.h:77
Array< T, N - 1 > subArray(uint r) const
Creates a new subArray of dimension N-1, starting from the given index at its first dimension.
Definition array.h:515
void resize(Sizes... s)
Allows to resize the Array, not conserving the values of the previous array.
Definition array.h:431
void fill(const T &t)
Fills the entire Array with the value t.
Definition array.h:393
std::size_t cols() const
Returns the number of columns of a 2-dimensional array.
Definition array.h:194
static constexpr uint DIM
The number of dimensions of the array.
Definition array.h:97
std::vector< T > && stdVector() &&
Returns a std::vector containing the elements of the array in row-major order.
Definition array.h:377
std::size_t rows() const
Returns the number of rows of a 2-dimensional array.
Definition array.h:185
std::vector< T >::iterator Iterator
An iterator to the elements of the array.
Definition array.h:91
std::vector< T >::value_type ValueType
The type of the elements stored in the array.
Definition array.h:69
void fill(Rng &&r)
Fills the entire Array with the values contained in the range r, in row-major order.
Definition array.h:411
std::size_t sizeW() const
Returns the size of the W dimension of the array.
Definition array.h:234
std::size_t sizeY() const
Returns the size of the Y dimension of the array.
Definition array.h:214
std::vector< T >::pointer Pointer
A pointer to the type of the elements stored in the array.
Definition array.h:88
bool empty() const
Checks whether the array is empty.
Definition array.h:163
void conservativeResize(Sizes... s)
Allows to resize the Array, conserving the values of the previous array.
Definition array.h:456
std::size_t sizeX() const
Returns the size of the X dimension of the array.
Definition array.h:204
ConstPointer data(I... indices) const
Allows to get the data of the Array, through a pointer to the first element.
Definition array.h:338
Array(NestedInitializerLists< T, N > values)
Creates and initializes an N-dimensional array. Sizes are given by the maximum size of the initialize...
Definition array.h:153
std::vector< T >::const_iterator ConstIterator
A const iterator to the elements of the array.
Definition array.h:94
Array(Sizes... s)
Constructor for the Array class that creates an N-dimensional array with the given sizes....
Definition array.h:120
ConstIterator begin() const
Returns a const iterator to the beginning of the array.
Definition array.h:560
void clear()
Clear the entire array, setting every dimension to size 0.
Definition array.h:485
std::vector< T >::reference Reference
A reference to the type of the elements stored in the array.
Definition array.h:80
const std::vector< T > & stdVector() const &
Returns a std::vector containing the elements of the array in row-major order.
Definition array.h:386
A class representing a box in N-dimensional space.
Definition box.h:46
PointT size() const
Computes the size of the box.
Definition box.h:267
static std::list< size_t > maxDimensionsLevels(NestedInitializerLists< T, L > values)
Returns a list containing the maximum size of elements for every dimension.
Definition nested_initializer_lists.h:103
static void processElements(NestedInitializerLists< T, L > values, T_Function function)
Applies the lambda function passed as parameter to all the elements of the NestedInitializerLists.
Definition nested_initializer_lists.h:155
A concept representing a 2-dimensional array.
Definition array.h:714
A concept representing a 3-dimensional array.
Definition array.h:727
A concept representing a 4-dimensional array.
Definition array.h:740
A concept representing a generic N-dimensional array.
Definition array.h:699