20
21
22
26#include "./accessors.hpp"
27#include "./basic_array_view.hpp"
28#include "./basic_functions.hpp"
29#include "./concepts.hpp"
30#include "./exceptions.hpp"
31#include "./iterators.hpp"
32#include "./layout/for_each.hpp"
33#include "./layout/permutation.hpp"
34#include "./layout/range.hpp"
35#include "./layout_transforms.hpp"
36#include "./macros.hpp"
37#include "./mem/address_space.hpp"
38#include "./mem/memcpy.hpp"
39#include "./mem/policies.hpp"
40#include "./stdutil/array.hpp"
41#include "./traits.hpp"
47#include <initializer_list>
53#ifdef NDA_ENFORCE_BOUNDCHECK
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 template <
typename ValueType,
int Rank,
typename LayoutPolicy,
char Algebra,
typename ContainerPolicy>
115 static_assert(!std::is_const_v<ValueType>,
"Error in nda::basic_array: ValueType cannot be const");
116 static_assert((Algebra !=
'N'),
"Internal error in nda::basic_array: Algebra 'N' not supported");
117 static_assert((Algebra !=
'M')
or (Rank == 2),
"Internal error in nda::basic_array: Algebra 'M' requires a rank 2 array");
118 static_assert((Algebra !=
'V')
or (Rank == 1),
"Internal error in nda::basic_array: Algebra 'V' requires a rank 1 array");
122 using value_type = ValueType;
125 using layout_policy_t = LayoutPolicy;
128 using layout_t =
typename LayoutPolicy::
template mapping<Rank>;
131 using container_policy_t = ContainerPolicy;
134 using storage_t =
typename ContainerPolicy::
template handle<ValueType>;
140 static constexpr int rank = Rank;
143 static_assert(has_contiguous(layout_t::layout_prop),
"Error in nda::basic_array: Memory layout has to be contiguous");
153 using OwningPolicy =
borrowed<storage_t::address_space>;
156 static constexpr bool is_const =
false;
159 static constexpr bool is_view =
false;
168 template <std::integral Int =
long>
169 basic_array(std::array<Int, Rank>
const &shape, mem::
init_zero_t) : lay{shape}, sto{lay.size(), mem
::init_zero} {}
173
174
175
179
180
181
188 return permuted_indices_view<
encode(std::array<
int, 2>{1, 0}
)>(*
this);
195 return permuted_indices_view<
encode(std::array<
int, 2>{1, 0}
)>(*
this);
208
209
210
211
212
213
214
215
216 template <
char A,
typename CP>
217 explicit basic_array(
basic_array<ValueType, Rank, LayoutPolicy, A, CP> a)
noexcept : lay(a.indexmap()), sto(std::move(a.storage())) {}
220
221
222
223
224
225
226
227
228 template <
std::integral... Ints>
229 requires(
sizeof...(Ints) == Rank)
232 lay = layout_t{std::array{
long(is)...}};
233 sto = storage_t{lay.size()};
237
238
239
240
241
242
243
244 template <
std::integral Int,
typename RHS>
246 requires((Rank == 1
and is_scalar_for_v<RHS,
basic_array>))
247 : lay(layout_t{std::array{
long(sz)}}), sto{lay.size()} {
248 assign_from_scalar(val);
252
253
254
255
256
257
258
259 template <
std::integral Int =
long>
261 requires(std::is_default_constructible_v<ValueType>)
262 : lay(shape), sto(lay.size()) {}
265
266
267
268
269
270
272 requires(std::is_default_constructible_v<ValueType>)
273 : lay{layout}, sto{lay.size()} {}
276
277
278
279
280
281
282
283 explicit basic_array(layout_t
const &layout, storage_t &&storage)
noexcept : lay{layout}, sto{std::move(storage)} {}
286
287
288
289
290
291 template <ArrayOfRank<Rank> A>
292 requires(HasValueTypeConstructibleFrom<A, value_type>)
294 static_assert(std::is_constructible_v<value_type, get_value_t<A>>,
"Error in nda::basic_array: Incompatible value types in constructor");
295 if constexpr (std::is_trivial_v<ValueType>
or is_complex_v<ValueType>) {
297 assign_from_ndarray(a);
300 nda::for_each(lay.lengths(), [&](
auto const &...is) {
new (sto.data() + lay(is...)) ValueType{a(is...)}; });
305
306
307
308
309
310
311
312
313 template <ArrayInitializer<
basic_array> Initializer>
315 initializer.invoke(*
this);
320 static std::array<
long, 1> shape_from_init_list(std::initializer_list<ValueType>
const &l)
noexcept {
return {
long(l.size())}; }
323 template <
typename L>
324 static auto shape_from_init_list(std::initializer_list<L>
const &l)
noexcept {
325 const auto [min, max] = std::minmax_element(std::begin(l), std::end(l), [](
auto &&x,
auto &&y) {
return x.size() < y.size(); });
327 "Error in nda::basic_array: Arrays can only be initialized with rectangular initializer lists");
328 return stdutil::front_append(shape_from_init_list(*max),
long(l.size()));
333
334
335
340 for (
auto const &x : l) {
new (sto.data() + lay(i++)) ValueType{x}; }
344
345
346
347 basic_array(std::initializer_list<std::initializer_list<ValueType>>
const &l2)
351 for (
auto const &l1 : l2) {
352 for (
auto const &x : l1) {
new (sto.data() + lay(i, j++)) ValueType{x}; }
359
360
361
362 basic_array(std::initializer_list<std::initializer_list<std::initializer_list<ValueType>>>
const &l3)
365 long i = 0, j = 0, k = 0;
366 for (
auto const &l2 : l3) {
367 for (
auto const &l1 : l2) {
368 for (
auto const &x : l1) {
new (sto.data() + lay(i, j, k++)) ValueType{x}; }
378
379
380
381
382
383
384
385
389 :
basic_array{a.indexmap(), std::move(a).storage()} {}
392
393
394
395
396
397
398 template <
std::integral Int =
long>
400 requires(std::is_standard_layout_v<ValueType> && std::is_trivially_copyable_v<ValueType>)
406
407
408
409
410
411
412 template <
std::integral... Ints>
414 requires(
sizeof...(Ints) == Rank)
416 return zeros(std::array<
long, Rank>{is...});
420
421
422
423
424
425
426 template <
std::integral Int =
long>
428 requires(nda::is_scalar_v<ValueType>)
430 auto res =
basic_array{stdutil::make_std_array<
long>(shape)};
431 res() = ValueType{1};
436
437
438
439
440
441
442 template <
std::integral... Ints>
444 requires(
sizeof...(Ints) == Rank)
446 return ones(std::array<
long, Rank>{is...});
450
451
452
453
454
455
456
457
458
459 template <
std::integral Int =
long>
461 requires(std::is_floating_point_v<ValueType>
or nda::is_complex_v<ValueType>)
463 using namespace std::complex_literals;
464 auto static gen = std::mt19937(std::random_device{}());
465 auto static dist = std::uniform_real_distribution<>(0.0, 1.0);
467 if constexpr (nda::is_complex_v<ValueType>)
468 for (
auto &x : res) x = dist(gen) + 1i * dist(gen);
470 for (
auto &x : res) x = dist(gen);
475
476
477
478
479
480
481
482
483
484 template <
std::integral... Ints>
486 requires(
sizeof...(Ints) == Rank)
488 return rand(std::array<
long, Rank>{is...});
498
499
500
501
502
503
504
505
506
507 template <
char A,
typename CP>
514
515
516
517
518
519
520
521
522 template <ArrayOfRank<Rank> RHS>
525 assign_from_ndarray(rhs);
530
531
532
533
534
535
536
537
538
539 template <
typename RHS>
543 assign_from_scalar(rhs);
548
549
550
551
552
553
554
555
556 template <ArrayInitializer<
basic_array> Initializer>
558 resize(initializer.shape());
559 initializer.invoke(*
this);
564
565
566
567
568
569
570
571
572
573 template <
std::integral... Ints>
575 static_assert(std::is_copy_constructible_v<ValueType>,
"Error in nda::basic_array: Resizing requires the value_type to be copy constructible");
576 static_assert(
sizeof...(is) == Rank,
"Error in nda::basic_array: Resizing requires exactly Rank arguments");
577 resize(std::array<
long, Rank>{
long(is)...});
581
582
583
584
585
586
587
588
590 lay = layout_t(shape);
591 if (sto.is_null()
or (sto.size() != lay.size())) sto = storage_t{lay.size()};
612
613
614
618
619
620
624
625
626
630
631
632
636
637
638
639
640
644
645
646
650
651
652
656
657
658
662
663
664
668
669
670
674
675
676
680
681
682
689
690
691
693#ifdef NDA_ENFORCE_BOUNDCHECK
694 if (i < 0 || i >= rank) {
695 std::cerr <<
"Error in extent: Dimension " << i <<
" is incompatible with array of rank " << rank << std::endl;
699 return lay.lengths()[i];
706
707
708
712
713
714
718
719
720
724
725
726
727
728
729
730
731
733 if constexpr (layout_t::layout_prop ==
layout_prop_e::strided_1d)
734 return sto[idx
.value * lay.min_stride()];
735 else if constexpr (layout_t::layout_prop ==
layout_prop_e::contiguous)
738 static_assert(always_false<layout_t>,
"Internal error in array/view: Calling this type with a _linear_index_t is not allowed");
743 if constexpr (layout_t::layout_prop ==
layout_prop_e::strided_1d)
744 return sto[idx
.value * lay.min_stride()];
745 else if constexpr (layout_t::layout_prop ==
layout_prop_e::contiguous)
748 static_assert(always_false<layout_t>,
"Internal error in array/view: Calling this type with a _linear_index_t is not allowed");
753#ifdef NDA_ENFORCE_BOUNDCHECK
756static constexpr bool has_no_boundcheck =
true;
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776template <
char ResultAlgebra,
bool SelfIsRvalue,
typename Self,
typename... Ts>
779 using r_v_t = std::conditional_t<std::is_const_v<std::remove_reference_t<Self>>, ValueType
const, ValueType>;
782 if constexpr (clef::is_any_lazy<Ts...>) {
784 return clef::make_expr_call(std::forward<Self>(self), idxs...);
785 }
else if constexpr (
sizeof...(Ts) == 0) {
787 return basic_array_view<r_v_t, Rank, LayoutPolicy, Algebra, AccessorPolicy, OwningPolicy>{self.lay, self.sto};
790 static_assert(((layout_t::
template argument_is_allowed_for_call_or_slice<Ts> + ...) > 0),
791 "Error in array/view: Slice arguments must be convertible to range, ellipsis, or long (or string if the layout permits it)");
794 static constexpr int n_args_long = (layout_t::
template argument_is_allowed_for_call<Ts> + ...);
796 if constexpr (n_args_long ==
rank) {
798 long offset = self.lay(idxs...);
799 if constexpr (is_view
or not SelfIsRvalue) {
801 return AccessorPolicy::
template accessor<ValueType>::access(self.sto.data(), offset);
804 return ValueType{self.sto[offset]};
808 auto const [offset, idxm] = self.lay.slice(idxs...);
809 static constexpr auto res_rank =
decltype(idxm)::rank();
811 static constexpr char newAlgebra = (ResultAlgebra ==
'M' and (res_rank == 1) ?
'V' : ResultAlgebra);
813 using r_layout_p =
typename detail::layout_to_policy<std::decay_t<
decltype(idxm)>>::type;
814 return basic_array_view<ValueType, res_rank, r_layout_p, newAlgebra, AccessorPolicy, OwningPolicy>{std::move(idxm), {self.sto, offset}};
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841template <
typename... Ts>
843 static_assert((
rank == -1)
or (
sizeof...(Ts) ==
rank)
or (
sizeof...(Ts) == 0)
or (ellipsis_is_present<Ts...>
and (
sizeof...(Ts) <=
rank + 1)),
844 "Error in array/view: Incorrect number of parameters in call operator");
845 return call<Algebra,
false>(*
this, idxs...);
849template <
typename... Ts>
851 static_assert((
rank == -1)
or (
sizeof...(Ts) ==
rank)
or (
sizeof...(Ts) == 0)
or (ellipsis_is_present<Ts...>
and (
sizeof...(Ts) <=
rank + 1)),
852 "Error in array/view: Incorrect number of parameters in call operator");
853 return call<Algebra,
false>(*
this, idxs...);
857template <
typename... Ts>
859 static_assert((
rank == -1)
or (
sizeof...(Ts) ==
rank)
or (
sizeof...(Ts) == 0)
or (ellipsis_is_present<Ts...>
and (
sizeof...(Ts) <=
rank + 1)),
860 "Error in array/view: Incorrect number of parameters in call operator");
861 return call<Algebra,
true>(*
this, idxs...);
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
883 static_assert((
rank == 1),
"Error in array/view: Subscript operator is only available for rank 1 views/arrays in C++17/20");
884 return call<Algebra,
false>(*
this, idx);
890 static_assert((
rank == 1),
"Error in array/view: Subscript operator is only available for rank 1 views/arrays in C++17/20");
891 return call<Algebra,
false>(*
this, x);
897 static_assert((
rank == 1),
"Error in array/view: Subscript operator is only available for rank 1 views/arrays in C++17/20");
898 return call<Algebra,
true>(*
this, x);
902static constexpr int iterator_rank = (has_strided_1d(layout_t::layout_prop) ? 1 : Rank);
912template <
typename Iterator>
913[[nodiscard]]
auto make_iterator(
bool at_end)
const noexcept {
916 if constexpr (layout_t::is_stride_order_C()) {
921 return Iterator{nda::permutations::apply(layout_t::stride_order,
indexmap().lengths()),
922 nda::permutations::apply(layout_t::stride_order,
indexmap().strides()), sto.data(), at_end};
926 return Iterator{std::array<
long, 1>{
size()}, std::array<
long, 1>{
indexmap().min_stride()}, sto.data(), at_end};
932[[
nodiscard]] const_iterator
begin()
const noexcept {
return make_iterator<const_iterator>(
false); }
935[[
nodiscard]] const_iterator
cbegin()
const noexcept {
return make_iterator<const_iterator>(
false); }
938iterator
begin()
noexcept {
return make_iterator<iterator>(
false); }
941[[
nodiscard]] const_iterator
end()
const noexcept {
return make_iterator<const_iterator>(
true); }
944[[
nodiscard]] const_iterator
cend()
const noexcept {
return make_iterator<const_iterator>(
true); }
947iterator
end()
noexcept {
return make_iterator<iterator>(
true); }
950
951
952
953
954
955
956
957
958
959
960
961template <
typename RHS>
963 static_assert(
not is_const,
"Error in array/view: Can not assign to a const view");
964 return operator=(*
this + rhs);
968
969
970
971
972
973
974
975
976
977
978
979template <
typename RHS>
981 static_assert(
not is_const,
"Error in array/view: Can not assign to a const view");
982 return operator=(*
this - rhs);
986
987
988
989
990
991
992
993
994
995
996
997template <
typename RHS>
999 static_assert(
not is_const,
"Error in array/view: Can not assign to a const view");
1000 return operator=((*
this) * rhs);
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015template <
typename RHS>
1017 static_assert(
not is_const,
"Error in array/view: Can not assign to a const view");
1018 return operator=(*
this / rhs);
1022
1023
1024
1025
1026
1027
1028
1029template <
std::
ranges::contiguous_range R>
1031 requires(Rank == 1
and not MemoryArray<R>)
1039template <
typename RHS>
1040void assign_from_ndarray(RHS
const &rhs) {
1041#ifdef NDA_ENFORCE_BOUNDCHECK
1042 if (
this->shape() != rhs.shape())
1043 NDA_RUNTIME_ERROR <<
"Error in assign_from_ndarray: Size mismatch:"
1044 <<
"\n LHS.shape() = " <<
this->shape() <<
"\n RHS.shape() = " << rhs.shape();
1047 static_assert(std::is_assignable_v<value_type &, get_value_t<RHS>>,
"Error in assign_from_ndarray: Incompatible value types");
1050 static constexpr bool both_in_memory = MemoryArray<self_t>
and MemoryArray<RHS>;
1053 static constexpr bool same_stride_order = get_layout_info<self_t>.stride_order == get_layout_info<RHS>.stride_order;
1056 if constexpr (both_in_memory
and same_stride_order) {
1057 if (rhs.empty())
return;
1059 static constexpr bool both_1d_strided = has_layout_strided_1d<self_t>
and has_layout_strided_1d<RHS>;
1060 if constexpr (mem::on_host<self_t, RHS>
and both_1d_strided) {
1064 }
else if constexpr (!mem::on_host<self_t, RHS>
and have_same_value_type_v<self_t, RHS>) {
1066 auto bl_layout_dst = get_block_layout(*
this);
1067 auto bl_layout_src = get_block_layout(rhs);
1068 if (bl_layout_dst && bl_layout_src) {
1069 auto [n_bl_dst, bl_size_dst, bl_str_dst] = *bl_layout_dst;
1070 auto [n_bl_src, bl_size_src, bl_str_src] = *bl_layout_src;
1072 if (n_bl_dst * bl_size_dst != n_bl_src * bl_size_src)
NDA_RUNTIME_ERROR <<
"Error in assign_from_ndarray: Incompatible block sizes";
1074 if (n_bl_dst == 1 && n_bl_src > 1) {
1075 n_bl_dst = n_bl_src;
1076 bl_size_dst /= n_bl_src;
1077 bl_str_dst = bl_size_dst;
1079 if (n_bl_src == 1 && n_bl_dst > 1) {
1080 n_bl_src = n_bl_dst;
1081 bl_size_src /= n_bl_dst;
1082 bl_str_src = bl_size_src;
1085 if (n_bl_dst == n_bl_src && bl_size_dst == bl_size_src) {
1086 mem::memcpy2D<mem::get_addr_space<self_t>, mem::get_addr_space<RHS>>((
void *)data(), bl_str_dst *
sizeof(value_type), (
void *)rhs.data(),
1087 bl_str_src *
sizeof(value_type), bl_size_src *
sizeof(value_type),
1095 if constexpr (mem::on_device<self_t> || mem::on_device<RHS>) {
1096 NDA_RUNTIME_ERROR <<
"Error in assign_from_ndarray: Fallback to elementwise assignment not implemented for arrays/views on the GPU";
1098 nda::for_each(shape(), [
this, &rhs](
auto const &...args) { (*
this)(args...) = rhs(args...); });
1102template <
typename Scalar>
1103void fill_with_scalar(Scalar
const &scalar)
noexcept {
1105 if constexpr (has_layout_strided_1d<self_t>) {
1107 auto *
__restrict const p = data();
1108 if constexpr (has_contiguous_layout<self_t>) {
1109 for (
long i = 0; i < L; ++i) p[i] = scalar;
1112 const long Lstri = L * stri;
1113 for (
long i = 0; i < Lstri; i += stri) p[i] = scalar;
1117 for (
auto &x : *
this) x = scalar;
1122template <
typename Scalar>
1123void assign_from_scalar(Scalar
const &scalar)
noexcept {
1124 static_assert(!is_const,
"Error in assign_from_ndarray: Cannot assign to a const view");
1125 if constexpr (Algebra !=
'M') {
1127 fill_with_scalar(scalar);
1132 if constexpr (is_scalar_or_convertible_v<Scalar>)
1133 fill_with_scalar(0);
1135 fill_with_scalar(Scalar{0 * scalar});
1137 for (
long i = 0; i < imax; ++i) operator()(i, i) = scalar;
1143 template <MemoryArray A>
1144 basic_array(A &&a) ->
basic_array<get_value_t<A>, get_rank<A>, get_contiguous_layout_policy<get_rank<A>, get_layout_info<A>.stride_order>,
1145 get_algebra<A>, heap<mem::get_addr_space<A>>>;
1148 basic_array(A &&a) ->
basic_array<get_value_t<A>, get_rank<A>,
C_layout, get_algebra<A>, heap<>>;
Iterator for nda::basic_array and nda::basic_array_view types.
A generic view of a multi-dimensional array.
A generic multi-dimensional array.
auto & operator+=(RHS const &rhs) noexcept
Addition assignment operator.
decltype(auto) operator[](T const &idx) const &noexcept(has_no_boundcheck)
Subscript operator to access the 1-dimensional view/array.
basic_array(basic_array< ValueType, 2, LayoutPolicy, A2, ContainerPolicy > &&a) noexcept
Construct a 2-dimensional array from another 2-dimensional array with a different algebra.
basic_array & operator=(RHS const &rhs)
Assignment operator makes a deep copy of an nda::ArrayOfRank object.
static constexpr bool is_stride_order_Fortran() noexcept
Is the stride order of the view/array in Fortran-order?
ValueType const * data() const noexcept
Get a pointer to the actual data (in general this is not the beginning of the memory block for a view...
ValueType * data() noexcept
Get a pointer to the actual data (in general this is not the beginning of thr memory block for a view...
long shape(int i) const noexcept
const_iterator cbegin() const noexcept
Get a const iterator to the beginning of the view/array.
static constexpr int rank
Number of dimensions of the array.
static constexpr bool is_stride_order_C() noexcept
Is the stride order of the view/array in C-order?
storage_t & storage() &noexcept
Get the data storage of the view/array.
basic_array(basic_array< ValueType, Rank, LayoutPolicy, A, CP > a) noexcept
Construct an array from another array with a different algebra and/or container policy.
auto const & strides() const noexcept
Get the strides of the view/array (see nda::idx_map for more details on how we define strides).
basic_array(Ints... is)
Construct an array with the given dimensions.
static basic_array ones(Ints... is)
Make a one-initialized array with the given dimensions.
const_iterator begin() const noexcept
Get a const iterator to the beginning of the view/array.
auto as_array_view() const
Convert the current array to a view with an 'A' (array) algebra.
long extent(int i) const noexcept
Get the extent of the ith dimension.
basic_array(std::initializer_list< ValueType > const &l)
Construct a 1-dimensional array from an initializer list.
decltype(auto) operator[](T const &x) &&noexcept(has_no_boundcheck)
Rvalue overload of nda::basic_array_view::operator[](T const &) const &.
long is_contiguous() const noexcept
Is the memory layout of the view/array contiguous?
basic_array(std::initializer_list< std::initializer_list< ValueType > > const &l2)
Construct a 2-dimensional array from a double nested initializer list.
decltype(auto) operator()(_linear_index_t idx) noexcept
Non-const overload of nda::basic_array_view::operator()(_linear_index_t) const.
__inline__ decltype(auto) operator()(Ts const &...idxs) &noexcept(has_no_boundcheck)
Non-const overload of nda::basic_array_view::operator()(Ts const &...) const &.
bool empty() const
Is the view/array empty?
void resize(std::array< long, Rank > const &shape)
Resize the array to a new shape.
basic_array(Int sz, RHS const &val)
Construct a 1-dimensional array with the given size and initialize each element to the given scalar v...
static basic_array ones(std::array< Int, Rank > const &shape)
Make a one-initialized array with the given shape.
constexpr auto stride_order() const noexcept
Get the stride order of the memory layout of the view/array (see nda::idx_map for more details on how...
auto & operator/=(RHS const &rhs) noexcept
Division assignment operator.
auto as_array_view()
Convert the current array to a view with an 'A' (array) algebra.
basic_array(A const &a)
Construct an array from an nda::ArrayOfRank object with the same rank by copying each element.
static basic_array zeros(Ints... is)
Make a zero-initialized array with the given dimensions.
auto indices() const noexcept
Get a range that generates all valid index tuples.
static __inline__ decltype(auto) call(Self &&self, Ts const &...idxs) noexcept(has_no_boundcheck)
Implementation of the function call operator.
void resize(Ints const &...is)
Resize the array to a new shape.
storage_t storage() &&noexcept
Get the data storage of the view/array.
basic_array()
Default constructor constructs an empty array with a default constructed memory handle and layout.
bool is_empty() const noexcept
auto & operator=(R const &rhs) noexcept
Assignment operator makes a deep copy of a general contiguous range and assigns it to the 1-dimension...
storage_t const & storage() const &noexcept
Get the data storage of the view/array.
basic_array & operator=(basic_array const &)=default
Default copy assignment copies the memory handle and layout from the right hand side array.
basic_array & operator=(basic_array< ValueType, Rank, LayoutPolicy, A, CP > const &rhs)
Assignment operator makes a deep copy of another array with a different algebra and/or container poli...
basic_array(basic_array const &a)=default
Default copy constructor copies the memory handle and layout.
basic_array(std::initializer_list< std::initializer_list< std::initializer_list< ValueType > > > const &l3)
Construct a 3-dimensional array from a triple nested initializer list.
iterator begin() noexcept
Get an iterator to the beginning of the view/array.
basic_array(layout_t const &layout)
Construct an array with the given memory layout.
static basic_array rand(Ints... is)
Make a random-initialized array with the given dimensions.
basic_array(layout_t const &layout, storage_t &&storage) noexcept
Construct an array with the given memory layout and with an existing memory handle/storage.
static constexpr int iterator_rank
Rank of the nda::array_iterator for the view/array.
auto & operator-=(RHS const &rhs) noexcept
Subtraction assignment operator.
const_iterator end() const noexcept
Get a const iterator to the end of the view/array.
basic_array(basic_array &&)=default
Default move constructor moves the memory handle and layout.
__inline__ decltype(auto) operator()(Ts const &...idxs) &&noexcept(has_no_boundcheck)
Rvalue overload of nda::basic_array_view::operator()(Ts const &...) const &.
basic_array(std::array< Int, Rank > const &shape)
Construct an array with the given shape.
const_iterator cend() const noexcept
Get a const iterator to the end of the view/array.
auto const & shape() const noexcept
Get the shape of the view/array.
long size() const noexcept
Get the total size of the view/array.
decltype(auto) operator[](T const &x) &noexcept(has_no_boundcheck)
Non-const overload of nda::basic_array_view::operator[](T const &) const &.
auto & operator*=(RHS const &rhs) noexcept
Multiplication assignment operator.
basic_array & operator=(basic_array &&)=default
Default move assignment moves the memory handle and layout from the right hand side array.
static basic_array zeros(std::array< Int, Rank > const &shape)
Make a zero-initialized array with the given shape.
__inline__ decltype(auto) operator()(Ts const &...idxs) const &noexcept(has_no_boundcheck)
Function call operator to access the view/array.
constexpr auto const & indexmap() const noexcept
Get the memory layout of the view/array.
iterator end() noexcept
Get an iterator to the end of the view/array.
decltype(auto) operator()(_linear_index_t idx) const noexcept
Access the element of the view/array at the given nda::_linear_index_t.
static basic_array rand(std::array< Int, Rank > const &shape)
Make a random-initialized array with the given shape.
#define CUSOLVER_CHECK(X, info,...)
#define NDA_RUNTIME_ERROR
layout_prop_e
Compile-time guarantees of the memory layout of an array/view.
static constexpr do_not_initialize_t do_not_initialize
Instance of nda::mem::do_not_initialize_t.
static constexpr init_zero_t init_zero
Instance of nda::mem::init_zero_t.
constexpr uint64_t encode(std::array< int, N > const &a)
Encode a std::array<int, N> in a uint64_t.
#define EXPECTS_WITH_MESSAGE(X,...)
Contiguous layout policy with C-order (row-major order).
A small wrapper around a single long integer to be used as a linear index.
Memory policy using an nda::mem::handle_borrowed.
Accessor type of the nda::default_accessor.
Default accessor for various array and view types.
Tag used in constructors to indicate that the memory should be initialized to zero.