5#ifndef DUNE_COMMON_STD_IMPL_SUBMDSPAN_HH
6#define DUNE_COMMON_STD_IMPL_SUBMDSPAN_HH
24namespace Dune::Std::Impl {
32constexpr auto slice_index (T value)
34 if constexpr(is_integral_constant_v<T>)
44struct IsFullExtent :
std::is_same<std::remove_cv_t<T>,full_extent_t> {};
47inline constexpr bool is_full_extent_v = IsFullExtent<T>::value;
52template <
class O,
class E,
class S>
56inline constexpr bool is_extent_slice_v = IsExtentSlice<std::remove_cv_t<T>>::value;
61template <
class F,
class L,
class S>
65inline constexpr bool is_range_slice_v = IsRangeSlice<std::remove_cv_t<T>>::value;
67template <
class T,
class =
void>
72 decltype(std::tuple_size<std::remove_cv_t<T>>::value),
73 typename std::tuple_element<0,std::remove_cv_t<T>>::type,
74 typename std::tuple_element<1,std::remove_cv_t<T>>::type>>
78inline constexpr bool is_pair_like_v = IsPairLike<T>::value;
81inline constexpr bool is_kept_slice_v =
82 is_full_extent_v<Slice> || is_extent_slice_v<Slice> || is_range_slice_v<Slice> || is_pair_like_v<Slice>;
86template <
class Slice,
class =
void>
87struct IsContiguousKeptSlice : IsFullExtent<Slice> {};
90struct IsContiguousKeptSlice<T,
std::enable_if_t<is_pair_like_v<T>>> :
std::true_type {};
92template <
class Str
ide,
bool = is_
integral_constant_v<Str
ide>>
95template <
class Str
ide>
98template <
class First,
class Last,
class Str
ide>
99struct IsContiguousKeptSlice<
range_slice<First,Last,Stride>>
100 : IsUnitStride<Stride>
103template <
class Offset,
class Extent,
class Str
ide>
104struct IsContiguousKeptSlice<
extent_slice<Offset,Extent,Stride>>
105 : IsUnitStride<Stride>
108template <
class Slice>
109inline constexpr bool is_contiguous_kept_slice_v =
110 IsContiguousKeptSlice<std::remove_cv_t<std::remove_reference_t<Slice>>>::value;
113template <
class Slice,
class IndexType>
114constexpr IndexType slice_offset (
const Slice& slice)
116 if constexpr(is_full_extent_v<Slice>)
118 else if constexpr(is_extent_slice_v<Slice>)
119 return IndexType(slice_index(slice.offset));
120 else if constexpr(is_range_slice_v<Slice>)
121 return IndexType(slice_index(slice.first));
122 else if constexpr(is_pair_like_v<Slice>)
123 return IndexType(std::get<0>(slice));
125 return IndexType(slice_index(slice));
129template <
class Slice,
class IndexType>
130constexpr IndexType slice_stride (
const Slice& slice)
132 if constexpr(is_extent_slice_v<Slice>)
133 return IndexType(slice_index(slice.stride));
134 else if constexpr(is_range_slice_v<Slice>)
135 return IndexType(slice_index(slice.stride));
141template <std::
size_t k,
class Extents,
class Slice>
142constexpr typename Extents::index_type slice_extent (
const Extents& extents,
const Slice& slice)
144 using index_type =
typename Extents::index_type;
145 if constexpr(is_full_extent_v<Slice>)
146 return extents.extent(k);
147 else if constexpr(is_extent_slice_v<Slice>)
148 return index_type(slice_index(slice.extent));
149 else if constexpr(is_range_slice_v<Slice>)
150 return (index_type(slice_index(slice.last)) - index_type(slice_index(slice.first))
151 + index_type(slice_index(slice.stride)) - 1) / index_type(slice_index(slice.stride));
153 return index_type(std::get<1>(slice)) - index_type(std::get<0>(slice));
158template <std::
size_t k,
class Extents,
class Slice>
159struct StaticSliceExtent
163template <std::
size_t k,
class Extents>
164struct StaticSliceExtent<k,Extents,full_extent_t>
169struct StaticValueOrDynamic
173template <
class T, T value>
174struct StaticValueOrDynamic<
std::integral_constant<T,value>>
178template <
class First,
class Last,
class Str
ide,
bool = is_
integral_constant_v<First> && is_
integral_constant_v<Last> && is_
integral_constant_v<Str
ide>>
179struct StaticRangeExtent
183template <
class First,
class Last,
class Str
ide>
184struct StaticRangeExtent<First,Last,Stride,true>
186 std::size_t((Last::value - First::value + Stride::value - 1) / Stride::value)>
189template <std::
size_t k,
class Extents,
class Offset,
class SliceExtent,
class Str
ide>
190struct StaticSliceExtent<k,Extents,
extent_slice<Offset,SliceExtent,Stride>>
191 : StaticValueOrDynamic<SliceExtent>
194template <std::
size_t k,
class Extents,
class First,
class Last,
class Str
ide>
195struct StaticSliceExtent<k,Extents,
range_slice<First,Last,Stride>>
196 : StaticRangeExtent<First,Last,Stride>
201template <
class IndexType,
class ExtentsSeq,
class SrcExtents,
std::size_t k,
class... Slices>
202struct SubextentsImpl;
205struct SubextentsImpl<IndexType,
std::integer_sequence<std::size_t,exts...>, SrcExtents, k>
207 using type = Std::extents<IndexType,exts...>;
210template <
class IndexType,
std::size_t... exts,
class SrcExtents,
std::size_t k,
class Slice0,
class... Slices>
211struct SubextentsImpl<IndexType,
std::integer_sequence<std::size_t,exts...>, SrcExtents, k, Slice0, Slices...>
214 is_kept_slice_v<Slice0>,
218 using type =
typename SubextentsImpl<IndexType,next_seq,SrcExtents,k+1,Slices...>::type;
221template <
class Extents,
class... Slices>
222using SubextentsType =
typename SubextentsImpl<
223 typename Extents::index_type,
229template <
class Layout>
230struct LayoutLeftPadding
234template <std::
size_t PaddingValue>
235struct LayoutLeftPadding<layout_left_padded<PaddingValue>>
239template <
class Layout>
240struct LayoutRightPadding
244template <std::
size_t PaddingValue>
245struct LayoutRightPadding<layout_right_padded<PaddingValue>>
249template <
class Layout>
250inline constexpr bool is_padded_layout_v =
251 is_layout_left_padded_v<Layout> || is_layout_right_padded_v<Layout>;
256template <
class Layout,
class SlicesTuple,
std::size_t... i>
259 if constexpr(!std::is_same_v<Layout,layout_right>)
262 constexpr bool kept[] = {is_kept_slice_v<std::tuple_element_t<i,SlicesTuple>>...};
263 constexpr bool full[] = {is_full_extent_v<std::tuple_element_t<i,SlicesTuple>>...};
264 bool seenKept =
false;
277template <
class Layout,
class SlicesTuple,
std::size_t... i>
280 if constexpr(!std::is_same_v<Layout,layout_left>)
283 constexpr bool kept[] = {is_kept_slice_v<std::tuple_element_t<i,SlicesTuple>>...};
284 constexpr bool full[] = {is_full_extent_v<std::tuple_element_t<i,SlicesTuple>>...};
285 bool seenFixed =
false;
288 if (seenFixed || !full[k])
301template <
class Layout,
class SlicesTuple,
std::size_t... i>
305 if constexpr(!(std::is_same_v<Layout,layout_left> || is_layout_left_padded_v<Layout>) || rank < 2)
308 constexpr bool contiguous[] = {is_contiguous_kept_slice_v<std::tuple_element_t<i,SlicesTuple>>...};
309 constexpr bool full[] = {is_full_extent_v<std::tuple_element_t<i,SlicesTuple>>...};
310 if (!contiguous[0] || !contiguous[1])
312 if constexpr(rank > 2 && !full[1])
324template <
class Layout,
class SlicesTuple,
std::size_t... i>
328 if constexpr(!(std::is_same_v<Layout,layout_right> || is_layout_right_padded_v<Layout>) || rank < 2)
331 constexpr bool contiguous[] = {is_contiguous_kept_slice_v<std::tuple_element_t<i,SlicesTuple>>...};
332 constexpr bool full[] = {is_full_extent_v<std::tuple_element_t<i,SlicesTuple>>...};
336 if constexpr(rank > 2 && !full[rank-2])
338 return contiguous[rank-2] && contiguous[rank-1];
342template <
class Layout,
class Extents>
343struct SubLayoutLeftPadded
346 if constexpr(is_layout_left_padded_v<Layout>)
347 return LayoutLeftPadding<Layout>::value;
348 else if constexpr(Extents::rank() > 0 && Extents::static_extent(0) != std::dynamic_extent)
349 return Extents::static_extent(0);
351 return std::dynamic_extent;
354 using type = layout_left_padded<padding>;
357template <
class Layout,
class Extents>
358struct SubLayoutRightPadded
361 if constexpr(is_layout_right_padded_v<Layout>)
362 return LayoutRightPadding<Layout>::value;
363 else if constexpr(Extents::rank() > 0 && Extents::static_extent(Extents::rank()-1) != std::dynamic_extent)
364 return Extents::static_extent(Extents::rank()-1);
366 return std::dynamic_extent;
369 using type = layout_right_padded<padding>;
372template <
class Layout,
class Extents,
class... Slices>
390template <
class Mapping,
class... Slices,
std::size_t... k>
393 using src_extents_type =
typename Mapping::extents_type;
394 using index_type =
typename Mapping::index_type;
395 using sub_extents_type = SubextentsType<src_extents_type,Slices...>;
396 using sub_layout_type =
typename SubLayout<
typename Mapping::layout_type,src_extents_type,Slices...>::type;
397 using sub_mapping_type =
typename sub_layout_type::template mapping<sub_extents_type>;
399 constexpr std::size_t rank = src_extents_type::rank();
400 constexpr std::size_t subrank = sub_extents_type::rank();
402 const auto& src_extents = mapping.extents();
408 auto add_kept = [&](
auto kk) {
410 using slice_type = std::tuple_element_t<i,
std::tuple<Slices...>>;
411 if constexpr(is_kept_slice_v<slice_type>) {
412 const auto& slice = std::get<i>(slices);
413 sub_exts[j] = slice_extent<i>(src_extents, slice);
414 sub_strides[j] = mapping.stride(i) * slice_stride<slice_type,index_type>(slice);
421 return mapping(offsets[i]...);
424 sub_extents_type sub_extents{sub_exts};
426 if constexpr(std::is_same_v<sub_layout_type,layout_stride>) {
427 return submdspan_mapping_result<sub_mapping_type>{
428 sub_mapping_type{sub_extents, sub_strides}, offset};
429 }
else if constexpr(is_padded_layout_v<sub_layout_type>) {
430 using strided_mapping_type =
typename layout_stride::template mapping<sub_extents_type>;
431 return submdspan_mapping_result<sub_mapping_type>{
432 sub_mapping_type{strided_mapping_type{sub_extents, sub_strides}}, offset};
434 return submdspan_mapping_result<sub_mapping_type>{
435 sub_mapping_type{sub_extents}, offset};
Traits for type conversions and type information.
decltype(auto) constexpr unpackIntegerSequence(F &&f, std::integer_sequence< I, i... > sequence)
Unpack an std::integer_sequence<I,i...> to std::integral_constant<I,i>...
Definition indices.hh:124
typename Impl::voider< Types... >::type void_t
Is void for all valid input types. The workhorse for C++11 SFINAE-techniques.
Definition typetraits.hh:40
extent_slice(OffsetType, ExtentType, StrideType) -> extent_slice< OffsetType, ExtentType, StrideType >
range_slice(FirstType, LastType) -> range_slice< FirstType, LastType >
Check if T is an std::integral_constant<I, i>
Definition typetraits.hh:384