Implements submdspan for layout_left_padded as described in P3663.
PR libstdc++/110352
libstdc++-v3/ChangeLog:
* include/std/mdspan (layout_left_padded::submdspan_mapping):
New friend method.
* testsuite/23_containers/mdspan/layout_traits.h
(LayoutTraits::layout_same_padded): New template type alias.
* testsuite/23_containers/mdspan/submdspan/selections/left_padded_1.cc:
Instantiate tests for layout_left_padded.
* testsuite/23_containers/mdspan/submdspan/selections/left_padded_8.cc:
Ditto.
*
testsuite/23_containers/mdspan/submdspan/selections/left_padded_dyn.cc:
Ditto.
* testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc:
Ditto.
Signed-off-by: Luc Grosheintz <[email protected]>
---
libstdc++-v3/include/std/mdspan | 56 +++++-
.../23_containers/mdspan/layout_traits.h | 4 +
.../submdspan/selections/left_padded_1.cc | 9 +
.../submdspan/selections/left_padded_8.cc | 9 +
.../submdspan/selections/left_padded_dyn.cc | 9 +
.../mdspan/submdspan/submdspan_mapping.cc | 179 ++++++++++++++++--
6 files changed, 241 insertions(+), 25 deletions(-)
create mode 100644
libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left_padded_1.cc
create mode 100644
libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left_padded_8.cc
create mode 100644
libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left_padded_dyn.cc
diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
index 16dda4c8468..520cf322d8c 100644
--- a/libstdc++-v3/include/std/mdspan
+++ b/libstdc++-v3/include/std/mdspan
@@ -812,6 +812,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Mapping>
constexpr bool __is_right_padded_mapping = __padded_mapping_of<
layout_right_padded, _Mapping>;
+
+ template<typename _Mapping>
+ constexpr bool __is_padded_mapping = __is_left_padded_mapping<_Mapping>
+ || __is_right_padded_mapping<_Mapping>;
#endif
template<typename _PaddedMapping>
@@ -1276,11 +1280,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
}
- template<_LayoutSide _Side>
+ template<_LayoutSide _Side, bool _Padded>
struct _SubMdspanMapping;
template<>
- struct _SubMdspanMapping<_LayoutSide::__left>
+ struct _SubMdspanMapping<_LayoutSide::__left, false>
{
using _Layout = layout_left;
template<size_t _Pad> using _PaddedLayout = layout_left_padded<_Pad>;
@@ -1304,7 +1308,42 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
template<>
- struct _SubMdspanMapping<_LayoutSide::__right>
+ struct _SubMdspanMapping<_LayoutSide::__left, true>
+ {
+ using _Layout = layout_left;
+ template<size_t _Pad> using _PaddedLayout = layout_left_padded<_Pad>;
+
+ template<typename _Mapping, size_t _Us>
+ static consteval size_t
+ _S_pad()
+ {
+ using _Extents = typename _Mapping::extents_type;
+ constexpr auto __sta_exts
+ = __mdspan::__static_extents<_Extents>(1, _Us);
+ constexpr auto __sta_padstride
+ = __mdspan::__get_static_stride<_Mapping>();
+ if constexpr (__sta_padstride == dynamic_extent
+ || !__mdspan::__all_static(__sta_exts))
+ return dynamic_extent;
+ else
+ return __sta_padstride * __mdspan::__fwd_prod(__sta_exts);
+ }
+
+ template<size_t _Nm>
+ static consteval bool
+ _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
+ size_t __sub_rank)
+ {
+ if (__sub_rank == 1)
+ return __slice_kinds[0] == _SliceKind::__unit_strided_slice
+ || __slice_kinds[0] == _SliceKind::__full;
+ else
+ return false;
+ }
+ };
+
+ template<>
+ struct _SubMdspanMapping<_LayoutSide::__right, false>
{
using _Layout = layout_right;
template<size_t _Pad> using _PaddedLayout = layout_right_padded<_Pad>;
@@ -1350,7 +1389,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr auto __side = __mdspan::__mapping_side<_Mapping>();
constexpr auto __rank = sizeof...(_Slices);
- using _Trait = _SubMdspanMapping<__side>;
+ using _Trait = _SubMdspanMapping<__side, __is_padded_mapping<_Mapping>>;
using _SliceView = span<const _SliceKind, __rank>;
constexpr auto __slice_kinds =
__mdspan::__make_slice_kind_array<_Slices...>();
@@ -2558,6 +2597,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator==(const mapping& __self, const _LeftpadMapping& __other)
noexcept
{ return __self._M_storage._M_equal(__other); }
+
+ private:
+#if __glibcxx_submdspan
+ template<typename... _Slices>
+ requires (extents_type::rank() == sizeof...(_Slices))
+ friend constexpr auto
+ submdspan_mapping(const mapping& __mapping, _Slices... __slices)
+ { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
+#endif // __glibcxx_submdspan
};
template<size_t _PaddingValue>
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layout_traits.h
b/libstdc++-v3/testsuite/23_containers/mdspan/layout_traits.h
index 619cab53b9e..f0aeac320de 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/layout_traits.h
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/layout_traits.h
@@ -87,6 +87,8 @@ template<>
{
using layout_same = std::layout_left;
using layout_other = std::layout_right;
+ template<size_t PaddingValue>
+ using layout_same_padded = std::layout_left_padded<PaddingValue>;
template<typename Extents>
using extents_type = Extents;
@@ -126,6 +128,8 @@ template<>
struct LayoutTraits<PaddingSide::Right>
{
using layout_same = std::layout_right;
+ template<size_t PaddingValue>
+ using layout_same_padded = std::layout_right_padded<PaddingValue>;
using layout_other = std::layout_left;
template<typename IndexType, size_t... Extents>
diff --git
a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left_padded_1.cc
b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left_padded_1.cc
new file mode 100644
index 00000000000..b21de0cb59a
--- /dev/null
+++
b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left_padded_1.cc
@@ -0,0 +1,9 @@
+// { dg-do run { target c++26 } }
+#include "testcases.h"
+
+int
+main()
+{
+ test_all<std::layout_left_padded<1>>();
+ return 0;
+}
diff --git
a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left_padded_8.cc
b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left_padded_8.cc
new file mode 100644
index 00000000000..f2402d833f3
--- /dev/null
+++
b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left_padded_8.cc
@@ -0,0 +1,9 @@
+// { dg-do run { target c++26 } }
+#include "testcases.h"
+
+int
+main()
+{
+ test_all<std::layout_left_padded<8>>();
+ return 0;
+}
diff --git
a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left_padded_dyn.cc
b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left_padded_dyn.cc
new file mode 100644
index 00000000000..0f6e4e35550
--- /dev/null
+++
b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left_padded_dyn.cc
@@ -0,0 +1,9 @@
+// { dg-do run { target c++26 } }
+#include "testcases.h"
+
+int
+main()
+{
+ test_all<std::layout_left_padded<dyn>>();
+ return 0;
+}
diff --git
a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc
b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc
index cf6167dc3b0..50836968a06 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc
@@ -6,6 +6,7 @@
#include <testsuite_hooks.h>
constexpr size_t dyn = std::dynamic_extent;
+constexpr auto all = std::full_extent;
template<typename Mapping, typename... Slices>
constexpr auto
@@ -18,10 +19,11 @@ template<typename Mapping, typename... Slices>
template<typename Layout>
constexpr bool
- test_layout_unpadded_return_types()
+ test_layout_common_return_types()
{
constexpr auto padding_side = DeducePaddingSide::from_typename<Layout>();
using Traits = LayoutTraits<padding_side>;
+ using layout_unpadded = typename Traits::layout_same;
{
auto m0 = typename Layout::mapping(std::extents());
@@ -32,21 +34,13 @@ template<typename Layout>
auto exts = Traits::make_extents(std::dims<5, int>(3, 5, 7, 11, 13));
auto m = typename Layout::mapping(exts);
- auto all = std::full_extent;
auto s251 = std::strided_slice{2, 5, std::cw<1>};
{
auto slices = std::tuple{0, 0, 0, 0, 0};
auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
using layout_type = typename decltype(result.mapping)::layout_type;
- static_assert(std::same_as<layout_type, Layout>);
- }
-
- {
- auto slices = std::tuple{all, all, all, s251, 0};
- auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
- using layout_type = typename decltype(result.mapping)::layout_type;
- static_assert(std::same_as<layout_type, Layout>);
+ static_assert(std::same_as<layout_type, layout_unpadded>);
}
{
@@ -98,6 +92,72 @@ template<typename Layout>
return true;
}
+template<typename Layout>
+ constexpr bool
+ test_layout_unpadded_return_types()
+ {
+ constexpr auto padding_side = DeducePaddingSide::from_typename<Layout>();
+ using Traits = LayoutTraits<padding_side>;
+
+ auto exts = Traits::make_extents(std::dims<5, int>(3, 5, 7, 11, 13));
+ auto m = typename Layout::mapping(exts);
+ auto s251 = std::strided_slice{2, 5, std::cw<1>};
+
+ {
+ auto slices = std::tuple{all, all, all, s251, 0};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ using layout_type = typename decltype(result.mapping)::layout_type;
+ static_assert(std::same_as<layout_type, Layout>);
+ }
+ return true;
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_layout_padded_return_types()
+ {
+ constexpr auto padding_side = DeducePaddingSide::from_typename<Layout>();
+ using Traits = LayoutTraits<padding_side>;
+
+ auto exts = Traits::make_extents(std::dims<5, int>(3, 5, 7, 11, 13));
+ auto m = typename Layout::mapping(exts);
+ auto s251 = std::strided_slice{2, 5, std::cw<1>};
+
+ {
+ auto slices = std::tuple{all, all, all, s251, 0};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ using layout_type = typename decltype(result.mapping)::layout_type;
+ using layout_expected = typename Traits::layout_same_padded<dyn>;
+ static_assert(std::same_as<layout_type, layout_expected>);
+ }
+
+ {
+ auto slices = std::tuple{all, 0, 0, 0, 0};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ using layout_type = typename decltype(result.mapping)::layout_type;
+ using layout_expected = typename Traits::layout_same;
+ static_assert(std::same_as<layout_type, layout_expected>);
+ }
+
+ {
+ auto s121 = std::strided_slice{1, 2, std::cw<1>};
+ auto slices = std::tuple{s121, 0, 0, 0, 0};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ using layout_type = typename decltype(result.mapping)::layout_type;
+ using layout_expected = typename Traits::layout_same;
+ static_assert(std::same_as<layout_type, layout_expected>);
+ }
+
+ {
+ auto s121 = std::strided_slice{1, 2, std::cw<1>};
+ auto slices = std::tuple{0, s121, 0, 0, 0};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ using layout_type = typename decltype(result.mapping)::layout_type;
+ static_assert(std::same_as<layout_type, std::layout_stride>);
+ }
+ return true;
+ }
+
template<typename Layout>
constexpr bool
test_layout_unpadded_padding_value()
@@ -105,7 +165,6 @@ template<typename Layout>
using Traits = LayoutTraits<DeducePaddingSide::from_typename<Layout>()>;
auto s0 = std::strided_slice{size_t(1), size_t(2), std::cw<size_t(1)>};
auto s3 = std::strided_slice{size_t(2), size_t(5), std::cw<size_t(1)>};
- auto all = std::full_extent;
auto check = [&](auto exts, size_t expected)
{
@@ -123,6 +182,52 @@ template<typename Layout>
return true;
}
+template<typename Layout>
+constexpr size_t static_padding_value = 1;
+
+template<size_t PaddingValue>
+constexpr size_t static_padding_value<std::layout_left_padded<PaddingValue>> =
PaddingValue;
+
+template<size_t PaddingValue>
+constexpr size_t static_padding_value<std::layout_right_padded<PaddingValue>>
= PaddingValue;
+
+template<typename Layout>
+ constexpr bool
+ test_layout_padded_padding_value()
+ {
+ using Traits = LayoutTraits<DeducePaddingSide::from_typename<Layout>()>;
+ auto s0 = std::strided_slice{size_t(1), size_t(2), std::cw<size_t(1)>};
+ auto s3 = std::strided_slice{size_t(2), size_t(5), std::cw<size_t(1)>};
+
+ auto check = [&](auto exts, size_t expected)
+ {
+ auto m = typename Layout::mapping(Traits::make_extents(exts));
+ auto slices = std::tuple{s0, size_t(0), all, s3, size_t(0)};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ auto padding_value = decltype(result.mapping)::padding_value;
+ VERIFY(padding_value == expected);
+ };
+
+ auto pad = [](int n, int m) -> size_t
+ {
+ constexpr auto padding_value = static_padding_value<Layout>;
+ if constexpr (padding_value != dyn)
+ {
+ auto npad = ((n + padding_value - 1) / padding_value) * padding_value;
+ return npad * m;
+ }
+ else
+ return dyn;
+ };
+
+ check(std::extents(std::cw<3>, std::cw<5>, std::cw<7>, 11, 13), pad(3, 5));
+ check(std::extents(std::cw<3>, std::cw<5>, 7, 11, 13), pad(3, 5));
+ check(std::extents(std::cw<3>, std::cw<6>, 7, 11, 13), pad(3, 6));
+ check(std::extents(std::cw<3>, 5, 7, 11, 13), dyn);
+ check(std::extents(3, 5, 7, 11, 13), dyn);
+ return true;
+ }
+
constexpr bool
test_layout_stride_return_types()
{
@@ -138,23 +243,55 @@ test_layout_stride_return_types()
return true;
}
+template<typename Layout>
+ constexpr bool
+ test_return_types_all()
+ {
+ return true;
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_return_types_unpadded_all()
+ {
+ test_layout_common_return_types<Layout>();
+ static_assert(test_layout_common_return_types<Layout>());
+
+ test_layout_unpadded_return_types<Layout>();
+ static_assert(test_layout_unpadded_return_types<Layout>());
+
+ test_layout_unpadded_padding_value<Layout>();
+ static_assert(test_layout_unpadded_padding_value<Layout>());
+ return true;
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_return_types_padded_all()
+ {
+ test_layout_common_return_types<Layout>();
+ static_assert(test_layout_common_return_types<Layout>());
+
+ test_layout_padded_return_types<Layout>();
+ static_assert(test_layout_padded_return_types<Layout>());
+
+ test_layout_padded_padding_value<Layout>();
+ static_assert(test_layout_padded_padding_value<Layout>());
+ return true;
+ }
+
int
main()
{
- test_layout_unpadded_return_types<std::layout_left>();
- static_assert(test_layout_unpadded_return_types<std::layout_left>());
+ test_return_types_unpadded_all<std::layout_left>();
+ test_return_types_unpadded_all<std::layout_right>();
- test_layout_unpadded_return_types<std::layout_right>();
- static_assert(test_layout_unpadded_return_types<std::layout_right>());
+ test_return_types_padded_all<std::layout_left_padded<1>>();
+ test_return_types_padded_all<std::layout_left_padded<2>>();
+ test_return_types_padded_all<std::layout_left_padded<dyn>>();
test_layout_stride_return_types();
static_assert(test_layout_stride_return_types());
-
- test_layout_unpadded_padding_value<std::layout_left>();
- static_assert(test_layout_unpadded_padding_value<std::layout_left>());
-
- test_layout_unpadded_padding_value<std::layout_right>();
- static_assert(test_layout_unpadded_padding_value<std::layout_right>());
return 0;
}
--
2.52.0