This patch add a range_slice a class, and maps it to strided_slice
with the original meanning. This is usefull for benchmark, as effects
of strided_slice remain stable before and after the change.
libstdc++-v3/ChangeLog:
* include/std/mdspan (range_slice, __mdspan::__is_range_slice):
Define.
(__mdspan::__slice_cast): Handle strided_slice.
* testsuite/23_containers/mdspan/submdspan/submdspan_extents.cc:
Sanity tests for range_slice.
---
libstdc++-v3/include/std/mdspan | 33 ++++++++
.../mdspan/submdspan/submdspan_extents.cc | 82 +++++++++++++++++++
2 files changed, 115 insertions(+)
diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
index cedf597d3c2..570c1c0bda8 100644
--- a/libstdc++-v3/include/std/mdspan
+++ b/libstdc++-v3/include/std/mdspan
@@ -368,6 +368,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
[[no_unique_address]] stride_type stride{};
};
+ template<typename _FirstType, typename _LastType, typename _StrideType =
constant_wrapper<1zu>>
+ struct range_slice
+ {
+ static_assert(__is_signed_or_unsigned_integer<_FirstType>::value
+ || __detail::__integral_constant_like<_FirstType>);
+ static_assert(__is_signed_or_unsigned_integer<_LastType>::value
+ || __detail::__integral_constant_like<_LastType>);
+ static_assert(__is_signed_or_unsigned_integer<_StrideType>::value
+ || __detail::__integral_constant_like<_StrideType>);
+
+ [[no_unique_address]] _FirstType first{};
+ [[no_unique_address]] _LastType last{};
+ [[no_unique_address]] _StrideType stride{};
+ };
+
template<typename _Mapping>
struct submdspan_mapping_result
{
@@ -864,6 +879,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr bool __is_strided_slice<strided_slice<_OffsetType,
_ExtentType, _StrideType>> = true;
+ template<typename _Tp>
+ constexpr bool __is_range_slice = false;
+
+ template<typename _FirstType, typename _LastType, typename _StrideType>
+ constexpr bool __is_range_slice<range_slice<_FirstType,
+ _LastType, _StrideType>> = true;
+
template<typename _IndexType, typename _OIndexType>
consteval bool
__is_representable_integer(_OIndexType __value)
@@ -3244,6 +3266,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
=
__mdspan::__canonical_index<_IndexType>(std::move(__slice.stride))
};
}
+ else if constexpr (__is_range_slice<_SliceType>)
+ {
+ auto __first
+ =
__mdspan::__canonical_index<_IndexType>(std::move(__slice.first));
+ auto __last
+ =
__mdspan::__canonical_index<_IndexType>(std::move(__slice.last));
+ auto __stride
+ =
__mdspan::__canonical_index<_IndexType>(std::move(__slice.stride));
+ return __mdspan::__slice_cast<_IndexType>(
+ strided_slice{__first, __last - __first, __stride});
+ }
else
{
auto [__sbegin, __send] = std::move(__slice);
diff --git
a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_extents.cc
b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_extents.cc
index 841910a77c8..6210161ffd8 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_extents.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_extents.cc
@@ -134,6 +134,86 @@ template<template<int> typename Cw>
return true;
}
+template<template<int> typename Cw>
+ constexpr bool
+ test_from_range_slice()
+ {
+ auto exts = std::extents<int, 5, 7, 11>{};
+ {
+ auto s0 = 1;
+ auto s1 = std::range_slice{0, 0, 0};
+ auto s2 = std::range_slice{Cw<1>{}, Cw<1>{}, 0};
+ auto sub_exts = submdspan_extents(exts, s0, s1, s2);
+ VERIFY(sub_exts.rank() == 2);
+ VERIFY(sub_exts.static_extent(0) == dyn);
+ VERIFY(sub_exts.extent(0) == 0);
+ VERIFY(sub_exts.static_extent(1) == 0);
+ }
+
+ {
+ auto s0 = 1;
+ auto s1 = std::range_slice{0, 2, Cw<1>{}};
+ auto s2 = std::range_slice{1, Cw<3>{}};
+ auto sub_exts = submdspan_extents(exts, s0, s1, s2);
+ VERIFY(sub_exts.rank() == 2);
+ VERIFY(sub_exts.static_extent(0) == dyn);
+ VERIFY(sub_exts.extent(0) == 2);
+ VERIFY(sub_exts.static_extent(1) == dyn);
+ VERIFY(sub_exts.extent(1) == 2);
+ }
+
+ {
+ auto s0 = 1;
+ auto s1 = std::range_slice{0, 2, Cw<1>{}};
+ auto s2 = std::range_slice{Cw<1>{}, Cw<3>{}, 1};
+ auto sub_exts = submdspan_extents(exts, s0, s1, s2);
+ VERIFY(sub_exts.rank() == 2);
+ VERIFY(sub_exts.static_extent(0) == dyn);
+ VERIFY(sub_exts.extent(0) == 2);
+ VERIFY(sub_exts.static_extent(1) == dyn);
+ VERIFY(sub_exts.extent(1) == 2);
+ }
+
+ {
+ // selected = 1 x [1, 3] x [1, 4, 7, 10]
+ auto s0 = 1;
+ auto s1 = std::range_slice{1, Cw<5>{}, 2};
+ auto s2 = std::range_slice{1, Cw<11>{}, Cw<3>{}};
+ auto sub_exts = submdspan_extents(exts, s0, s1, s2);
+ VERIFY(sub_exts.rank() == 2);
+ VERIFY(sub_exts.static_extent(0) == dyn);
+ VERIFY(sub_exts.extent(0) == 2);
+ VERIFY(sub_exts.static_extent(1) == dyn);
+ VERIFY(sub_exts.extent(1) == 4);
+ }
+
+ {
+ // selected = 1 x [1, 3] x [1, 4, 7, 10]
+ auto s0 = 1;
+ auto s1 = std::range_slice{1, Cw<5>{}, 2};
+ auto s2 = std::range_slice{Cw<1>{}, Cw<11>{}, Cw<3>{}};
+ auto sub_exts = submdspan_extents(exts, s0, s1, s2);
+ VERIFY(sub_exts.rank() == 2);
+ VERIFY(sub_exts.static_extent(0) == dyn);
+ VERIFY(sub_exts.extent(0) == 2);
+ VERIFY(sub_exts.static_extent(1) == 4);
+ }
+
+ {
+ // selected = [0, 2] x [1, 3] x [0, 3, 6]
+ auto s0 = std::range_slice(0, 3, 2);
+ auto s1 = std::range_slice(1, 5, 2);
+ auto s2 = std::range_slice(0, 7, 3);
+ auto sub_exts = submdspan_extents(exts, s0, s1, s2);
+ VERIFY(sub_exts.rank() == 3);
+ VERIFY(sub_exts.extent(0) == 2);
+ VERIFY(sub_exts.extent(1) == 2);
+ VERIFY(sub_exts.extent(2) == 3);
+ }
+ return true;
+ }
+
+
template<int Value>
using CW = std::constant_wrapper<Value, int>;
@@ -150,6 +230,8 @@ test_all()
test_from_const_int<IC>();
test_from_strided_slice<CW>();
test_from_strided_slice<IC>();
+ test_from_range_slice<CW>();
+ test_from_range_slice<IC>();
test_from_int_like_in_tuple<StructuralInt>();
return true;
}
--
2.52.0