10#ifndef XTENSOR_INDEX_MAPPER_HPP
11#define XTENSOR_INDEX_MAPPER_HPP
20 template <
class UndefinedView>
57 template <
class UnderlyingContainer,
class... Slices>
72 static constexpr size_t n_slices =
sizeof...(Slices);
84 template <std::integral... Indices>
94 template <std::integral... Indices>
104 template <std::integral... Indices>
106 cmap(
const UnderlyingContainer& container,
const view_type&
view,
const Indices... indices)
const;
115 template <std::integral... Indices>
125 template <std::integral... Indices>
130 size_t dimension(
const UnderlyingContainer& container)
const;
135 template <
bool IS_CONST>
136 using conditional_reference = std::conditional_t<IS_CONST, const_reference, reference>;
140 using slice_type = std::tuple_element_t<I, std::tuple<Slices...>>;
144 static consteval bool is_slice_integral();
148 static consteval bool is_slice_new_axis();
157 template <
size_t first,
size_t bound,
size_t... indices>
158 struct indices_sequence_helper
161 using not_new_axis_type =
typename indices_sequence_helper<first + 1, bound, indices..., first>::type;
164 using new_axis_type =
typename indices_sequence_helper<first + 1, bound, indices...>::type;
167 using type = std::conditional_t<is_slice_new_axis<first>(), new_axis_type, not_new_axis_type>;
171 template <
size_t bound,
size_t... indices>
172 struct indices_sequence_helper<bound, bound, indices...>
174 using type = std::index_sequence<indices...>;
178 template <
size_t bound>
179 using indices_sequence = indices_sequence_helper<0, bound>::type;
196 template <
size_t I, std::
integral Index>
197 size_t map_ith_index(
const view_type&
view,
const Index i)
const;
212 template <
bool IS_CONST,
access_t ACCESS, std::integral FirstIndice, std::integral... OtherIndices>
213 conditional_reference<IS_CONST> map_main(
214 std::bool_constant<IS_CONST> ,
215 std::conditional_t<IS_CONST, const UnderlyingContainer&, UnderlyingContainer&> container,
216 std::integral_constant<access_t, ACCESS> ,
217 const view_type&
view,
218 const FirstIndice firstIndice,
219 const OtherIndices... otherIndices
232 template <
bool IS_CONST, access_t ACCESS>
233 conditional_reference<IS_CONST> map_main(
234 std::bool_constant<IS_CONST> ,
235 std::conditional_t<IS_CONST, const UnderlyingContainer&, UnderlyingContainer&> container,
236 std::integral_constant<access_t, ACCESS> ,
237 const view_type&
view
254 template <
bool IS_CONST,
access_t ACCESS,
size_t n_indices,
size_t... Is>
255 conditional_reference<IS_CONST> map_all_indices(
256 std::bool_constant<IS_CONST> ,
257 std::conditional_t<IS_CONST, const UnderlyingContainer&, UnderlyingContainer&> container,
258 std::integral_constant<access_t, ACCESS> ,
259 const view_type&
view,
260 std::index_sequence<Is...> ,
261 const std::array<size_t, n_indices>& indices
265 template <std::integral... Indices>
266 std::array<size_t, n_indices_full_v<Indices...>> get_indices_full(
const Indices... indices)
const;
273 template <
class UnderlyingContainer,
class... Slices>
275 consteval bool index_mapper<xt::xview<UnderlyingContainer, Slices...>>::is_slice_integral()
277 if constexpr (I <
sizeof...(Slices))
279 return std::is_integral_v<slice_type<I>>;
287 template <
class UnderlyingContainer,
class... Slices>
289 consteval bool index_mapper<xt::xview<UnderlyingContainer, Slices...>>::is_slice_new_axis()
291 if constexpr (I <
sizeof...(Slices))
293 return xt::detail::is_newaxis_v<slice_type<I>>;
301 template <
class UnderlyingContainer,
class... Slices>
302 template <std::integral... Indices>
304 index_mapper<xt::xview<UnderlyingContainer, Slices...>>::get_indices_full(
const Indices... indices)
const
305 -> std::array<size_t, n_indices_full_v<Indices...>>
307 constexpr size_t n_indices_full = n_indices_full_v<Indices...>;
309 std::array<size_t,
sizeof...(indices)> args{size_t(indices)...};
310 std::array<size_t, n_indices_full> args_full;
312 const auto fill_args_full = [&args_full, &args]<
size_t... Is>(std::index_sequence<Is...>)
314 auto it = std::cbegin(args);
316 ((args_full[Is] = (is_slice_integral<Is>()) ? size_t(0) : *it++), ...);
319 fill_args_full(std::make_index_sequence<n_indices_full>{});
324 template <
class UnderlyingContainer,
class... Slices>
325 template <std::integral... Indices>
326 auto index_mapper<xt::xview<UnderlyingContainer, Slices...>>::map(
327 UnderlyingContainer& container,
328 const view_type&
view,
329 const Indices... indices
335 std::integral_constant<access_t, access_t::UNSAFE>{},
341 template <
class UnderlyingContainer,
class... Slices>
342 template <std::integral... Indices>
343 auto index_mapper<xt::xview<UnderlyingContainer, Slices...>>::cmap(
344 const UnderlyingContainer& container,
345 const view_type&
view,
346 const Indices... indices
347 )
const -> const_reference
352 std::integral_constant<access_t, access_t::UNSAFE>{},
358 template <
class UnderlyingContainer,
class... Slices>
359 template <std::integral... Indices>
360 auto index_mapper<xt::xview<UnderlyingContainer, Slices...>>::map_at(
361 UnderlyingContainer& container,
362 const view_type&
view,
363 const Indices... indices
369 std::integral_constant<access_t, access_t::SAFE>{},
375 template <
class UnderlyingContainer,
class... Slices>
376 template <std::integral... Indices>
377 auto index_mapper<xt::xview<UnderlyingContainer, Slices...>>::cmap_at(
378 const UnderlyingContainer& container,
379 const view_type&
view,
380 const Indices... indices
381 )
const -> const_reference
386 std::integral_constant<access_t, access_t::SAFE>{},
392 template <
class UnderlyingContainer,
class... Slices>
393 template <
bool IS_CONST,
access_t ACCESS, std::integral FirstIndice, std::integral... OtherIndices>
394 auto index_mapper<xt::xview<UnderlyingContainer, Slices...>>::map_main(
395 std::bool_constant<IS_CONST> is_const,
396 std::conditional_t<IS_CONST, const UnderlyingContainer&, UnderlyingContainer&> container,
397 std::integral_constant<access_t, ACCESS> access,
398 const view_type&
view,
399 const FirstIndice firstIndice,
400 const OtherIndices... otherIndices
401 )
const -> conditional_reference<IS_CONST>
403 constexpr size_t n_indices_full = n_indices_full_v<FirstIndice, OtherIndices...>;
405 constexpr size_t underlying_n_dimensions =
static_cast<size_t>(
406 xt::static_dimension<typename std::decay_t<UnderlyingContainer>::shape_type>::value
414 if constexpr (underlying_n_dimensions != size_t(-1))
417 constexpr size_t n_dimensions = underlying_n_dimensions - nb_integral_slices + nb_new_axis_slices;
420 if constexpr (1 +
sizeof...(OtherIndices) > n_dimensions)
422 return map_main(is_const, container, access,
view, otherIndices...);
426 return map_all_indices(
431 indices_sequence<n_indices_full>{},
432 get_indices_full(firstIndice, otherIndices...)
439 if (1 +
sizeof...(OtherIndices) > dimension(container))
441 return map_main(is_const, container, access,
view, otherIndices...);
445 return map_all_indices(
450 indices_sequence<n_indices_full>{},
451 get_indices_full(firstIndice, otherIndices...)
457 template <
class UnderlyingContainer,
class... Slices>
458 template <
bool IS_CONST, access_t ACCESS>
459 auto index_mapper<xt::xview<UnderlyingContainer, Slices...>>::map_main(
460 std::bool_constant<IS_CONST> is_const,
461 std::conditional_t<IS_CONST, const UnderlyingContainer&, UnderlyingContainer&> container,
462 std::integral_constant<access_t, ACCESS> access,
463 const view_type&
view
464 )
const -> conditional_reference<IS_CONST>
468 constexpr size_t n_indices_full = nb_integral_slices;
470 return map_all_indices(
475 indices_sequence<n_indices_full>{},
480 template <
class UnderlyingContainer,
class... Slices>
481 template <
bool IS_CONST,
access_t ACCESS,
size_t n_indices,
size_t... Is>
482 auto index_mapper<xt::xview<UnderlyingContainer, Slices...>>::map_all_indices(
483 std::bool_constant<IS_CONST> ,
484 std::conditional_t<IS_CONST, const UnderlyingContainer&, UnderlyingContainer&> container,
485 std::integral_constant<access_t, ACCESS> ,
486 const view_type&
view,
487 std::index_sequence<Is...> ,
488 const std::array<size_t, n_indices>& indices
489 )
const -> conditional_reference<IS_CONST>
493 return container.at(map_ith_index<Is>(
view, indices[Is])...);
497 return container(map_ith_index<Is>(
view, indices[Is])...);
501 template <
class UnderlyingContainer,
class... Slices>
502 template <
size_t I, std::
integral Index>
504 index_mapper<xt::xview<UnderlyingContainer, Slices...>>::map_ith_index(
const view_type&
view,
const Index i)
const
507 if constexpr (I <
sizeof...(Slices))
510 using current_slice = std::tuple_element_t<I, std::tuple<Slices...>>;
512 static_assert(not xt::detail::is_newaxis_v<current_slice>);
514 const auto& slice = std::get<I>(
view.slices());
516 if constexpr (std::is_integral_v<current_slice>)
519 return size_t(slice);
523 using slice_size_type =
typename current_slice::size_type;
524 assert(i < slice.size());
525 return size_t(slice(
static_cast<slice_size_type
>(i)));
535 template <
class UnderlyingContainer,
class... Slices>
xt::xview< UnderlyingContainer, Slices... > view_type
The view type this mapper works with.
static constexpr size_t nb_integral_slices
Number of slices that are integral constants (fixed indices)
typename xt::xview< UnderlyingContainer, Slices... >::const_reference const_reference
Const reference type of the underlying view.
const_reference cmap_at(const UnderlyingContainer &container, const view_type &view, const Indices... indices) const
Map view indices to container const_reference using SAFE access.
typename xt::xview< UnderlyingContainer, Slices... >::reference reference
Reference type of the underlying view.
size_t dimension(const UnderlyingContainer &container) const
Return the dimensionality of the view.
const_reference cmap(const UnderlyingContainer &container, const view_type &view, const Indices... indices) const
Map view indices to container const_reference using UNSAFE access.
static constexpr size_t nb_new_axis_slices
Number of slices that are xt::newaxis (insert a dimension)
static constexpr size_t n_indices_full_v
Compute how many indices are needed to address the underlying container when given N indices in the v...
static constexpr size_t n_slices
Total number of explicitly passed slices in the view.
reference map_at(UnderlyingContainer &container, const view_type &view, const Indices... indices) const
Map view indices to container reference using SAFE access.
reference map(UnderlyingContainer &container, const view_type &view, const Indices... indices) const
Map view indices to container reference using UNSAFE access.
Multidimensional view with tensor semantic.
standard mathematical functions for xexpressions
access_t
Defines the access policy for the underlying container.
@ UNSAFE
Use operator() accessor (no bounds checking).
@ SAFE
Use .at() accessor (bounds checked).
auto view(E &&e, S &&... slices)
Constructs and returns a view on the specified xexpression.
A helper class for mapping indices between views and their underlying containers.