36#ifdef NDA_ENFORCE_BOUNDCHECK
44 template <
int Rank, u
int64_t StaticExtents, u
int64_t Str
ideOrder, layout_prop_e LayoutProp>
50namespace nda::slice_static {
94 template <
typename... Args,
size_t... Is>
95 constexpr int ellipsis_position_impl(std::index_sequence<Is...>) {
97 int r = ((std::is_same_v<Args, ellipsis> ? int(Is) + 1 : 0) + ...);
98 return (r == 0 ? 128 : r - 1);
102 template <
typename... Args>
103 constexpr int ellipsis_position() {
104 return detail::ellipsis_position_impl<Args...>(std::make_index_sequence<
sizeof...(Args)>{});
108 constexpr int q_of_n(
int n,
int e_pos,
int e_len) {
110 if (n < e_pos)
return n;
113 if (n < (e_pos + e_len))
return e_pos;
116 return n - (e_len - 1);
120 template <
int N,
int P,
size_t Q>
121 constexpr std::array<int, P> n_of_p_map(std::array<bool, Q>
const &args_is_range,
int e_pos,
int e_len) {
124 for (
int n = 0, p = 0; n < N; ++n) {
126 int q = q_of_n(n, e_pos, e_len);
128 if (args_is_range[q]) result[p++] = n;
134 template <
int N,
int P,
size_t Q>
135 constexpr std::array<int, P> q_of_p_map(std::array<bool, Q>
const &args_is_range,
int e_pos,
int e_len) {
139 for (
int n = 0; n < N; ++n) {
141 int q = q_of_n(n, e_pos, e_len);
143 if (args_is_range[q]) result[p++] = q;
149 template <
size_t N,
size_t P>
150 constexpr std::array<int, N> p_of_n_map(std::array<int, P>
const &n_of_p) {
152 for (
size_t p = 0; p < P; ++p) result[n_of_p[p]] = p;
157 template <
size_t P,
size_t N>
158 constexpr std::array<int, P> slice_stride_order(std::array<int, N>
const &orig_stride_order, std::array<int, P>
const &n_of_p) {
160 auto p_of_n = p_of_n_map<N>(n_of_p);
161 for (
int i = 0, ip = 0; i < N; ++i) {
163 int n = orig_stride_order[i];
167 if (p != -1) result[ip++] = p;
173 template <
size_t Q,
size_t N>
174 constexpr layout_prop_e slice_layout_prop(
int P,
bool has_only_rangeall_and_long, std::array<bool, Q>
const &args_is_rangeall,
175 std::array<int, N>
const &orig_stride_order,
layout_prop_e orig_layout_prop,
int e_pos,
int e_len) {
177 if (not has_only_rangeall_and_long) {
180 return layout_prop_e::strided_1d;
183 return layout_prop_e::none;
188 int n_rangeall_blocks = 0;
189 bool previous_arg_is_rangeall =
false;
190 for (
int i = 0; i < N; ++i) {
191 int q = q_of_n(orig_stride_order[i], e_pos, e_len);
192 bool arg_is_rangeall = args_is_rangeall[q];
193 if (arg_is_rangeall and (not previous_arg_is_rangeall)) ++n_rangeall_blocks;
194 previous_arg_is_rangeall = arg_is_rangeall;
196 bool rangeall_are_grouped_in_memory = (n_rangeall_blocks <= 1);
197 bool last_is_rangeall = previous_arg_is_rangeall;
200 if (
has_contiguous(orig_layout_prop) and rangeall_are_grouped_in_memory and last_is_rangeall)
return layout_prop_e::contiguous;
201 if (
has_strided_1d(orig_layout_prop) and rangeall_are_grouped_in_memory)
return layout_prop_e::strided_1d;
204 return layout_prop_e::none;
209 FORCEINLINE
long get_offset(
long idx,
long stride) {
return idx * stride; }
213 FORCEINLINE
long get_offset(range
const &rg,
long stride) {
return rg.first() * stride; }
217 FORCEINLINE
long get_offset(range::all_t,
long) {
return 0; }
220 FORCEINLINE
long get_length(range
const &rg,
long original_len) {
221 auto last = (rg.last() == -1 and rg.step() > 0) ? original_len : rg.last();
222 return range(rg.first(), last, rg.step()).size();
227 FORCEINLINE
long get_length(range::all_t,
long original_len) {
return original_len; }
230 FORCEINLINE
long get_stride(range
const &rg,
long original_str) {
return original_str * rg.step(); }
234 FORCEINLINE
long get_stride(range::all_t,
long original_str) {
return original_str; }
237 template <
size_t... Ps,
size_t... Ns,
typename IdxMap,
typename... Args>
238 FORCEINLINE
auto slice_idx_map_impl(std::index_sequence<Ps...>, std::index_sequence<Ns...>, IdxMap
const &idxm, Args
const &...args) {
240#ifdef NDA_ENFORCE_BOUNDCHECK
244 static_assert(IdxMap::rank() ==
sizeof...(Ns),
"Internal error in slice_idx_map_impl: Rank and length of index sequence do not match");
248 static constexpr int N =
sizeof...(Ns);
249 static constexpr int P =
sizeof...(Ps);
250 static constexpr int Q =
sizeof...(Args);
251 static constexpr int e_len = N - Q + 1;
252 static constexpr int e_pos = ellipsis_position<Args...>();
255 static constexpr std::array<bool, Q> args_is_range{(std::is_same_v<Args, range> or std::is_base_of_v<range::all_t, Args>)...};
258 static constexpr std::array<bool, Q> args_is_rangeall{(std::is_base_of_v<range::all_t, Args>)...};
261 static constexpr std::array<int, P> n_of_p = n_of_p_map<N, P>(args_is_range, e_pos, e_len);
264 static constexpr std::array<int, P> q_of_p = q_of_p_map<N, P>(args_is_range, e_pos, e_len);
267 static_assert(n_of_p.size() == P,
"Internal error in slice_idx_map_impl: Size of the mapping n_of_p and P do not match");
268 static_assert(q_of_p.size() == P,
"Internal error in slice_idx_map_impl: Size of the mapping q_of_p and P do not match");
271 auto argstie = std::tie(args...);
274 long offset = (get_offset(std::get<q_of_n(Ns, e_pos, e_len)>(argstie), std::get<Ns>(idxm.strides())) + ... + 0);
277 std::array<long, P> len{get_length(std::get<q_of_p[Ps]>(argstie), std::get<n_of_p[Ps]>(idxm.lengths()))...};
278 std::array<long, P> str{get_stride(std::get<q_of_p[Ps]>(argstie), std::get<n_of_p[Ps]>(idxm.strides()))...};
282 static constexpr std::array<int, P> new_static_extents{(args_is_rangeall[q_of_p[Ps]] ? IdxMap::static_extents[n_of_p[Ps]] : 0)...};
285 static constexpr std::array<int, P> new_stride_order = slice_stride_order(IdxMap::stride_order, n_of_p);
288 static constexpr bool has_only_rangeall_and_long = ((std::is_constructible_v<long, Args> or std::is_base_of_v<range::all_t, Args>)and...);
290 slice_layout_prop(P, has_only_rangeall_and_long, args_is_rangeall, IdxMap::stride_order, IdxMap::layout_prop, e_pos, e_len);
293 static constexpr uint64_t new_static_extents_encoded =
encode(new_static_extents);
294 static constexpr uint64_t new_stride_order_encoded =
encode(new_stride_order);
295 return std::make_pair(offset, idx_map<P, new_static_extents_encoded, new_stride_order_encoded, li>{len, str});
324 template <
int R, uint64_t SE, uint64_t SO,
layout_prop_e LP,
typename... Args>
327 static constexpr int n_args_ellipsis = ((std::is_same_v<Args, ellipsis>)+...);
328 static constexpr int n_args_long = (std::is_constructible_v<long, Args> + ...);
331 static_assert(n_args_ellipsis <= 1,
"Error in nda::slice_static::slice_idx_map: At most one ellipsis argument is allowed");
332 static_assert((
sizeof...(Args) <= R + 1),
"Error in nda::slice_static::slice_idx_map: Incorrect number of arguments");
333 static_assert((n_args_ellipsis == 1) or (
sizeof...(Args) == R),
"Error in nda::slice_static::slice_idx_map: Incorrect number of arguments");
335 return detail::slice_idx_map_impl(std::make_index_sequence<R - n_args_long>{}, std::make_index_sequence<R>{}, idxm, args...);
Provides utility functions for std::array.
Provides a way to check the bounds when accessing elements/slices of an array or a view.
Layout that specifies how to map multi-dimensional indices to a linear/flat index.
__inline__ decltype(auto) slice_idx_map(idx_map< R, SE, SO, LP > const &idxm, Args const &...args)
Determine the resulting nda::idx_map when taking a slice of a given nda::idx_map.
constexpr bool has_contiguous(layout_prop_e lp)
Checks if a layout property has the contiguous property.
constexpr bool has_strided_1d(layout_prop_e lp)
Checks if a layout property has the strided_1d property.
void assert_in_bounds(int rank, long const *lengths, Args const &...args)
Check if the given indices/arguments are within the bounds of an array/view.
constexpr bool has_smallest_stride_is_one(layout_prop_e lp)
Checks if a layout property has the smallest_stride_is_one property.
layout_prop_e
Compile-time guarantees of the memory layout of an array/view.
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.
Macros used in the nda library.
Includes the itertools header and provides some additional utilities.
Provides type traits for the nda library.