31#include <itertools/itertools.hpp>
60 template <
typename T, mem::AddressSpace AdrSp = mem::Host, std::
integral Int, auto Rank>
61 auto zeros(std::array<Int, Rank>
const &shape) {
62 static_assert(AdrSp != mem::None);
63 if constexpr (Rank == 0)
65 else if constexpr (AdrSp == mem::Host)
84 return zeros<T, AdrSp>(std::array<
long,
sizeof...(Ints)>{
static_cast<long>(is)...});
98 template <
typename T, std::
integral Int, auto Rank>
99 auto ones(std::array<Int, Rank>
const &shape)
102 if constexpr (Rank == 0)
117 template <
typename T, std::integral... Ints>
119 return ones<T>(std::array<
long,
sizeof...(Ints)>{is...});
131 template <std::
integral Int =
long>
132 auto arange(
long first,
long last,
long step = 1) {
133 auto r = range(first, last, step);
135 for (
auto [x, v] : itertools::zip(a, r)) x = v;
147 template <std::
integral Int =
long>
164 template <
typename RealType =
double, std::
integral Int, auto Rank>
165 auto rand(std::array<Int, Rank>
const &shape)
166 requires(std::is_floating_point_v<RealType>)
168 if constexpr (Rank == 0) {
169 auto static gen = std::mt19937{};
170 auto static dist = std::uniform_real_distribution<>{0.0, 1.0};
188 template <
typename RealType = double, std::integral... Ints>
237 template <
typename A,
typename A_t = std::decay_t<A>>
239 if constexpr (
Array<A> and not is_regular_v<A>) {
241 }
else if constexpr (
requires {
typename A_t::regular_t; }) {
242 if constexpr (not std::is_same_v<A_t, typename A_t::regular_t>)
243 return typename A_t::regular_t{std::forward<A>(a)};
245 return std::forward<A>(a);
247 return std::forward<A>(a);
260 template <MemoryArray A>
265 return std::forward<A>(a);
278 template <MemoryArray A>
283 return std::forward<A>(a);
296 template <MemoryArray A>
301 return std::forward<A>(a);
317 template <
typename A>
321 if (a.shape() == sha)
return;
322 if constexpr (is_regular_v<A>) {
325 NDA_RUNTIME_ERROR <<
"Error in nda::resize_or_check_if_view: Size mismatch: " << a.shape() <<
" != " << sha;
341 template <
typename T,
int R,
typename LP,
char A,
typename CP>
359 template <
typename T,
int R,
typename LP,
char A,
typename AP,
typename OP>
376 template <
typename T,
int R,
typename LP,
char A,
typename CP>
394 template <
typename T,
int R,
typename LP,
char A,
typename AP,
typename OP>
411 template <
typename T,
int R,
typename LP,
char A,
typename CP>
429 template <
typename T,
int R,
typename LP,
char A,
typename AP,
typename OP>
446 template <
typename T,
int R,
typename LP,
char A,
typename CP>
464 template <
typename T,
int R,
typename LP,
char A,
typename AP,
typename OP>
479 template <Array LHS, Array RHS>
483 static_assert(std::equality_comparable_with<get_value_t<LHS>,
get_value_t<RHS>>,
484 "Error in nda::operator==: Only defined when elements are comparable");
486 if (lhs.shape() != rhs.shape())
return false;
488 nda::for_each(lhs.shape(), [&](
auto &&...x) { r &= (lhs(x...) == rhs(x...)); });
502 template <ArrayOfRank<1> A, std::ranges::contiguous_range R>
517 template <std::ranges::contiguous_range R, ArrayOfRank<1> A>
531 template <Array A,
typename F>
534 if constexpr (clef::is_function<std::decay_t<decltype(f(x...))>>) {
535 clef_auto_assign(a(x...), f(x...));
559 template <MemoryArray A>
562 using opt_t = std::optional<std::tuple<int, int, int>>;
564 auto const &shape = a.indexmap().lengths();
565 auto const &strides = a.indexmap().strides();
566 auto const &order = a.indexmap().stride_order;
568 int data_size = shape[order[0]] * strides[order[0]];
569 int block_size = data_size;
570 int block_str = data_size;
573 for (
auto n : range(A::rank)) {
574 auto inner_size = (n == A::rank - 1) ? 1 : strides[order[n + 1]] * shape[order[n + 1]];
575 if (strides[order[n]] != inner_size) {
576 if (block_size < data_size)
579 n_blocks = a.size() / inner_size;
580 block_size = inner_size;
581 block_str = strides[order[n]];
584 ASSERT(n_blocks * block_size == a.size());
585 ASSERT(n_blocks * block_str == shape[order[0]] * strides[order[0]]);
586 return opt_t{std::make_tuple(n_blocks, block_size, block_str)};
602 template <
size_t Axis = 0, Array A0, Array... As>
605 auto constexpr rank = A0::rank;
606 static_assert(Axis < rank);
609 for (
auto ax [[maybe_unused]] : range(rank)) { EXPECTS(ax == Axis or ((a0.extent(ax) == as.extent(ax)) and ... and
true)); }
612 auto new_shape = a0.shape();
613 new_shape[Axis] = (as.extent(Axis) + ... + new_shape[Axis]);
617 auto slice_Axis = [](
Array auto &a, range r) {
618 auto all_or_range = std::make_tuple(range::all, r);
619 return [&]<
auto... Is>(std::index_sequence<Is...>) {
return a(std::get<Is == Axis>(all_or_range)...); }(std::make_index_sequence<rank>{});
625 slice_Axis(new_array, range(offset, offset + a_view.extent(Axis))) = a_view;
626 offset += a_view.
extent(Axis);
Provides definitions and type traits involving the different memory address spaces supported by nda.
A generic view of a multi-dimensional array.
A generic multi-dimensional array.
long extent(int i) const noexcept
Get the extent of the ith dimension.
static basic_array ones(std::array< Int, Rank > const &shape)
Make a one-initialized array with the given shape.
static basic_array zeros(std::array< Int, Rank > const &shape)
Make a zero-initialized array with the given shape.
static basic_array rand(std::array< Int, Rank > const &shape)
Make a random-initialized array with the given shape.
Includes all relevant headers for the core clef library.
Check if a given type satisfies the array concept.
Provides various convenient aliases and helper functions for nda::basic_array and nda::basic_array_vi...
Provides a custom runtime error class and macros to assert conditions and throw exceptions.
Provides for_each functions for multi-dimensional arrays/views.
auto rand(std::array< Int, Rank > const &shape)
Make an array of the given shape and initialize it with random values from the uniform distribution o...
decltype(auto) make_regular(A &&a)
Make a given object regular.
void resize_or_check_if_view(A &a, std::array< long, A::rank > const &sha)
Resize a given regular array to the given shape or check if a given view as the correct shape.
decltype(auto) to_unified(A &&a)
Convert an nda::MemoryArray to its regular type on unified memory.
auto make_const_view(basic_array< T, R, LP, A, CP > const &a)
Make an nda::basic_array_view with a const value type from a given nda::basic_array.
auto zeros(std::array< Int, Rank > const &shape)
Make an array of the given shape on the given address space and zero-initialize it.
auto arange(long first, long last, long step=1)
Make a 1-dimensional integer array and initialize it with values of a given nda::range.
decltype(auto) to_host(A &&a)
Convert an nda::MemoryArray to its regular type on host memory.
auto make_matrix_view(basic_array< T, R, LP, A, CP > const &a)
Make an nda::matrix_view of a given nda::basic_array.
decltype(auto) to_device(A &&a)
Convert an nda::MemoryArray to its regular type on device memory.
auto make_array_view(basic_array< T, R, LP, A, CP > const &a)
Make an nda::array_view of a given nda::basic_array.
auto make_array_const_view(basic_array< T, R, LP, A, CP > const &a)
Make an nda::array_const_view of a given nda::basic_array.
auto ones(std::array< Int, Rank > const &shape)
Make an array of the given shape and one-initialize it.
auto concatenate(A0 const &a0, As const &...as)
Join a sequence of nda::Array types along an existing axis.
basic_array< ValueType, Rank, Layout, 'A', ContainerPolicy > array
Alias template of an nda::basic_array with an 'A' algebra.
std::conditional_t< mem::on_device< RT >, RT, basic_array< get_value_t< RT >, get_rank< RT >, get_contiguous_layout_policy< get_rank< RT >, get_layout_info< RT >.stride_order >, get_algebra< RT >, heap< mem::Device > > > get_regular_device_t
Get the type of the nda::basic_array that would be obtained by constructing an array on device memory...
std::conditional_t< mem::on_unified< RT >, RT, basic_array< get_value_t< RT >, get_rank< RT >, get_contiguous_layout_policy< get_rank< RT >, get_layout_info< RT >.stride_order >, get_algebra< RT >, heap< mem::Unified > > > get_regular_unified_t
Get the type of the nda::basic_array that would be obtained by constructing an array on unified memor...
long first_dim(A const &a)
Get the extent of the first dimension of the array.
std::conditional_t< mem::on_host< RT >, RT, basic_array< get_value_t< RT >, get_rank< RT >, get_contiguous_layout_policy< get_rank< RT >, get_layout_info< RT >.stride_order >, get_algebra< RT >, heap< mem::Host > > > get_regular_host_t
Get the type of the nda::basic_array that would be obtained by constructing an array on host memory f...
constexpr bool have_same_value_type_v
Constexpr variable that is true if all types in As have the same value type as A0.
std::decay_t< decltype(get_first_element(std::declval< A const >()))> get_value_t
Get the value type of an array/view or a scalar type.
constexpr bool have_same_rank_v
Constexpr variable that is true if all types in As have the same rank as A0.
constexpr bool is_regular_or_view_v
Constexpr variable that is true if type A is either a regular array or a view.
bool operator==(LHS const &lhs, RHS const &rhs)
Equal-to comparison operator for two nda::Array objects.
long second_dim(A const &a)
Get the extent of the second dimension of the array.
void clef_auto_assign(A &&a, F &&f)
Overload of nda::clef::clef_auto_assign function for nda::Array objects.
__inline__ void for_each(std::array< Int, R > const &shape, F &&f)
Loop over all possible index values of a given shape and apply a function to them.
auto get_block_layout(A const &a)
Check if a given nda::MemoryArray has a block-strided layout.
AddressSpace
Enum providing identifiers for the different memory address spaces.
static constexpr bool on_device
Constexpr variable that is true if all given types have a Device address space.
static constexpr bool on_unified
Constexpr variable that is true if all given types have a Unified address space.
static constexpr bool on_host
Constexpr variable that is true if all given types have a Host address space.
constexpr bool is_scalar_v
Constexpr variable that is true if type S is a scalar type, i.e. arithmetic or complex.
Provides type traits for the nda library.