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

Reply via email to