Visual Computing Library
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/concepts/ranges/range.h>
27#include <vclib/concepts/space/array.h>
28#include <vclib/io/serialization.h>
29#include <vclib/misc/nested_initializer_lists.h>
30#include <vclib/types.h>
31
32#include <array>
33#include <cassert>
34#include <iomanip>
35#include <utility>
36#include <vector>
37
38namespace vcl {
39
62template<class T, uint N>
63class Array
64{
65 static_assert(N > 0, "Array dimension must be > 0.");
66 friend Array<T, N + 1>;
67
68 std::array<std::size_t, N> mSizes;
69 std::vector<T> mVec;
70
71public:
73 using ValueType = std::vector<T>::value_type;
74
77
81 using ConstReference = std::vector<T>::const_reference;
82
84 using Reference = std::vector<T>::reference;
85
89 using ConstPointer = std::vector<T>::const_pointer;
90
92 using Pointer = std::vector<T>::pointer;
93
95 using Iterator = std::vector<T>::iterator;
96
98 using ConstIterator = std::vector<T>::const_iterator;
99
101 static constexpr uint DIM = N;
102
108 Array() : mVec(0) { mSizes.fill(0); }
109
123 template<typename... Sizes>
124 Array(Sizes... s) requires (sizeof...(s) == N)
125 {
126 std::size_t args[N] = {static_cast<std::size_t>(s)...};
127 std::size_t totalSize = 1;
128 for (uint i = 0; i < N; i++) {
129 mSizes[i] = args[i];
130 totalSize *= args[i];
131 }
132 mVec.resize(totalSize);
133 }
134
158 {
159 initializeNestedLists(values);
160 }
161
167 bool empty() const { return mVec.empty(); }
168
176 std::size_t size(std::size_t dim) const
177 {
178 assert(dim < N);
179 return mSizes[dim];
180 }
181
189 std::size_t rows() const requires (N == 2) { return mSizes[0]; }
190
198 std::size_t cols() const requires (N == 2) { return mSizes[1]; }
199
208 std::size_t sizeX() const requires (N >= 1) { return mSizes[0]; }
209
218 std::size_t sizeY() const requires (N >= 2) { return mSizes[1]; }
219
228 std::size_t sizeZ() const requires (N >= 3) { return mSizes[2]; }
229
238 std::size_t sizeW() const requires (N >= 4) { return mSizes[3]; }
239
252 template<typename... I>
253 Reference operator()(I... indices) requires (sizeof...(indices) == N)
254 {
255 std::size_t args[N] = {static_cast<std::size_t>(indices)...};
256 return mVec[getIndex(args)];
257 }
258
271 template<typename... I>
272 ConstReference operator()(I... indices) const
273 requires (sizeof...(indices) == N)
274 {
275 std::size_t args[N] = {static_cast<std::size_t>(indices)...};
276 return mVec[getIndex(args)];
277 }
278
307 template<typename... I>
308 Pointer data(I... indices) requires (sizeof...(indices) < N)
309 {
310 return const_cast<Pointer>(std::as_const(*this).data(indices...));
311 }
312
341 template<typename... I>
342 ConstPointer data(I... indices) const requires (sizeof...(indices) < N)
343 {
344 constexpr std::size_t n = sizeof...(indices);
345 if constexpr (n == 0) {
346 return mVec.data();
347 }
348 else {
349 std::size_t args[] = {static_cast<std::size_t>(indices)...};
350 std::size_t ind = args[0];
351 assert(args[0] < mSizes[0]);
352 uint i;
353 for (i = 1; i < n; i++) {
354 assert(args[i] < mSizes[i]);
355 ind *= mSizes[i];
356 ind += args[i];
357 }
358 for (; i < N; i++) {
359 ind *= mSizes[i];
360 }
361 return &mVec[ind];
362 }
363 }
364
372 std::vector<T> stdVector() & { return mVec; }
373
381 std::vector<T>&& stdVector() && { return std::move(mVec); }
382
390 const std::vector<T>& stdVector() const& { return mVec; }
391
397 void fill(const T& t) { std::fill(mVec.begin(), mVec.end(), t); }
398
414 template<Range Rng>
415 void fill(Rng&& r)
416 {
417 uint i = 0;
418 for (auto it = std::ranges::begin(r);
419 it != std::ranges::end(r) && i < mVec.size();
420 ++i, ++it) {
421 mVec[i] = *it;
422 }
423 }
424
434 template<typename... Sizes>
435 void resize(Sizes... s) requires (sizeof...(s) == N)
436 {
437 std::size_t args[N] = {static_cast<std::size_t>(s)...};
438 std::size_t totalSize = 1;
439 for (uint i = 0; i < N; i++) {
440 mSizes[i] = args[i];
441 totalSize *= args[i];
442 }
443 mVec.resize(totalSize);
444 }
445
459 template<typename... Sizes>
460 void conservativeResize(Sizes... s) requires (sizeof...(s) == N)
461 {
462 std::size_t newSizes[N] = {static_cast<std::size_t>(s)...};
463 std::size_t newTotalSize = 1;
464 for (uint i = 0; i < N; i++)
466 std::vector<T> newVector(newTotalSize);
467
468 for (std::size_t i = 0; i < mVec.size(); i++) {
469 std::array<std::size_t, N> indices = reverseIndex(i);
470 bool outOfBound = false;
471 for (std::size_t j = 0; j < N; j++)
472 if (indices[j] >= newSizes[j] || indices[j] >= mSizes[j])
473 outOfBound = true;
474 if (!outOfBound) {
475 newVector[getIndex(indices.data(), newSizes)] = mVec[i];
476 }
477 }
478
479 for (uint i = 0; i < mSizes.size(); i++) {
480 mSizes[i] = newSizes[i];
481 }
482
483 mVec = std::move(newVector);
484 }
485
489 void clear()
490 {
491 mVec.clear();
492 for (uint i = 0; i < N; i++)
493 mSizes[i] = 0;
494 }
495
519 Array<T, N - 1> subArray(uint r) const requires (N > 1)
520 {
521 assert(r < mSizes[0]);
522 Array<T, N - 1> sub;
523 size_t size = 1;
524 for (uint i = 0; i < mSizes.size() - 1; i++) {
525 sub.mSizes[i] = mSizes[i + 1];
526 size *= sub.mSizes[i];
527 }
528 sub.mVec = std::vector<T>(
529 mVec.begin() + r * size, mVec.begin() + (r + 1) * size);
530 return sub;
531 }
532
533 void serialize(std::ostream& os) const
534 {
535 vcl::serialize(os, mSizes);
536 vcl::serialize(os, mVec);
537 }
538
539 void deserialize(std::istream& is)
540 {
541 vcl::deserialize(is, mSizes);
542 vcl::deserialize(is, mVec);
543 }
544
550 Iterator begin() { return mVec.begin(); }
551
557 Iterator end() { return mVec.end(); }
558
564 ConstIterator begin() const { return mVec.begin(); }
565
571 ConstIterator end() const { return mVec.end(); }
572
574 template<typename S>
575 friend std::ostream& operator<<(std::ostream& out, const Array<S, 2>& a);
576
577private:
578 std::size_t getIndex(const std::size_t indices[]) const
579 {
580 std::size_t ind = indices[0];
581 assert(indices[0] < mSizes[0]);
582 for (uint i = 1; i < N; i++) {
583 assert(indices[i] < mSizes[i]);
584 ind *= mSizes[i];
585 ind += indices[i];
586 }
587 return ind;
588 }
589
590 std::array<std::size_t, N> reverseIndex(uint index)
591 {
592 std::array<std::size_t, N> indices;
593 for (long int i = N - 1; i >= 0; i--) {
594 indices[i] = index % mSizes[i];
595 index /= mSizes[i];
596 }
597 return indices;
598 }
599
600 static std::size_t getIndex(
601 const std::size_t indices[],
602 const std::size_t sizes[])
603 {
604 std::size_t ind = indices[0];
605 assert(indices[0] < sizes[0]);
606 for (uint i = 1; i < N; i++) {
607 assert(indices[i] < sizes[i]);
608 ind *= sizes[i];
609 ind += indices[i];
610 }
611 return ind;
612 }
613
614 void initializeNestedLists(NestedInitializerLists<T, N> values)
615 {
616 std::list<std::size_t> szs =
618
619 uint i = 0;
620 size_t totalSize = 1;
621 for (std::size_t s : szs) {
622 totalSize *= s;
623 mSizes[i++] = s;
624 }
625 mVec.resize(totalSize);
626
627 typename std::vector<T>::iterator iterator = mVec.begin();
629 values,
630 [&iterator](T value) {
631 *(iterator++) = value;
632 },
633 szs);
634 }
635};
636
637template<typename Scalar>
638std::ostream& operator<<(std::ostream& out, const Array<Scalar, 2>& a)
639{
640 for (uint i = 0; i < a.sizeX(); i++) {
641 for (uint j = 0; j < a.sizeY(); j++) {
642 out << std::setw(4) << a(i, j) << " ";
643 }
644 out << std::endl;
645 }
646 return out;
647}
648
649/* Specialization Aliases */
650
661template<typename Scalar>
663
674template<typename Scalar>
676
687template<typename Scalar>
689
690} // namespace vcl
691
692#endif // VCL_SPACE_CORE_ARRAY_H
The Array class is a dynamically allocated N-dimensional array stored in RowWise mode.
Definition array.h:64
std::vector< T > stdVector() &
Returns a std::vector containing the elements of the array in row-major order.
Definition array.h:372
Array()
Default constructor for the Array class.
Definition array.h:108
std::vector< T >::const_pointer ConstPointer
A const pointer to the type of the elements stored in the array.
Definition array.h:89
ConstIterator end() const
Returns a const iterator to the end of the array.
Definition array.h:571
std::size_t sizeZ() const
Returns the size of the Z dimension of the array.
Definition array.h:228
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:253
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:272
Iterator end()
Returns an iterator to the end of the array.
Definition array.h:557
std::size_t size(std::size_t dim) const
Returns the size of the given dimension.
Definition array.h:176
ValueType Scalar
Same of ValueType, just for compatibility with Eigen Matrices.
Definition array.h:76
Pointer data(I... indices)
Allows to get the data of the Array, through a pointer to the first element.
Definition array.h:308
Iterator begin()
Returns an iterator to the beginning of the array.
Definition array.h:550
std::vector< T >::const_reference ConstReference
A const reference to the type of the elements stored in the array.
Definition array.h:81
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:519
void resize(Sizes... s)
Allows to resize the Array, not conserving the values of the previous array.
Definition array.h:435
void fill(const T &t)
Fills the entire Array with the value t.
Definition array.h:397
std::size_t cols() const
Returns the number of columns of a 2-dimensional array.
Definition array.h:198
static constexpr uint DIM
The number of dimensions of the array.
Definition array.h:101
std::vector< T > && stdVector() &&
Returns a std::vector containing the elements of the array in row-major order.
Definition array.h:381
std::size_t rows() const
Returns the number of rows of a 2-dimensional array.
Definition array.h:189
std::vector< T >::iterator Iterator
An iterator to the elements of the array.
Definition array.h:95
std::vector< T >::value_type ValueType
The type of the elements stored in the array.
Definition array.h:73
void fill(Rng &&r)
Fills the entire Array with the values contained in the range r, in row-major order.
Definition array.h:415
std::size_t sizeW() const
Returns the size of the W dimension of the array.
Definition array.h:238
std::size_t sizeY() const
Returns the size of the Y dimension of the array.
Definition array.h:218
std::vector< T >::pointer Pointer
A pointer to the type of the elements stored in the array.
Definition array.h:92
bool empty() const
Checks whether the array is empty.
Definition array.h:167
void conservativeResize(Sizes... s)
Allows to resize the Array, conserving the values of the previous array.
Definition array.h:460
std::size_t sizeX() const
Returns the size of the X dimension of the array.
Definition array.h:208
ConstPointer data(I... indices) const
Allows to get the data of the Array, through a pointer to the first element.
Definition array.h:342
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:157
std::vector< T >::const_iterator ConstIterator
A const iterator to the elements of the array.
Definition array.h:98
Array(Sizes... s)
Constructor for the Array class that creates an N-dimensional array with the given sizes....
Definition array.h:124
ConstIterator begin() const
Returns a const iterator to the beginning of the array.
Definition array.h:564
void clear()
Clear the entire array, setting every dimension to size 0.
Definition array.h:489
std::vector< T >::reference Reference
A reference to the type of the elements stored in the array.
Definition array.h:84
const std::vector< T > & stdVector() const &
Returns a std::vector containing the elements of the array in row-major order.
Definition array.h:390
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 class representing a line segment in n-dimensional space. The class is parameterized by a PointConc...
Definition segment.h:43