mirror of git://gcc.gnu.org/git/gcc.git
libstdc++: Implement submdspan_mapping for layout_left_padded. [PR110352]
Implements submdspan for layout_left_padded as described in P3663. PR libstdc++/110352 libstdc++-v3/ChangeLog: * include/std/mdspan (__mdspan::__is_padded_mapping): Define. (__mdspan::_SubMdspanMapping): Add _Padded template parameter. (__mdspan::_SubMdspanMapping<_LayoutSide::__left, true>): Define. (__mdspan::__submdspan_mapping_impl): Updated _Trait alias. (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.cc: Instantiate tests for layout_left_padded. * testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc: Ditto. Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com> Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
This commit is contained in:
parent
0fcb1bd46a
commit
558ab7b638
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
// { dg-do run { target c++26 } }
|
||||
// { dg-timeout-factor 2 }
|
||||
#include "testcases.h"
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test_all<std::layout_left_padded<1>>();
|
||||
test_all<std::layout_left_padded<8>>();
|
||||
test_all<std::layout_left_padded<dyn>>();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue