25#ifdef NDA_ENFORCE_BOUNDCHECK 
   33  template <
int Rank, u
int64_t StaticExtents, u
int64_t Str
ideOrder, layout_prop_e LayoutProp>
 
   39namespace nda::slice_static {
 
   83    template <
typename... Args, 
size_t... Is>
 
   84    constexpr int ellipsis_position_impl(std::index_sequence<Is...>) {
 
   86      int r = ((std::is_same_v<Args, ellipsis> ? int(Is) + 1 : 0) + ...);
 
   87      return (r == 0 ? 128 : r - 1);
 
   91    template <
typename... Args>
 
   92    constexpr int ellipsis_position() {
 
   93      return detail::ellipsis_position_impl<Args...>(std::make_index_sequence<
sizeof...(Args)>{});
 
   97    constexpr int q_of_n(
int n, 
int e_pos, 
int e_len) {
 
   99      if (n < e_pos) 
return n;
 
  102      if (n < (e_pos + e_len)) 
return e_pos;
 
  105      return n - (e_len - 1);
 
  109    template <
int N, 
int P, 
size_t Q>
 
  110    constexpr std::array<int, P> n_of_p_map(std::array<bool, Q> 
const &args_is_range, 
int e_pos, 
int e_len) {
 
  113      for (
int n = 0, p = 0; n < N; ++n) {
 
  115        int q = q_of_n(n, e_pos, e_len);
 
  117        if (args_is_range[q]) result[p++] = n;
 
  123    template <
int N, 
int P, 
size_t Q>
 
  124    constexpr std::array<int, P> q_of_p_map(std::array<bool, Q> 
const &args_is_range, 
int e_pos, 
int e_len) {
 
  128      for (
int n = 0; n < N; ++n) {
 
  130        int q = q_of_n(n, e_pos, e_len);
 
  132        if (args_is_range[q]) result[p++] = q;
 
  138    template <
size_t N, 
size_t P>
 
  139    constexpr std::array<int, N> p_of_n_map(std::array<int, P> 
const &n_of_p) {
 
  141      for (
size_t p = 0; p < P; ++p) result[n_of_p[p]] = p;
 
  146    template <
size_t P, 
size_t N>
 
  147    constexpr std::array<int, P> slice_stride_order(std::array<int, N> 
const &orig_stride_order, std::array<int, P> 
const &n_of_p) {
 
  149      auto p_of_n = p_of_n_map<N>(n_of_p);
 
  150      for (
int i = 0, ip = 0; i < N; ++i) {
 
  152        int n = orig_stride_order[i];
 
  156        if (p != -1) result[ip++] = p;
 
  162    template <
size_t Q, 
size_t N>
 
  163    constexpr layout_prop_e slice_layout_prop(
int P, 
bool has_only_rangeall_and_long, std::array<bool, Q> 
const &args_is_rangeall,
 
  164                                              std::array<int, N> 
const &orig_stride_order, 
layout_prop_e orig_layout_prop, 
int e_pos, 
int e_len) {
 
  166      if (not has_only_rangeall_and_long) {
 
  169          return layout_prop_e::strided_1d;
 
  172          return layout_prop_e::none;
 
  177      int n_rangeall_blocks         = 0;
 
  178      bool previous_arg_is_rangeall = 
false;
 
  179      for (
int i = 0; i < N; ++i) {
 
  180        int q                = q_of_n(orig_stride_order[i], e_pos, e_len);
 
  181        bool arg_is_rangeall = args_is_rangeall[q];
 
  182        if (arg_is_rangeall and (not previous_arg_is_rangeall)) ++n_rangeall_blocks;
 
  183        previous_arg_is_rangeall = arg_is_rangeall;
 
  185      bool rangeall_are_grouped_in_memory = (n_rangeall_blocks <= 1);
 
  186      bool last_is_rangeall               = previous_arg_is_rangeall;
 
  189      if (
has_contiguous(orig_layout_prop) and rangeall_are_grouped_in_memory and last_is_rangeall) 
return layout_prop_e::contiguous;
 
  190      if (
has_strided_1d(orig_layout_prop) and rangeall_are_grouped_in_memory) 
return layout_prop_e::strided_1d;
 
  193      return layout_prop_e::none;
 
  198    FORCEINLINE 
long get_offset(
long idx, 
long stride) { 
return idx * stride; }
 
  202    FORCEINLINE 
long get_offset(range 
const &rg, 
long stride) { 
return rg.first() * stride; }
 
  206    FORCEINLINE 
long get_offset(range::all_t, 
long) { 
return 0; }
 
  209    FORCEINLINE 
long get_length(range 
const &rg, 
long original_len) {
 
  210      auto last = (rg.last() == -1 and rg.step() > 0) ? original_len : rg.last();
 
  211      return range(rg.first(), last, rg.step()).size();
 
  216    FORCEINLINE 
long get_length(range::all_t, 
long original_len) { 
return original_len; }
 
  219    FORCEINLINE 
long get_stride(range 
const &rg, 
long original_str) { 
return original_str * rg.step(); }
 
  223    FORCEINLINE 
long get_stride(range::all_t, 
long original_str) { 
return original_str; }
 
  226    template <
size_t... Ps, 
size_t... Ns, 
typename IdxMap, 
typename... Args>
 
  227    FORCEINLINE 
auto slice_idx_map_impl(std::index_sequence<Ps...>, std::index_sequence<Ns...>, IdxMap 
const &idxm, Args 
const &...args) {
 
  229#ifdef NDA_ENFORCE_BOUNDCHECK 
  233      static_assert(IdxMap::rank() == 
sizeof...(Ns), 
"Internal error in slice_idx_map_impl: Rank and length of index sequence do not match");
 
  237      static constexpr int N     = 
sizeof...(Ns);
 
  238      static constexpr int P     = 
sizeof...(Ps);
 
  239      static constexpr int Q     = 
sizeof...(Args);
 
  240      static constexpr int e_len = N - Q + 1;
 
  241      static constexpr int e_pos = ellipsis_position<Args...>();
 
  244      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>)...};
 
  247      static constexpr std::array<bool, Q> args_is_rangeall{(std::is_base_of_v<range::all_t, Args>)...};
 
  250      static constexpr std::array<int, P> n_of_p = n_of_p_map<N, P>(args_is_range, e_pos, e_len);
 
  253      static constexpr std::array<int, P> q_of_p = q_of_p_map<N, P>(args_is_range, e_pos, e_len);
 
  256      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");
 
  257      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");
 
  260      auto argstie = std::tie(args...);
 
  263      long offset = (get_offset(std::get<q_of_n(Ns, e_pos, e_len)>(argstie), std::get<Ns>(idxm.strides())) + ... + 0);
 
  266      std::array<long, P> len{get_length(std::get<q_of_p[Ps]>(argstie), std::get<n_of_p[Ps]>(idxm.lengths()))...};
 
  267      std::array<long, P> str{get_stride(std::get<q_of_p[Ps]>(argstie), std::get<n_of_p[Ps]>(idxm.strides()))...};
 
  271      static constexpr std::array<int, P> new_static_extents{(args_is_rangeall[q_of_p[Ps]] ? IdxMap::static_extents[n_of_p[Ps]] : 0)...};
 
  274      static constexpr std::array<int, P> new_stride_order = slice_stride_order(IdxMap::stride_order, n_of_p);
 
  277      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 ...);
 
  279         slice_layout_prop(P, has_only_rangeall_and_long, args_is_rangeall, IdxMap::stride_order, IdxMap::layout_prop, e_pos, e_len);
 
  282      static constexpr uint64_t new_static_extents_encoded = 
encode(new_static_extents);
 
  283      static constexpr uint64_t new_stride_order_encoded   = 
encode(new_stride_order);
 
  284      return std::make_pair(offset, idx_map<P, new_static_extents_encoded, new_stride_order_encoded, li>{len, str});
 
  313  template <
int R, uint64_t SE, uint64_t SO, 
layout_prop_e LP, 
typename... Args>
 
  316    static constexpr int n_args_ellipsis = ((std::is_same_v<Args, ellipsis>)+...);
 
  317    static constexpr int n_args_long     = (std::is_constructible_v<long, Args> + ...);
 
  320    static_assert(n_args_ellipsis <= 1, 
"Error in nda::slice_static::slice_idx_map: At most one ellipsis argument is allowed");
 
  321    static_assert((
sizeof...(Args) <= R + 1), 
"Error in nda::slice_static::slice_idx_map: Incorrect number of arguments");
 
  322    static_assert((n_args_ellipsis == 1) or (
sizeof...(Args) == R), 
"Error in nda::slice_static::slice_idx_map: Incorrect number of arguments");
 
  324    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.