41 template <
size_t R,
size_t... Rs>
42 constexpr bool is_partition_of_indices(std::array<int, Rs>
const &...grps) {
44 constexpr auto Rstot = (Rs + ...);
45 static_assert(Rstot == R,
"Error in nda::detail::is_partition_of_indices: Number of indices has to be equal to the rank");
49 auto l = [&](
auto &&grp)
mutable ->
void {
50 for (
int u = 0; u < grp.size(); ++u) {
51 if (grp[u] < 0)
throw std::runtime_error(
"Error in nda::detail::is_partition_of_indices: Negative indices are not allowed");
52 if (grp[u] >= R)
throw std::runtime_error(
"Error in nda::detail::is_partition_of_indices: Indices larger than the rank are not allowed");
63 template <
size_t R,
size_t... Rs>
64 constexpr std::array<int,
sizeof...(Rs)> stride_order_of_grouped_idx_map(std::array<int, R>
const &stride_order,
65 std::array<int, Rs>
const &...grps) {
71 auto min_mem_pos = [&mem_pos](
auto &&grp) {
78 bool idx_are_consecutive_in_memory = (max - min + 1 == grp.size());
79 if (!idx_are_consecutive_in_memory)
80 throw std::runtime_error(
"Error in nda::detail::stride_order_of_grouped_idx_map: Indices are not consecutive in memory");
85 constexpr int Ngrps =
sizeof...(Rs);
88 std::array<int, Ngrps> min_mem_positions{min_mem_pos(grps)...};
92 for (
int u = 0; u < Ngrps; ++u) {
93 for (
int i = 0; i < Ngrps; ++i) {
94 if (min_mem_positions[i] < min_mem_positions[u]) ++mem_pos_out[u];
156 template <
int Rank, uint64_t StaticExtents, uint64_t StrideOrder,
layout_prop_e LayoutProp,
typename... IdxGrps>
159 static_assert(LayoutProp == layout_prop_e::contiguous,
"Error in nda::group_indices_layout: Only contiguous layouts are supported");
160 static_assert(detail::is_partition_of_indices<Rank>(IdxGrps::as_std_array...),
161 "Error in nda::group_indices_layout: Given index groups are not a valid partition");
167 auto total_len_of_a_grp = [&idxm](
auto &&grp) {
168 return std::accumulate(grp.begin(), grp.end(), 1L, [&idxm](
long l,
long u) { return l * idxm.lengths()[u]; });
172 auto min_stride_of_a_grp = [&idxm](
auto &&grp) {
173 return std::accumulate(grp.begin(), grp.end(), idxm.
size(), [&idxm](
long s,
long u) { return std::min(s, idxm.strides()[u]); });
177 static constexpr int new_rank =
sizeof...(IdxGrps);
178 std::array<long, new_rank> new_extents{total_len_of_a_grp(IdxGrps::as_std_array)...};
179 std::array<long, new_rank> new_strides{min_stride_of_a_grp(IdxGrps::as_std_array)...};
180 constexpr auto new_stride_order =
encode(detail::stride_order_of_grouped_idx_map(stride_order, IdxGrps::as_std_array...));
Provides utility functions for std::array.
Layout that specifies how to map multi-dimensional indices to a linear/flat index.
long size() const noexcept
Get the total number of elements.
idx_group_t< Is... > idx_group
Variable template for an nda::idx_group_t.
layout_prop_e
Compile-time guarantees of the memory layout of an array/view.
auto group_indices_layout(idx_map< Rank, StaticExtents, StrideOrder, LayoutProp > const &idxm, IdxGrps...)
Given an nda::idx_map and a partition of its indices, return a new nda::idx_map with the grouped indi...
constexpr std::array< Int, N > inverse(std::array< Int, N > const &p)
Inverse of a permutation.
constexpr uint64_t encode(std::array< int, N > const &a)
Encode a std::array<int, N> in a uint64_t.
constexpr std::array< T, R > make_initialized_array(T v)
Create a new std::array object initialized with a specific value.
Provides a class that maps multi-dimensional indices to a linear index and vice versa.
Provides utilities to work with permutations and to compactly encode/decode std::array objects.
static constexpr std::array< int, sizeof...(Is)> as_std_array
std::array containing the indices.
Provides type traits for the nda library.