Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
submdspan_extents.hpp
Go to the documentation of this file.
1// parasoft-begin-suppress AUTOSAR-A2_8_1-a-2 "False positive: also defines submdspan_extents"
2
3// Copyright 2026, Toyota Motor Corporation
4//
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
7#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_MDSPAN_SUBMDSPAN_EXTENTS_HPP_
8#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_MDSPAN_SUBMDSPAN_EXTENTS_HPP_
9
10#include "arene/base/compiler_support/cpp14_inline.hpp"
11#include "arene/base/constraints/constraints.hpp"
12#include "arene/base/mdspan/detail/canonical_slice.hpp"
13#include "arene/base/mdspan/detail/mandate_each_argtype_is_submdspan_slice.hpp"
14#include "arene/base/mdspan/detail/map_rank.hpp"
15#include "arene/base/mdspan/detail/to_array.hpp"
16#include "arene/base/mdspan/extents.hpp"
17#include "arene/base/mdspan/full_extent.hpp"
18#include "arene/base/mdspan/slice.hpp"
19#include "arene/base/mdspan/submdspan_canonicalize_slices.hpp"
20#include "arene/base/mdspan/submdspan_subextents_type.hpp"
21#include "arene/base/stdlib_choice/cstddef.hpp"
22#include "arene/base/stdlib_choice/enable_if.hpp"
23#include "arene/base/stdlib_choice/forward.hpp"
24#include "arene/base/stdlib_choice/integer_sequence.hpp"
25#include "arene/base/stdlib_choice/integral_constant.hpp"
26#include "arene/base/stdlib_choice/move.hpp"
27#include "arene/base/stdlib_choice/tuple.hpp"
28#include "arene/base/stdlib_choice/tuple_element.hpp"
29#include "arene/base/tuple/detail/get.hpp"
30#include "arene/base/tuple/detail/tuple_transform.hpp"
31#include "arene/base/type_traits/is_invocable.hpp"
32
33// parasoft-begin-suppress CERT_C-EXP37-a "False positive: The rule does not mention naming all parameters"
34// parasoft-begin-suppress AUTOSAR-M2_10_1-a "Similar identifiers permitted by M2-10-1 Permit #1 v1.0.0"
35
36namespace arene {
37namespace base {
38namespace submdspan_extents_detail {
39
40/// @brief filter tuple elements using a compile-time inverse mapping
41/// @tparam Is index sequence corresponding to the elements of the *filtered* tuple
42/// @tparam Tuple input tuple type
43/// @tparam LiftedInverseMapping compile-time inverse rank mapping
44/// @param tuple input tuple
45///
46/// Constructs a new @c std::tuple by selecting elements from @c tuple at the
47/// indices specified by @c LiftedInverseMapping::value.
48///
49/// @return tuple containing the selected elements
50///
51/// @note @c LiftedInverseMapping an @c inverse_map_rank lifted into type-space.
52/// Lifting the inverse mapping into type-space enables compile-time filtering
53/// of tuple elements by index.
54template <std::size_t... Is, class Tuple, class LiftedInverseMapping>
55constexpr auto filter_impl(std::index_sequence<Is...>, Tuple&& tuple, LiftedInverseMapping) noexcept
56 -> std::tuple<std::tuple_element_t<LiftedInverseMapping::value[Is], Tuple>...> {
57 return std::tuple<std::tuple_element_t<LiftedInverseMapping::value[Is], Tuple>...>{
58 tuple_detail::get<LiftedInverseMapping::value[Is]>(std::forward<Tuple>(tuple))...
59 };
60}
61
62/// @brief filter tuple elements using a compile-time inverse mapping
63/// @tparam Tuple input tuple type
64/// @tparam LiftedInverseMapping compile-time inverse rank mapping
65/// @param tuple input tuple
66/// @return tuple containing the selected elements
67///
68/// Creates a new tuple by selecting elements from @c tuple according to the
69/// indices specified by @c LiftedInverseMapping::value.
70///
71/// @note @c LiftedInverseMapping an @c inverse_map_rank lifted into type-space.
72/// Lifting the inverse mapping into type-space enables compile-time filtering
73/// of tuple elements by index.
74template <class Tuple, class LiftedInverseMapping>
75constexpr auto filter(Tuple tuple, LiftedInverseMapping) noexcept //
76 -> decltype(filter_impl(
77 std::make_index_sequence<LiftedInverseMapping::value.size()>{},
78 std::move(tuple),
79 LiftedInverseMapping{}
80 )) {
81 return filter_impl( //
82 std::make_index_sequence<LiftedInverseMapping::value.size()>{},
83 std::move(tuple),
84 LiftedInverseMapping{}
85 );
86}
87
88/// @brief compute the extents of a submdspan defined by slice specifiers
89///
90/// Given a source @c extents and a pack of submdspan slice specifiers, computes
91/// the extents of the resulting submdspan after applying the slices.
92///
93/// The slice specifiers are first converted to canonical form using
94/// @c submdspan_canonicalize_slices, and the resulting canonical slices are then
95/// used to determine the rank and extent values of the submdspan.
96class submdspan_extents_fn {
97 /// @brief function object to compute extent values for canonical non-collapsing slices
98 class extent_from_slice {
99 public:
100 /// @brief compute the sliced extent value from an @c extent_slice
101 /// @tparam IndexType index type
102 /// @tparam Offset @c extent_slice offset type
103 /// @tparam Extent @c extent_slice extent type
104 /// @tparam Stride @c extent_slice stride type
105 /// @param slice canonical extent slice
106 /// @return extent value of the slice
107 template <class IndexType, class Offset, class Extent, class Stride>
108 constexpr auto operator()(IndexType const&, extent_slice<Offset, Extent, Stride> slice) const noexcept
109 -> IndexType {
110 return slice.extent;
111 }
112
113 /// @brief propagate the original extent for a full slice
114 /// @tparam IndexType index type
115 /// @param ext original extent
116 /// @return unchanged extent value
117 template <class IndexType>
118 constexpr auto operator()(IndexType const& ext, full_extent_t) const noexcept -> IndexType {
119 return ext;
120 }
121 };
122
123 public:
124 // parasoft-begin-suppress AUTOSAR-A0_1_4-a "False positive: parameters 'src' and 'slices' are used"
125 /// @brief compute submdspan extents from slice specifiers
126 ///
127 /// @tparam IndexType index type of the source extents
128 /// @tparam Extents static extent values of the source extents
129 /// @tparam SliceSpecifiers submdspan slice specifier types
130 ///
131 /// @param src source @c extents to slice
132 /// @param slices submdspan slice specifiers
133 ///
134 /// Canonicalizes @c slices with a call to
135 /// <c> submdspan_canonicalize_slices(src, slices...) </c>,
136 /// and uses the resulting canonical slices to determine the rank and extent
137 /// values of the submdspan.
138 ///
139 /// Returns an @c extents specialization describing the extents of the
140 /// submdspan obtained by applying the canonical slices to @c src.
141 ///
142 /// @return A value @c ext of type
143 /// @c submdspan_subextents_type_t<Extents, SliceSpecifiers...> that, for each
144 /// rank index @c k of @c extents<IndexType, Extents...> where the type of the
145 /// canonical slice @c canonical...[k] is not a collapsing slice type, the
146 /// following holds.
147 /// Let @c sk denote @c canonical...[k], and let @c r denote
148 /// <c> MAP_RANK(canonical, k) </c>:
149 /// * if the type of @c sk is a specialization of @c extent_slice,
150 /// <c> ext.extent(r) </c> equals @c sk.extent;
151 /// * otherwise, <c> ext.extent(r) </c> equals <c> U - L </c>, where
152 /// <c> [L, U) </c> is the submdspan slice range denoted by @c sk for the
153 /// @c k-th extent of @c src.
154 ///
155 /// @note Constraints <br>
156 /// * <c> sizeof...(Extents) == sizeof...(SliceSpecifiers) </c>
157 ///
158 /// @note Mandates <br>
159 /// * for each rank index @c k of @c src, @c SliceSpecifiers...[k] is a valid
160 /// submdspan slice type for @c IndexType
161 /// * the canonical form of each slice specifier is a valid submdspan slice
162 /// type for the associated static extent of @c src
163 ///
164 /// @note Preconditions <br>
165 /// * for each rank index @c k of @c src, the canonical slice
166 /// @c slices...[k] denotes a valid submdspan slice for the @c k-th extent
167 /// of @c src
168 ///
169 /// @note Remarks <br>
170 /// * the rank of the returned extents is equal to
171 /// <c> MAP_RANK(slices, extents::rank()) </c>
172 template <
173 class IndexType,
174 std::size_t... Extents,
175 class... SliceSpecifiers,
176 constraints<std::enable_if_t<sizeof...(Extents) == sizeof...(SliceSpecifiers)>> = nullptr,
177 std::nullptr_t = mdspan_detail::mandate_each_argtype_is_submdspan_slice<IndexType, SliceSpecifiers...>()
178 >
179 constexpr auto operator()(extents<IndexType, Extents...> const& src, SliceSpecifiers... slices) const noexcept( //
180 is_nothrow_invocable_v<
181 decltype(submdspan_canonicalize_slices),
182 extents<IndexType, Extents...> const& ,
183 SliceSpecifiers&&...>
184 ) -> submdspan_subextents_type_t<extents<IndexType, Extents...>, SliceSpecifiers...> {
185 // parasoft-begin-suppress AUTOSAR-M0_1_3-a "False positive: 'lifted_inverse_mapping' is used"
186 // parasoft-begin-suppress AUTOSAR-M0_1_3-b "False positive: 'lifted_inverse_mapping' is used"
187 // Lift the inverse mapping into type-space so we can determine which elements of the tuple can be filtered out.
188 constexpr auto lifted_inverse_mapping = std::integral_constant<
189 decltype((mdspan_detail::inverse_map_rank<mdspan_detail::canonical_slice_t<IndexType, SliceSpecifiers>...>)),
190 mdspan_detail::inverse_map_rank<mdspan_detail::canonical_slice_t<IndexType, SliceSpecifiers>...>>{};
191 // parasoft-end-suppress AUTOSAR-M0_1_3-a
192 // parasoft-end-suppress AUTOSAR-M0_1_3-b
193
194 // parasoft-begin-suppress AUTOSAR-A8_4_2-a "False positive: function does have a return"
195 // parasoft-begin-suppress CERT_C-MSC37-a "False positive: function does have a return"
196 // parasoft-begin-suppress CERT_CPP-MSC52-a "False positive: function does have a return"
197 return submdspan_subextents_type_t<extents<IndexType, Extents...>, SliceSpecifiers...>{
198 tuple_detail::tuple_transform_to_array<IndexType>(
199 filter(mdspan_detail::to_array(src), lifted_inverse_mapping),
200 filter(submdspan_canonicalize_slices(src, std::move(slices)...), lifted_inverse_mapping),
201 extent_from_slice{}
202 )
203 };
204 // parasoft-end-suppress AUTOSAR-A8_4_2-a
205 // parasoft-end-suppress CERT_C-MSC37-a
206 // parasoft-end-suppress CERT_CPP-MSC52-a
207 }
208 // parasoft-end-suppress AUTOSAR-A0_1_4-a
209};
210
211} // namespace submdspan_extents_detail
212
213/// @def arene::base::submdspan_extents
214/// @copydoc arene::base::submdspan_extents_detail::submdspan_extents_fn::operator()
215// parasoft-begin-suppress AUTOSAR-M7_3_3-a "An unnamed namespace is used to create a per-TU reference to a global
216// object used in multiple TUs."
217// parasoft-begin-suppress CERT_CPP-DCL59-a "An unnamed namespace is used to create a per-TU reference to a global
218// object used in multiple TUs."
219ARENE_CPP14_INLINE_VARIABLE(submdspan_extents_detail::submdspan_extents_fn, submdspan_extents);
220// parasoft-end-suppress AUTOSAR-M7_3_3-a
221// parasoft-end-suppress CERT_CPP-DCL59-a
222
223} // namespace base
224} // namespace arene
225
226#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_MDSPAN_SUBMDSPAN_EXTENTS_HPP_
Definition array_exceptions_disabled.cpp:11
ARENE_CPP14_INLINE_VARIABLE(submdspan_extents_detail::submdspan_extents_fn, submdspan_extents)
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10