10#ifndef XTENSOR_INDEX_MAPPER_HPP
11#define XTENSOR_INDEX_MAPPER_HPP
18 template <
class UndefinedView>
55 template <
class UnderlyingContainer,
class... Slices>
70 static constexpr size_t n_slices =
sizeof...(Slices);
82 template <std::integral... Indices>
92 template <std::integral... Indices>
102 template <std::integral... Indices>
104 cmap(
const UnderlyingContainer& container,
const view_type&
view,
const Indices... indices)
const;
113 template <std::integral... Indices>
123 template <std::integral... Indices>
128 size_t dimension(
const UnderlyingContainer& container)
const;
133 template <
bool IS_CONST>
134 using conditional_reference = std::conditional_t<IS_CONST, const_reference, reference>;
138 using slice_type = std::tuple_element_t<I, std::tuple<Slices...>>;
142 static consteval bool is_slice_integral();
146 static consteval bool is_slice_new_axis();
155 template <
size_t first,
size_t bound,
size_t... indices>
156 struct indices_sequence_helper
159 using not_new_axis_type =
typename indices_sequence_helper<first + 1, bound, indices..., first>::type;
162 using new_axis_type =
typename indices_sequence_helper<first + 1, bound, indices...>::type;
165 using type = std::conditional_t<is_slice_new_axis<first>(), new_axis_type, not_new_axis_type>;
169 template <
size_t bound,
size_t... indices>
170 struct indices_sequence_helper<bound, bound, indices...>
172 using type = std::index_sequence<indices...>;
176 template <
size_t bound>
177 using indices_sequence = indices_sequence_helper<0, bound>::type;
194 template <
size_t I, std::
integral Index>
195 size_t map_ith_index(
const view_type&
view,
const Index i)
const;
210 template <
bool IS_CONST,
access_t ACCESS, std::integral FirstIndice, std::integral... OtherIndices>
211 conditional_reference<IS_CONST> map_main(
212 std::bool_constant<IS_CONST> ,
213 std::conditional_t<IS_CONST, const UnderlyingContainer&, UnderlyingContainer&> container,
214 std::integral_constant<access_t, ACCESS> ,
215 const view_type&
view,
216 const FirstIndice firstIndice,
217 const OtherIndices... otherIndices
230 template <
bool IS_CONST, access_t ACCESS>
231 conditional_reference<IS_CONST> map_main(
232 std::bool_constant<IS_CONST> ,
233 std::conditional_t<IS_CONST, const UnderlyingContainer&, UnderlyingContainer&> container,
234 std::integral_constant<access_t, ACCESS> ,
235 const view_type&
view
252 template <
bool IS_CONST,
access_t ACCESS,
size_t n_indices,
size_t... Is>
253 conditional_reference<IS_CONST> map_all_indices(
254 std::bool_constant<IS_CONST> ,
255 std::conditional_t<IS_CONST, const UnderlyingContainer&, UnderlyingContainer&> container,
256 std::integral_constant<access_t, ACCESS> ,
257 const view_type&
view,
258 std::index_sequence<Is...> ,
259 const std::array<size_t, n_indices>& indices
263 template <std::integral... Indices>
264 std::array<size_t, n_indices_full_v<Indices...>> get_indices_full(
const Indices... indices)
const;
271 template <
class UnderlyingContainer,
class... Slices>
273 consteval bool index_mapper<xt::xview<UnderlyingContainer, Slices...>>::is_slice_integral()
275 if constexpr (I <
sizeof...(Slices))
277 return std::is_integral_v<slice_type<I>>;
285 template <
class UnderlyingContainer,
class... Slices>
287 consteval bool index_mapper<xt::xview<UnderlyingContainer, Slices...>>::is_slice_new_axis()
289 if constexpr (I <
sizeof...(Slices))
291 return xt::detail::is_newaxis_v<slice_type<I>>;
299 template <
class UnderlyingContainer,
class... Slices>
300 template <std::integral... Indices>
302 index_mapper<xt::xview<UnderlyingContainer, Slices...>>::get_indices_full(
const Indices... indices)
const
303 -> std::array<size_t, n_indices_full_v<Indices...>>
305 constexpr size_t n_indices_full = n_indices_full_v<Indices...>;
307 std::array<size_t,
sizeof...(indices)> args{size_t(indices)...};
308 std::array<size_t, n_indices_full> args_full;
310 const auto fill_args_full = [&args_full, &args]<
size_t... Is>(std::index_sequence<Is...>)
312 auto it = std::cbegin(args);
314 ((args_full[Is] = (is_slice_integral<Is>()) ? size_t(0) : *it++), ...);
317 fill_args_full(std::make_index_sequence<n_indices_full>{});
322 template <
class UnderlyingContainer,
class... Slices>
323 template <std::integral... Indices>
324 auto index_mapper<xt::xview<UnderlyingContainer, Slices...>>::map(
325 UnderlyingContainer& container,
326 const view_type&
view,
327 const Indices... indices
333 std::integral_constant<access_t, access_t::UNSAFE>{},
339 template <
class UnderlyingContainer,
class... Slices>
340 template <std::integral... Indices>
341 auto index_mapper<xt::xview<UnderlyingContainer, Slices...>>::cmap(
342 const UnderlyingContainer& container,
343 const view_type&
view,
344 const Indices... indices
345 )
const -> const_reference
350 std::integral_constant<access_t, access_t::UNSAFE>{},
356 template <
class UnderlyingContainer,
class... Slices>
357 template <std::integral... Indices>
358 auto index_mapper<xt::xview<UnderlyingContainer, Slices...>>::map_at(
359 UnderlyingContainer& container,
360 const view_type&
view,
361 const Indices... indices
367 std::integral_constant<access_t, access_t::SAFE>{},
373 template <
class UnderlyingContainer,
class... Slices>
374 template <std::integral... Indices>
375 auto index_mapper<xt::xview<UnderlyingContainer, Slices...>>::cmap_at(
376 const UnderlyingContainer& container,
377 const view_type&
view,
378 const Indices... indices
379 )
const -> const_reference
384 std::integral_constant<access_t, access_t::SAFE>{},
390 template <
class UnderlyingContainer,
class... Slices>
391 template <
bool IS_CONST,
access_t ACCESS, std::integral FirstIndice, std::integral... OtherIndices>
392 auto index_mapper<xt::xview<UnderlyingContainer, Slices...>>::map_main(
393 std::bool_constant<IS_CONST> is_const,
394 std::conditional_t<IS_CONST, const UnderlyingContainer&, UnderlyingContainer&> container,
395 std::integral_constant<access_t, ACCESS> access,
396 const view_type&
view,
397 const FirstIndice firstIndice,
398 const OtherIndices... otherIndices
399 )
const -> conditional_reference<IS_CONST>
401 constexpr size_t n_indices_full = n_indices_full_v<FirstIndice, OtherIndices...>;
403 constexpr size_t underlying_n_dimensions = xt::static_dimension<
404 typename std::decay_t<UnderlyingContainer>::shape_type>::value;
411 if constexpr (underlying_n_dimensions != size_t(-1))
414 constexpr size_t n_dimensions = underlying_n_dimensions - nb_integral_slices + nb_new_axis_slices;
417 if constexpr (1 +
sizeof...(OtherIndices) > n_dimensions)
419 return map_main(is_const, container, access,
view, otherIndices...);
423 return map_all_indices(
428 indices_sequence<n_indices_full>{},
429 get_indices_full(firstIndice, otherIndices...)
436 if (1 +
sizeof...(OtherIndices) > dimension(container))
438 return map_main(is_const, container, access,
view, otherIndices...);
442 return map_all_indices(
447 indices_sequence<n_indices_full>{},
448 get_indices_full(firstIndice, otherIndices...)
454 template <
class UnderlyingContainer,
class... Slices>
455 template <
bool IS_CONST, access_t ACCESS>
456 auto index_mapper<xt::xview<UnderlyingContainer, Slices...>>::map_main(
457 std::bool_constant<IS_CONST> is_const,
458 std::conditional_t<IS_CONST, const UnderlyingContainer&, UnderlyingContainer&> container,
459 std::integral_constant<access_t, ACCESS> access,
460 const view_type&
view
461 )
const -> conditional_reference<IS_CONST>
463 constexpr size_t n_indices_full = n_indices_full_v<>;
465 return map_all_indices(
470 indices_sequence<n_indices_full>{},
475 template <
class UnderlyingContainer,
class... Slices>
476 template <
bool IS_CONST,
access_t ACCESS,
size_t n_indices,
size_t... Is>
477 auto index_mapper<xt::xview<UnderlyingContainer, Slices...>>::map_all_indices(
478 std::bool_constant<IS_CONST> ,
479 std::conditional_t<IS_CONST, const UnderlyingContainer&, UnderlyingContainer&> container,
480 std::integral_constant<access_t, ACCESS> ,
481 const view_type&
view,
482 std::index_sequence<Is...> ,
483 const std::array<size_t, n_indices>& indices
484 )
const -> conditional_reference<IS_CONST>
488 return container.at(map_ith_index<Is>(
view, indices[Is])...);
492 return container(map_ith_index<Is>(
view, indices[Is])...);
496 template <
class UnderlyingContainer,
class... Slices>
497 template <
size_t I, std::
integral Index>
499 index_mapper<xt::xview<UnderlyingContainer, Slices...>>::map_ith_index(
const view_type&
view,
const Index i)
const
502 if constexpr (I <
sizeof...(Slices))
505 using current_slice = std::tuple_element_t<I, std::tuple<Slices...>>;
507 static_assert(not xt::detail::is_newaxis_v<current_slice>);
509 const auto& slice = std::get<I>(
view.slices());
511 if constexpr (std::is_integral_v<current_slice>)
514 return size_t(slice);
518 assert(i < slice.size());
519 return size_t(slice(i));
529 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.