2 #ifndef SYDEVS_ARRAYND_H_
3 #define SYDEVS_ARRAYND_H_
186 template<
typename T,
int64 ndims>
210 arraynd(
const std::array<int64, ndims>&
dims,
const T& value);
229 arraynd(
const std::array<int64, ndims>&
dims,
const std::vector<T>&
data);
245 arraynd(
const std::array<int64, ndims>&
dims, std::function<T(
const std::array<int64, ndims>& indices)> func);
304 arraynd(
const std::array<int64, 1>&
dims,
const T& value);
335 arraynd(
const std::array<int64, 1>&
dims, std::function<T(
const std::array<int64, 1>& indices)> func);
379 template<
typename T,
int64 ndims>
386 template<
typename T,
int64 ndims>
393 template<
typename T,
int64 ndims>
400 template<
typename T,
int64 ndims>
407 template<
typename T,
int64 ndims>
410 return arraynd<T, ndims-1>(*
this, index,
true);
414 template<
typename T,
int64 ndims>
417 return arraynd<T, ndims-1>(*
this, index, this->is_readonly());
421 template<
typename T,
int64 ndims>
428 template<
typename T,
int64 ndims>
435 template<
typename T,
int64 ndims>
442 template<
typename T,
int64 ndims>
449 template<
typename T,
int64 ndims>
456 template<
typename T,
int64 ndims>
460 this->transpose(arr);
465 template<
typename T,
int64 ndims>
469 this->transpose(arr);
474 template<
typename T,
int64 ndims>
478 this->transpose(arr);
483 template<
typename T,
int64 ndims>
487 this->swap_axes(arr, idim0, idim1);
492 template<
typename T,
int64 ndims>
496 this->swap_axes(arr, idim0, idim1);
501 template<
typename T,
int64 ndims>
505 this->swap_axes(arr, idim0, idim1);
510 template<
typename T,
int64 ndims>
514 this->subdivide_axis(*
this, arr, idim, dims);
519 template<
typename T,
int64 ndims>
523 this->subdivide_axis(*
this, arr, idim, dims);
528 template<
typename T,
int64 ndims>
532 return arr0.view_subdivided_axis(idim, dims);
536 template<
typename T,
int64 ndims>
539 auto arr =
arraynd<T, ndims - 1>(std::array<
int64, ndims - 1>(), std::vector<T>());
540 this->absorb_axis(*
this, arr, idim);
545 template<
typename T,
int64 ndims>
548 auto arr =
arraynd<T, ndims - 1>(std::array<
int64, ndims - 1>(), std::vector<T>());
549 this->absorb_axis(*
this, arr, idim);
554 template<
typename T,
int64 ndims>
558 return arr0.view_absorbed_axis(idim);
562 template<
typename T,
int64 ndims>
569 template<
typename T,
int64 ndims>
571 : arraynd_base<T, ndims>(rhs, r, readonly)
576 template<
typename T,
int64 ndims>
578 : arraynd_base<T, ndims>(rhs, is_view, readonly)
623 if (this->
is_readonly())
throw std::logic_error(
"Attempt to obtain a non-const reference to readonly multidimensional array data");
685 return arr0.view_subdivided_axis(idim, dims);
698 : arraynd_base<T, 1>(rhs, r, readonly)
705 : arraynd_base<T, 1>(rhs, is_view, readonly)
712 template<
typename T,
int64 ndims>
716 for (
int64 idim = 0; okay && idim < ndims; ++idim) {
717 okay = (lhs.
dims()[idim] == rhs.
dims()[idim]);
723 template<
typename T,
int64 ndims>
730 template<
typename T,
int64 ndims>
734 return -rhs(indices);
739 template<
typename T,
int64 ndims>
742 if (!
aligned(lhs, rhs))
throw std::domain_error(
"Attempt to apply + operator to multidimensional arrays with inconsistent dimensions");
744 return lhs(indices) + rhs(indices);
749 template<
typename T,
int64 ndims,
typename U>
753 return lhs(indices) + rhs;
758 template<
typename T,
int64 ndims,
typename U>
762 return lhs + rhs(indices);
767 template<
typename T,
int64 ndims>
770 if (!
aligned(lhs, rhs))
throw std::domain_error(
"Attempt to apply - operator to multidimensional arrays with inconsistent dimensions");
772 return lhs(indices) - rhs(indices);
777 template<
typename T,
int64 ndims,
typename U>
781 return lhs(indices) - rhs;
786 template<
typename T,
int64 ndims,
typename U>
790 return lhs - rhs(indices);
795 template<
typename T,
int64 ndims>
798 if (!
aligned(lhs, rhs))
throw std::domain_error(
"Attempt to apply * operator to multidimensional arrays with inconsistent dimensions");
800 return lhs(indices)*rhs(indices);
805 template<
typename T,
int64 ndims,
typename U>
809 return lhs(indices)*rhs;
814 template<
typename T,
int64 ndims,
typename U>
818 return lhs*rhs(indices);
823 template<
typename T,
int64 ndims>
826 if (!
aligned(lhs, rhs))
throw std::domain_error(
"Attempt to apply / operator to multidimensional arrays with inconsistent dimensions");
828 return lhs(indices)/rhs(indices);
833 template<
typename T,
int64 ndims,
typename U>
837 return lhs(indices)/rhs;
842 template<
typename T,
int64 ndims,
typename U>
846 return lhs/rhs(indices);
851 template<
int64 ndims>
855 return !arr(indices);
863 template<
int64 ndims>
866 bool conjunction =
true;
867 arr.
traverse([&conjunction](
const std::array<int64, ndims>& indices,
const bool& value) {
868 conjunction = (conjunction && value);
878 template<
int64 ndims>
881 bool disjunction =
false;
882 arr.
traverse([&disjunction](
const std::array<int64, ndims>& indices,
const bool& value) {
883 disjunction = (disjunction || value);
890 template<
typename T,
int64 ndims>
893 if (!
aligned(lhs, rhs))
throw std::domain_error(
"Attempt to apply < operator to multidimensional arrays with inconsistent dimensions");
895 return lhs(indices) < rhs(indices);
900 template<
typename T,
int64 ndims>
903 if (!
aligned(lhs, rhs))
throw std::domain_error(
"Attempt to apply > operator to multidimensional arrays with inconsistent dimensions");
905 return lhs(indices) > rhs(indices);
910 template<
typename T,
int64 ndims>
913 if (!
aligned(lhs, rhs))
throw std::domain_error(
"Attempt to apply <= operator to multidimensional arrays with inconsistent dimensions");
915 return lhs(indices) <= rhs(indices);
920 template<
typename T,
int64 ndims>
923 if (!
aligned(lhs, rhs))
throw std::domain_error(
"Attempt to apply >= operator to multidimensional arrays with inconsistent dimensions");
925 return lhs(indices) >= rhs(indices);
930 template<
typename T,
int64 ndims>
933 if (!
aligned(lhs, rhs))
throw std::domain_error(
"Attempt to apply == operator to multidimensional arrays with inconsistent dimensions");
935 return lhs(indices) == rhs(indices);
940 template<
typename T,
int64 ndims>
943 if (!
aligned(lhs, rhs))
throw std::domain_error(
"Attempt to apply != operator to multidimensional arrays with inconsistent dimensions");
945 return lhs(indices) != rhs(indices);
950 template<
int64 ndims>
953 if (!
aligned(lhs, rhs))
throw std::domain_error(
"Attempt to apply && operator to multidimensional arrays with inconsistent dimensions");
955 return lhs(indices) && rhs(indices);
960 template<
int64 ndims>
963 if (!
aligned(lhs, rhs))
throw std::domain_error(
"Attempt to apply || operator to multidimensional arrays with inconsistent dimensions");
965 return lhs(indices) || rhs(indices);
970 template<
typename T,
int64 ndims,
typename U>
974 return lhs(indices) < rhs;
979 template<
typename T,
int64 ndims,
typename U>
983 return lhs(indices) > rhs;
988 template<
typename T,
int64 ndims,
typename U>
992 return lhs(indices) <= rhs;
997 template<
typename T,
int64 ndims,
typename U>
1001 return lhs(indices) >= rhs;
1006 template<
typename T,
int64 ndims,
typename U>
1010 return lhs(indices) == rhs;
1015 template<
typename T,
int64 ndims,
typename U>
1019 return lhs(indices) != rhs;
1024 template<
int64 ndims>
1028 return lhs(indices) && rhs;
1033 template<
int64 ndims>
1037 return lhs(indices) || rhs;
1042 template<
typename T,
int64 ndims,
typename U>
1045 return arraynd<bool, ndims>(rhs.dims(), [&lhs, &rhs](
const std::array<int64, ndims>& indices) {
1046 return lhs < rhs(indices);
1051 template<
typename T,
int64 ndims,
typename U>
1055 return lhs > rhs(indices);
1060 template<
typename T,
int64 ndims,
typename U>
1063 return arraynd<bool, ndims>(rhs.dims(), [&lhs, &rhs](
const std::array<int64, ndims>& indices) {
1064 return lhs <= rhs(indices);
1069 template<
typename T,
int64 ndims,
typename U>
1073 return lhs >= rhs(indices);
1078 template<
typename T,
int64 ndims,
typename U>
1082 return lhs == rhs(indices);
1087 template<
typename T,
int64 ndims,
typename U>
1091 return lhs != rhs(indices);
1096 template<
int64 ndims>
1100 return lhs && rhs(indices);
1105 template<
int64 ndims>
1109 return lhs || rhs(indices);
1118 template<
typename T,
int64 ndims,
typename U>
1122 return static_cast<T
>(arr(indices));
1131 template<
typename T,
int64 ndims,
typename U>
1134 return arraynd<T, ndims>(lhs.
dims(), [&lhs, &selection, &rhs](
const std::array<int64, ndims>& indices) {
1135 return selection(indices) ? rhs : lhs(indices);
1145 template<
typename T,
int64 ndims,
typename U>
1148 if (!
aligned(lhs, rhs))
throw std::domain_error(
"Attempt to replace values using multidimensional arrays with inconsistent dimensions");
1149 return arraynd<T, ndims>(lhs.
dims(), [&lhs, &selection, &rhs](
const std::array<int64, ndims>& indices) {
1150 return selection(indices) ? rhs(indices) : lhs(indices);
1155 template<
typename T,
int64 ndims>
1156 std::ostream& operator<<(std::ostream& os, const arraynd<T, ndims>& rhs)
1158 auto indices = std::array<int64, ndims>();
1159 for (
int64 idim = 0; idim < ndims; ++idim) {
1166 if (indices[idim] < rhs.dims()[idim]) {
1169 if (indices[idim] > 0) {
1174 if (idim == ndims - 1) {
1177 os << rhs.data()[offset];
1179 offset += rhs.strides()[idim];
1192 offset -= rhs.dims()[idim]*rhs.strides()[idim];
1196 offset += rhs.strides()[idim];
1215 template<
typename T>
1219 return std::lexicographical_compare(lhs.
data(), lhs.
data() + lhs.
size(),
arraynd< bool, ndims > operator==(const arraynd< T, ndims > &lhs, const arraynd< T, ndims > &rhs)
Definition: arraynd.h:931
arraynd< T, ndims > operator+(const arraynd< T, ndims > &rhs)
Definition: arraynd.h:724
bool is_readonly() const
Returns true if the data is readonly, in which case attempts to modify it raise a std::logic_error...
Definition: arraynd_base.h:280
A data type which represents a range of array indices along a single dimension.
Definition: range.h:51
std::array< int64, ndims > dims() const
Returns the lengths of each dimension.
Definition: arraynd_base.h:197
bool is_view() const
Returns true if this multidimensional array is a view of another, meaning that data is shared...
Definition: arraynd_base.h:272
std::array< int64, ndims > strides() const
Returns the number of element-size steps in memory between successive elements for each dimension...
Definition: arraynd_base.h:205
bool aligned(const arraynd< T, ndims > &lhs, const arraynd< T, ndims > &rhs)
Definition: arraynd.h:713
const T * data() const
Returns a pointer to the element data (const).
Definition: arraynd_base.h:237
arraynd< T, ndims > copy_swapped_axes(int64 idim0, int64 idim1) const
Create a deep copy with dimensions idim0 and idim1 swapped (data is copied).
Definition: arraynd.h:502
bool traverse(std::function< bool(const std::array< int64, ndims > &indices, const T &value)> func) const
Traverses the multidimensional array in row-major order, calling func at every element.
Definition: arraynd_base.h:392
arraynd< T, 1 > array1d
Definition: arraynd.h:366
arraynd()
Constructs an arraynd object with dimensions of length zero.
Definition: arraynd.h:380
arraynd< bool, ndims > operator!(const arraynd< bool, ndims > &arr)
Definition: arraynd.h:852
~arraynd()=default
Destructor.
arraynd< T, ndims > & operator=(const arraynd< T, ndims > &)=default
Copy assignment (if !is_view() && rhs.is_view(), data is shared; otherwise data is copied) ...
arraynd< bool, ndims > operator>(const arraynd< T, ndims > &lhs, const arraynd< T, ndims > &rhs)
Definition: arraynd.h:901
arraynd< T, ndims > replace(const arraynd< T, ndims > &lhs, const arraynd< bool, ndims > &selection, const U &rhs)
Returns a multidimensional array similar to arr but with elements for which selection(indices) is tru...
Definition: arraynd.h:1132
bool any(const arraynd< bool, ndims > &arr)
Returns true if any element of arr is true.
Definition: arraynd.h:879
A class template for a multidimensional array with elements of type T arranged in a lattice of ndims ...
Definition: arraynd.h:187
arraynd< T, ndims > to(const arraynd< U, ndims > &arr)
Returns a multidimensional array with the elements of arr converted to type T.
Definition: arraynd.h:1119
A base class template for a multidimensional array with elements of type T arranged in a lattice of n...
Definition: arraynd_base.h:25
const arraynd< T, ndims > view_transposed() const
Create a const transposed view of the multidimensional array (data is shared).
Definition: arraynd.h:457
bool all(const arraynd< bool, ndims > &arr)
Returns true if all elements of arr are true.
Definition: arraynd.h:864
arraynd< bool, ndims > operator||(const arraynd< bool, ndims > &lhs, const arraynd< bool, ndims > &rhs)
Definition: arraynd.h:961
arraynd< T, ndims+1 > copy_subdivided_axis(int64 idim, const std::array< int64, 2 > &dims) const
Create a deep copy with dimension idim split into two dimensions with lengths given by dims (data is ...
Definition: arraynd.h:529
const arraynd< T, ndims > view_swapped_axes(int64 idim0, int64 idim1) const
Create a const view with dimensions idim0 and idim1 swapped (data is shared).
Definition: arraynd.h:484
int64 size() const
Returns the total number of elements.
int64 offset() const
Returns the number of element-size steps in memory before the first element.
Definition: arraynd_base.h:229
bool operator()(const sydevs::array1d< T > &lhs, const sydevs::array1d< T > &rhs) const
Definition: arraynd.h:1218
arraynd< T, ndims > operator-(const arraynd< T, ndims > &rhs)
Definition: arraynd.h:731
const arraynd< T, ndims-1 > view_absorbed_axis(int64 idim) const
Create a const view with dimension idim absorbed into dimension idim - 1 (data is shared)...
Definition: arraynd.h:537
arraynd< bool, ndims > operator>=(const arraynd< T, ndims > &lhs, const arraynd< T, ndims > &rhs)
Definition: arraynd.h:921
arraynd< T, ndims > copy_transposed() const
Create a transposed deep copy of the multidimensional array (data is copied).
Definition: arraynd.h:475
const arraynd< T, ndims-1 > operator[](int64 index) const
Create a const slice with one dimension replaced by referencing elements at the specified index (data...
Definition: arraynd.h:408
static void subdivide_axis(const arraynd_base< T, ndims > &arr0, arraynd_base< T, ndims+1 > &arr, int64 idim, const std::array< int64, 2 > &dims)
Definition: arraynd_base.h:564
A one-dimensional (1D) specialization of the arraynd multidimensional array template.
Definition: arraynd.h:291
arraynd< T, ndims > copy() const
Create a deep copy of the multidimensional array (data is copied).
Definition: arraynd.h:450
const arraynd< T, ndims+1 > view_subdivided_axis(int64 idim, const std::array< int64, 2 > &dims) const
Create a const view with dimension idim split into two dimensions with lengths given by dims (data is...
Definition: arraynd.h:511
arraynd< bool, ndims > operator!=(const arraynd< T, ndims > &lhs, const arraynd< T, ndims > &rhs)
Definition: arraynd.h:941
arraynd< T, ndims-1 > copy_absorbed_axis(int64 idim) const
Create a deep copy with dimension idim absorbed into dimension idim - 1 (data is copied).
Definition: arraynd.h:555
arraynd< T, ndims > operator*(const arraynd< T, ndims > &lhs, const arraynd< T, ndims > &rhs)
Definition: arraynd.h:796
int64_t int64
Definition: number_types.h:14
const arraynd< T, ndims > view() const
Create a const view of the multidimensional array (data is shared).
Definition: arraynd.h:436
arraynd< bool, ndims > operator&&(const arraynd< bool, ndims > &lhs, const arraynd< bool, ndims > &rhs)
Definition: arraynd.h:951
arraynd< T, ndims > operator/(const arraynd< T, ndims > &lhs, const arraynd< T, ndims > &rhs)
Definition: arraynd.h:824