mirror of git://gcc.gnu.org/git/gcc.git
libstdc++: Implement std::layout_right_padded [PR110352].
This commit adds the right padded layout as described in N5014, with LWG4372 (dynamic padding value) and LWG4314 (move in operator()). PR libstdc++/110352 libstdc++-v3/ChangeLog: * include/std/mdspan (_RightPaddedIndices): Traits for right padded layouts. (layout_right::mapping::mapping) New overload for right padded layouts. (layout_right_padded): Add implementation. * src/c++23/std.cc.in (layout_right_padded): Add. * testsuite/23_containers/mdspan/layouts/ctors.cc: Update test for right padded layouts. * testsuite/23_containers/mdspan/layouts/empty.cc: Ditto. * testsuite/23_containers/mdspan/layouts/mapping.cc: Ditto. * testsuite/23_containers/mdspan/layouts/padded.cc: Ditto. * testsuite/23_containers/mdspan/layouts/padded_neg.cc: Ditto. * testsuite/23_containers/mdspan/layouts/padded_traits.h: Ditto. Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com> Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
This commit is contained in:
parent
8c71d18f54
commit
bfd41adc61
|
@ -977,6 +977,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
: mapping(__other.extents(), __mdspan::__internal_ctor{})
|
||||
{ __glibcxx_assert(*this == __other); }
|
||||
|
||||
#if __glibcxx_padded_layouts
|
||||
template<typename _RightPaddedMapping>
|
||||
requires __mdspan::__is_right_padded_mapping<_RightPaddedMapping>
|
||||
&& is_constructible_v<extents_type,
|
||||
typename _RightPaddedMapping::extents_type>
|
||||
constexpr
|
||||
explicit(!is_convertible_v<typename _RightPaddedMapping::extents_type,
|
||||
extents_type>)
|
||||
mapping(const _RightPaddedMapping& __other) noexcept
|
||||
: mapping(__other.extents(), __mdspan::__internal_ctor{})
|
||||
{
|
||||
constexpr size_t __rank = extents_type::rank();
|
||||
constexpr size_t __ostride_sta = __mdspan::__get_static_stride<
|
||||
_RightPaddedMapping>();
|
||||
|
||||
if constexpr (__rank > 1)
|
||||
{
|
||||
if constexpr (extents_type::static_extent(__rank - 1) != dynamic_extent
|
||||
&& __ostride_sta != dynamic_extent)
|
||||
static_assert(extents_type::static_extent(__rank - 1)
|
||||
== __ostride_sta);
|
||||
else
|
||||
__glibcxx_assert(__other.stride(__rank - 2)
|
||||
== __other.extents().extent(__rank - 1));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
constexpr mapping&
|
||||
operator=(const mapping&) noexcept = default;
|
||||
|
||||
|
@ -1370,6 +1398,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
return __res;
|
||||
}
|
||||
|
||||
template<typename _Extents, typename _Stride, typename... _Indices>
|
||||
constexpr typename _Extents::index_type
|
||||
__linear_index_rightpad(const _Extents& __exts, _Stride __stride,
|
||||
_Indices... __indices)
|
||||
{
|
||||
// i[n-1] + stride*(i[n-2] + extents.extent(n-2])*...)
|
||||
using _IndexType = typename _Extents::index_type;
|
||||
_IndexType __res = 0;
|
||||
if constexpr (sizeof...(__indices) > 0)
|
||||
{
|
||||
_IndexType __mult = 1;
|
||||
array<_IndexType, sizeof...(__indices)> __ind_arr{__indices...};
|
||||
|
||||
auto __update_rest = [&, __pos = __exts.rank()-1](_IndexType) mutable
|
||||
{
|
||||
--__pos;
|
||||
__res += __ind_arr[__pos] * __mult;
|
||||
__mult *= __exts.extent(__pos);
|
||||
};
|
||||
|
||||
auto __update = [&](_IndexType, auto... __rest)
|
||||
{
|
||||
__res += __ind_arr[__exts.rank() - 1];
|
||||
__mult = __stride.extent(0);
|
||||
(__update_rest(__rest), ...);
|
||||
};
|
||||
__update(__indices...);
|
||||
}
|
||||
return __res;
|
||||
}
|
||||
|
||||
template<size_t _Rank>
|
||||
struct _LeftPaddedLayoutTraits
|
||||
{
|
||||
|
@ -1396,6 +1455,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
}
|
||||
};
|
||||
|
||||
template<size_t _Rank>
|
||||
struct _RightPaddedLayoutTraits
|
||||
{
|
||||
using _LayoutSame = layout_right;
|
||||
using _LayoutOther = layout_left;
|
||||
|
||||
constexpr static size_t _S_ext_idx = _Rank - 1;
|
||||
constexpr static size_t _S_stride_idx = _Rank - 2;
|
||||
constexpr static size_t _S_unpad_begin = 0;
|
||||
constexpr static size_t _S_unpad_end = _Rank - 1;
|
||||
|
||||
template<typename _IndexType, size_t _StaticStride, size_t..._Extents>
|
||||
constexpr static auto _S_make_padded_extent(
|
||||
extents<_IndexType, _StaticStride> __stride,
|
||||
const extents<_IndexType, _Extents...>& __exts)
|
||||
{
|
||||
auto __impl = [&]<size_t... _Is>(integer_sequence<size_t, _Is...>)
|
||||
{
|
||||
return extents<_IndexType, (_Extents...[_Is])..., _StaticStride>{
|
||||
__exts.extent(_Is)..., __stride.extent(0)};
|
||||
};
|
||||
return __impl(make_index_sequence<sizeof...(_Extents) - 1>());
|
||||
}
|
||||
};
|
||||
|
||||
template<size_t _PaddingValue, typename _Extents, typename _LayoutTraits>
|
||||
class _PaddedStorage
|
||||
{
|
||||
|
@ -1825,6 +1909,170 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
noexcept
|
||||
{ return __self._M_storage._M_equal(__other); }
|
||||
};
|
||||
|
||||
template<size_t _PaddingValue>
|
||||
template<typename _Extents>
|
||||
class layout_right_padded<_PaddingValue>::mapping {
|
||||
public:
|
||||
static constexpr size_t padding_value = _PaddingValue;
|
||||
using extents_type = _Extents;
|
||||
using index_type = typename extents_type::index_type;
|
||||
using size_type = typename extents_type::size_type;
|
||||
using rank_type = typename extents_type::rank_type;
|
||||
using layout_type = layout_right_padded<_PaddingValue>;
|
||||
|
||||
private:
|
||||
static constexpr size_t _S_rank = extents_type::rank();
|
||||
using _PaddedStorage = __mdspan::_PaddedStorage<_PaddingValue,
|
||||
_Extents, __mdspan::_RightPaddedLayoutTraits<_S_rank>>;
|
||||
[[no_unique_address]] _PaddedStorage _M_storage;
|
||||
|
||||
consteval friend size_t
|
||||
__mdspan::__get_static_stride<mapping>();
|
||||
|
||||
constexpr index_type
|
||||
_M_extent(size_t __r) const noexcept
|
||||
{ return _M_storage._M_extents.extent(__r); }
|
||||
|
||||
constexpr index_type
|
||||
_M_padstride() const noexcept
|
||||
{ return _M_storage._M_stride.extent(0); }
|
||||
|
||||
public:
|
||||
constexpr
|
||||
mapping() noexcept
|
||||
{ }
|
||||
|
||||
constexpr
|
||||
mapping(const mapping&) noexcept = default;
|
||||
|
||||
constexpr
|
||||
mapping(const extents_type& __exts)
|
||||
: _M_storage(__exts)
|
||||
{ }
|
||||
|
||||
template<__mdspan::__valid_index_type<index_type> _OIndexType>
|
||||
constexpr mapping(const extents_type& __exts, _OIndexType __pad)
|
||||
: _M_storage(__exts,
|
||||
__mdspan::__index_type_cast<index_type>(std::move(__pad)))
|
||||
{ }
|
||||
|
||||
template<typename _OExtents>
|
||||
requires is_constructible_v<extents_type, _OExtents>
|
||||
constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
|
||||
mapping(const layout_right::mapping<_OExtents>& __other)
|
||||
: _M_storage(__other)
|
||||
{ }
|
||||
|
||||
template<typename _OExtents>
|
||||
requires is_constructible_v<_OExtents, extents_type>
|
||||
constexpr explicit(_OExtents::rank() > 0)
|
||||
mapping(const typename layout_stride::mapping<_OExtents>& __other)
|
||||
: _M_storage(__other)
|
||||
{ __glibcxx_assert(*this == __other); }
|
||||
|
||||
template<typename _RightPaddedMapping>
|
||||
requires __mdspan::__is_right_padded_mapping<_RightPaddedMapping>
|
||||
&& is_constructible_v<extents_type,
|
||||
typename _RightPaddedMapping::extents_type>
|
||||
constexpr explicit(_S_rank > 1 && (padding_value != dynamic_extent
|
||||
|| _RightPaddedMapping::padding_value == dynamic_extent))
|
||||
mapping(const _RightPaddedMapping& __other)
|
||||
: _M_storage(layout_right{}, __other)
|
||||
{ }
|
||||
|
||||
template<typename _LeftPaddedMapping>
|
||||
requires (__mdspan::__is_left_padded_mapping<_LeftPaddedMapping>
|
||||
|| __mdspan::__mapping_of<layout_left, _LeftPaddedMapping>)
|
||||
&& (_S_rank <= 1)
|
||||
&& is_constructible_v<extents_type,
|
||||
typename _LeftPaddedMapping::extents_type>
|
||||
constexpr explicit(!is_convertible_v<
|
||||
typename _LeftPaddedMapping::extents_type, extents_type>)
|
||||
mapping(const _LeftPaddedMapping& __other) noexcept
|
||||
: _M_storage(layout_left{}, __other)
|
||||
{ }
|
||||
|
||||
constexpr mapping& operator=(const mapping&) noexcept = default;
|
||||
|
||||
constexpr const extents_type&
|
||||
extents() const noexcept { return _M_storage._M_extents; }
|
||||
|
||||
constexpr array<index_type, _S_rank>
|
||||
strides() const noexcept
|
||||
{
|
||||
array<index_type, _S_rank> __ret;
|
||||
if constexpr (_S_rank > 0)
|
||||
__ret[_S_rank - 1] = 1;
|
||||
if constexpr (_S_rank > 1)
|
||||
__ret[_S_rank - 2] = _M_padstride();
|
||||
if constexpr (_S_rank > 2)
|
||||
for(size_t __i = _S_rank - 2; __i > 0; --__i)
|
||||
__ret[__i - 1] = __ret[__i] * _M_extent(__i);
|
||||
return __ret;
|
||||
}
|
||||
|
||||
constexpr index_type
|
||||
required_span_size() const noexcept
|
||||
{ return _M_storage._M_required_span_size(); }
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 4314. Missing move in mdspan layout mapping::operator()
|
||||
template<__mdspan::__valid_index_type<index_type>... _Indices>
|
||||
requires (sizeof...(_Indices) == _S_rank)
|
||||
constexpr index_type
|
||||
operator()(_Indices... __indices) const noexcept
|
||||
{
|
||||
return __mdspan::__linear_index_rightpad(
|
||||
extents(), _M_storage._M_stride,
|
||||
static_cast<index_type>(std::move(__indices))...);
|
||||
}
|
||||
|
||||
static constexpr bool
|
||||
is_always_exhaustive() noexcept
|
||||
{ return _PaddedStorage::_M_is_always_exhaustive(); }
|
||||
|
||||
constexpr bool
|
||||
is_exhaustive() noexcept
|
||||
{ return _M_storage._M_is_exhaustive(); }
|
||||
|
||||
static constexpr bool
|
||||
is_always_unique() noexcept { return true; }
|
||||
|
||||
static constexpr bool
|
||||
is_always_strided() noexcept { return true; }
|
||||
|
||||
static constexpr bool
|
||||
is_unique() noexcept { return true; }
|
||||
|
||||
static constexpr bool
|
||||
is_strided() noexcept { return true; }
|
||||
|
||||
constexpr index_type
|
||||
stride(rank_type __r) const noexcept
|
||||
{
|
||||
__glibcxx_assert(__r < _S_rank);
|
||||
if constexpr (_S_rank <= 1)
|
||||
return 1;
|
||||
else if (__r == _S_rank - 1)
|
||||
return 1;
|
||||
else if (__r == _S_rank - 2)
|
||||
return _M_padstride();
|
||||
else
|
||||
return static_cast<index_type>(
|
||||
static_cast<size_t>(_M_padstride()) *
|
||||
static_cast<size_t>(__mdspan::__fwd_prod(
|
||||
extents(), __r + 1, _S_rank - 1)));
|
||||
}
|
||||
|
||||
template<typename _RightPaddedMapping>
|
||||
requires(__mdspan::__is_right_padded_mapping<_RightPaddedMapping>
|
||||
&& _RightPaddedMapping::extents_type::rank() == _S_rank)
|
||||
friend constexpr bool
|
||||
operator==(const mapping& __self, const _RightPaddedMapping& __other)
|
||||
noexcept
|
||||
{ return __self._M_storage._M_equal(__other); }
|
||||
};
|
||||
#endif // __glibcxx_padded_layouts
|
||||
|
||||
template<typename _ElementType>
|
||||
|
|
|
@ -1871,9 +1871,10 @@ export namespace std
|
|||
using std::mdspan;
|
||||
#if __glibcxx_padded_layouts
|
||||
using std::layout_left_padded;
|
||||
using std::layout_right_padded;
|
||||
#endif
|
||||
// FIXME layout_right_padded, strided_slice, submdspan_mapping_result,
|
||||
// full_extent_t, full_extent, submdspan_extents, mdsubspan
|
||||
// FIXME strided_slice, submdspan_mapping_result, full_extent_t, full_extent,
|
||||
// submdspan_extents, mdsubspan
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -469,6 +469,7 @@ main()
|
|||
test_all<std::layout_right>();
|
||||
#if __cplusplus > 202302L
|
||||
test_padded_all<std::layout_left_padded>();
|
||||
test_padded_all<std::layout_right_padded>();
|
||||
#endif
|
||||
|
||||
from_left_or_right::test_all<std::layout_left, std::layout_right>();
|
||||
|
|
|
@ -142,6 +142,7 @@ main()
|
|||
static_assert(test_all<std::layout_stride>());
|
||||
#if __cplusplus > 202302L
|
||||
static_assert(test_padded_all<std::layout_left_padded>());
|
||||
static_assert(test_padded_all<std::layout_right_padded>());
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -373,7 +373,7 @@ template<>
|
|||
|
||||
#if __cplusplus > 202302L
|
||||
template<typename Layout>
|
||||
requires is_left_padded<Layout>
|
||||
requires is_left_padded<Layout> || is_right_padded<Layout>
|
||||
struct TestStride2D<Layout>
|
||||
{
|
||||
static constexpr void
|
||||
|
@ -457,7 +457,7 @@ template<>
|
|||
|
||||
#if __cplusplus > 202302L
|
||||
template<typename Layout>
|
||||
requires is_left_padded<Layout>
|
||||
requires is_left_padded<Layout> || is_right_padded<Layout>
|
||||
struct TestStride3D<Layout>
|
||||
{
|
||||
static constexpr void
|
||||
|
@ -701,6 +701,7 @@ main()
|
|||
test_all<std::layout_stride>();
|
||||
#if __cplusplus > 202302L
|
||||
test_padded_all<std::layout_left_padded>();
|
||||
test_padded_all<std::layout_right_padded>();
|
||||
#endif
|
||||
|
||||
test_has_op_eq<std::layout_right, std::layout_left, false>();
|
||||
|
@ -708,6 +709,7 @@ main()
|
|||
test_has_op_eq<std::layout_left, std::layout_stride, true>();
|
||||
#if __cplusplus > 202302L
|
||||
test_padded_has_op_eq<std::layout_left_padded>();
|
||||
test_padded_has_op_eq<std::layout_right_padded>();
|
||||
#endif
|
||||
|
||||
test_has_op_eq_peculiar();
|
||||
|
|
|
@ -668,6 +668,10 @@ main()
|
|||
test_all<std::layout_left_padded>();
|
||||
static_assert(test_all<std::layout_left_padded>());
|
||||
|
||||
test_all<std::layout_right_padded>();
|
||||
static_assert(test_all<std::layout_right_padded>());
|
||||
|
||||
test_from_pad_all<std::layout_left_padded>();
|
||||
test_from_pad_all<std::layout_right_padded>();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ template<template<size_t> typename Layout>
|
|||
return true;
|
||||
}
|
||||
static_assert(test_from_extens_representable_sta<std::layout_left_padded>()); // { dg-error "from here" }
|
||||
static_assert(test_from_extens_representable_sta<std::layout_right_padded>()); // { dg-error "from here" }
|
||||
|
||||
template<template<size_t> typename Layout>
|
||||
constexpr bool
|
||||
|
@ -28,6 +29,7 @@ template<template<size_t> typename Layout>
|
|||
return true;
|
||||
}
|
||||
static_assert(test_from_extents_representable_padded_size<std::layout_left_padded>()); // { dg-error "expansion of" }
|
||||
static_assert(test_from_extents_representable_padded_size<std::layout_right_padded>()); // { dg-error "expansion of" }
|
||||
|
||||
template<template<size_t> typename Layout>
|
||||
constexpr bool
|
||||
|
@ -40,6 +42,7 @@ template<template<size_t> typename Layout>
|
|||
return true;
|
||||
}
|
||||
static_assert(test_from_extents_representable_stride<std::layout_left_padded>()); // { dg-error "expansion of" }
|
||||
static_assert(test_from_extents_representable_stride<std::layout_right_padded>()); // { dg-error "expansion of" }
|
||||
|
||||
template<template<size_t> typename Layout>
|
||||
constexpr bool
|
||||
|
@ -51,6 +54,7 @@ template<template<size_t> typename Layout>
|
|||
return true;
|
||||
}
|
||||
static_assert(test_from_pad_representable_stride<std::layout_left_padded>()); // { dg-error "expansion of" }
|
||||
static_assert(test_from_pad_representable_stride<std::layout_right_padded>()); // { dg-error "expansion of" }
|
||||
|
||||
template<template<size_t> typename Layout>
|
||||
constexpr bool
|
||||
|
@ -62,6 +66,7 @@ template<template<size_t> typename Layout>
|
|||
return true;
|
||||
}
|
||||
static_assert(test_from_pad_representable_padded_size<std::layout_left_padded>()); // { dg-error "expansion of" }
|
||||
static_assert(test_from_pad_representable_padded_size<std::layout_right_padded>()); // { dg-error "expansion of" }
|
||||
|
||||
template<template<size_t> typename Layout>
|
||||
constexpr bool
|
||||
|
@ -76,6 +81,7 @@ template<template<size_t> typename Layout>
|
|||
return true;
|
||||
}
|
||||
static_assert(test_from_left<std::layout_left_padded>()); // { dg-error "required from here" }
|
||||
static_assert(test_from_left<std::layout_right_padded>()); // { dg-error "required from here" }
|
||||
|
||||
template<template<size_t> typename Layout>
|
||||
constexpr bool
|
||||
|
@ -90,6 +96,7 @@ template<template<size_t> typename Layout>
|
|||
return true;
|
||||
}
|
||||
static_assert(test_from_left_bad_runtime_stride<std::layout_left_padded>()); // { dg-error "expansion of" }
|
||||
static_assert(test_from_left_bad_runtime_stride<std::layout_right_padded>()); // { dg-error "expansion of" }
|
||||
|
||||
template<template<size_t> typename Layout>
|
||||
constexpr bool
|
||||
|
@ -103,6 +110,7 @@ template<template<size_t> typename Layout>
|
|||
return true;
|
||||
}
|
||||
static_assert(test_from_left_representable_extents<std::layout_left_padded>()); // { dg-error "expansion of" }
|
||||
static_assert(test_from_left_representable_extents<std::layout_right_padded>()); // { dg-error "expansion of" }
|
||||
|
||||
template<template<size_t> typename Layout, size_t PaddingValue>
|
||||
constexpr bool
|
||||
|
@ -116,6 +124,8 @@ template<template<size_t> typename Layout, size_t PaddingValue>
|
|||
}
|
||||
static_assert(test_pad_overflow<std::layout_left_padded, 1>()); // { dg-error "expansion of" }
|
||||
static_assert(test_pad_overflow<std::layout_left_padded, dyn>()); // { dg-error "expansion of" }
|
||||
static_assert(test_pad_overflow<std::layout_right_padded, 1>()); // { dg-error "expansion of" }
|
||||
static_assert(test_pad_overflow<std::layout_right_padded, dyn>()); // { dg-error "expansion of" }
|
||||
|
||||
template<template<size_t> typename Layout, size_t PaddingValue>
|
||||
constexpr bool
|
||||
|
@ -128,6 +138,8 @@ template<template<size_t> typename Layout, size_t PaddingValue>
|
|||
}
|
||||
static_assert(test_from_pad_negative<std::layout_left_padded, 1>()); // { dg-error "expansion of" }
|
||||
static_assert(test_from_pad_negative<std::layout_left_padded, dyn>()); // { dg-error "expansion of" }
|
||||
static_assert(test_from_pad_negative<std::layout_right_padded, 1>()); // { dg-error "expansion of" }
|
||||
static_assert(test_from_pad_negative<std::layout_right_padded, dyn>()); // { dg-error "expansion of" }
|
||||
|
||||
template<template<size_t> typename Layout, size_t Pad>
|
||||
constexpr bool
|
||||
|
@ -142,6 +154,8 @@ template<template<size_t> typename Layout, size_t Pad>
|
|||
}
|
||||
static_assert(test_static_pad_same<std::layout_left_padded, 1>()); // { dg-error "expansion of" }
|
||||
static_assert(test_static_pad_same<std::layout_left_padded, 3>()); // { dg-error "expansion of" }
|
||||
static_assert(test_static_pad_same<std::layout_right_padded, 1>()); // { dg-error "expansion of" }
|
||||
static_assert(test_static_pad_same<std::layout_right_padded, 3>()); // { dg-error "expansion of" }
|
||||
|
||||
template<template<size_t> typename Layout>
|
||||
constexpr bool
|
||||
|
@ -156,6 +170,7 @@ template<template<size_t> typename Layout>
|
|||
return true;
|
||||
}
|
||||
static_assert(test_from_stride_wrong_stride0<std::layout_left_padded>()); // { dg-error "expansion of" }
|
||||
static_assert(test_from_stride_wrong_stride0<std::layout_right_padded>()); // { dg-error "expansion of" }
|
||||
|
||||
template<template<size_t> typename Layout>
|
||||
constexpr bool
|
||||
|
@ -170,6 +185,7 @@ template<template<size_t> typename Layout>
|
|||
return true;
|
||||
}
|
||||
static_assert(test_from_stride_wrong_stride1<std::layout_left_padded>()); // { dg-error "expansion of" }
|
||||
static_assert(test_from_stride_wrong_stride1<std::layout_right_padded>()); // { dg-error "expansion of" }
|
||||
|
||||
template<template<size_t> typename Layout>
|
||||
constexpr bool
|
||||
|
@ -184,6 +200,7 @@ template<template<size_t> typename Layout>
|
|||
return true;
|
||||
}
|
||||
static_assert(test_from_stride_wrong_stride2<std::layout_left_padded>());
|
||||
static_assert(test_from_stride_wrong_stride2<std::layout_right_padded>());
|
||||
|
||||
template<template<size_t> typename Layout>
|
||||
constexpr bool
|
||||
|
@ -200,6 +217,7 @@ template<template<size_t> typename Layout>
|
|||
return true;
|
||||
}
|
||||
static_assert(test_from_stride_oversized<std::layout_left_padded>()); // { dg-error "expansion of" }
|
||||
static_assert(test_from_stride_oversized<std::layout_right_padded>()); // { dg-error "expansion of" }
|
||||
|
||||
template<template<size_t> typename Layout>
|
||||
constexpr bool
|
||||
|
@ -213,6 +231,7 @@ template<template<size_t> typename Layout>
|
|||
return true;
|
||||
}
|
||||
static_assert(test_from_samepad_dyn<std::layout_left_padded>()); // { dg-error "expansion of" }
|
||||
static_assert(test_from_samepad_dyn<std::layout_right_padded>()); // { dg-error "expansion of" }
|
||||
|
||||
template<template<size_t> typename Layout>
|
||||
constexpr bool
|
||||
|
@ -226,6 +245,7 @@ template<template<size_t> typename Layout>
|
|||
return true;
|
||||
}
|
||||
static_assert(test_from_samepad_sta<std::layout_left_padded>()); // { dg-error "expansion of" }
|
||||
static_assert(test_from_samepad_sta<std::layout_right_padded>()); // { dg-error "expansion of" }
|
||||
|
||||
template<template<size_t> typename Layout>
|
||||
constexpr bool
|
||||
|
@ -240,6 +260,7 @@ template<template<size_t> typename Layout>
|
|||
return true;
|
||||
}
|
||||
static_assert(test_from_samepad_oversized<std::layout_left_padded>()); // { dg-error "expansion of" }
|
||||
static_assert(test_from_samepad_oversized<std::layout_right_padded>()); // { dg-error "expansion of" }
|
||||
|
||||
template<template<size_t> typename Layout, size_t RunId>
|
||||
constexpr bool
|
||||
|
@ -278,6 +299,10 @@ static_assert(test_to_same_not_exhaustive<std::layout_left_padded, 0>()); // { d
|
|||
static_assert(test_to_same_not_exhaustive<std::layout_left_padded, 1>()); // { dg-error "expansion of" }
|
||||
static_assert(test_to_same_not_exhaustive<std::layout_left_padded, 2>()); // { dg-error "expansion of" }
|
||||
static_assert(test_to_same_not_exhaustive<std::layout_left_padded, 3>()); // { dg-error "expansion of" }
|
||||
static_assert(test_to_same_not_exhaustive<std::layout_right_padded, 0>()); // { dg-error "expansion of" }
|
||||
static_assert(test_to_same_not_exhaustive<std::layout_right_padded, 1>()); // { dg-error "expansion of" }
|
||||
static_assert(test_to_same_not_exhaustive<std::layout_right_padded, 2>()); // { dg-error "expansion of" }
|
||||
static_assert(test_to_same_not_exhaustive<std::layout_right_padded, 3>()); // { dg-error "expansion of" }
|
||||
|
||||
template<template<size_t> typename Layout>
|
||||
constexpr bool
|
||||
|
@ -290,6 +315,7 @@ template<template<size_t> typename Layout>
|
|||
return true;
|
||||
}
|
||||
static_assert(test_statically_bad_padding_value1<std::layout_left_padded>()); // { dg-error "required from" }
|
||||
static_assert(test_statically_bad_padding_value1<std::layout_right_padded>()); // { dg-error "required from" }
|
||||
|
||||
template<template<size_t> typename Layout>
|
||||
constexpr bool
|
||||
|
@ -301,6 +327,7 @@ template<template<size_t> typename Layout>
|
|||
return true;
|
||||
}
|
||||
static_assert(test_statically_bad_padding_value2<std::layout_left_padded>()); // { dg-error "required from" }
|
||||
static_assert(test_statically_bad_padding_value2<std::layout_right_padded>()); // { dg-error "required from" }
|
||||
|
||||
template<template<size_t> typename Layout>
|
||||
constexpr bool
|
||||
|
@ -312,6 +339,7 @@ template<template<size_t> typename Layout>
|
|||
return true;
|
||||
}
|
||||
static_assert(test_statically_oversized<std::layout_left_padded>()); // { dg-error "from here" }
|
||||
static_assert(test_statically_oversized<std::layout_right_padded>()); // { dg-error "from here" }
|
||||
|
||||
// { dg-prune-output "padding_value must be representable as index_type" }
|
||||
// { dg-prune-output "non-constant condition for static assertion" }
|
||||
|
|
|
@ -13,14 +13,33 @@ template<size_t PaddingValue>
|
|||
#endif
|
||||
|
||||
template<typename Layout>
|
||||
constexpr bool
|
||||
is_padded_layout = is_left_padded<Layout>;
|
||||
constexpr static bool is_right_padded = false;
|
||||
|
||||
#if __cplusplus > 202302L
|
||||
template<size_t PaddingValue>
|
||||
constexpr static bool is_right_padded<std::layout_right_padded<PaddingValue>>
|
||||
= true;
|
||||
#endif
|
||||
|
||||
template<typename Layout>
|
||||
constexpr bool
|
||||
is_padded_layout = is_left_padded<Layout> || is_right_padded<Layout>;
|
||||
|
||||
#if __cplusplus > 202302L
|
||||
template<typename Extents>
|
||||
constexpr auto
|
||||
dynamic_extents_array(const Extents& exts)
|
||||
{
|
||||
std::array<typename Extents::index_type, Extents::rank()> ret;
|
||||
for(size_t i = 0; i < Extents::rank(); ++i)
|
||||
ret[i] = exts.extent(i);
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum class PaddingSide
|
||||
{
|
||||
Left
|
||||
Left,
|
||||
Right
|
||||
};
|
||||
|
||||
struct DeducePaddingSide
|
||||
|
@ -28,12 +47,22 @@ struct DeducePaddingSide
|
|||
template<template<size_t> typename Layout>
|
||||
constexpr static PaddingSide
|
||||
from_template()
|
||||
{ return PaddingSide::Left; }
|
||||
{
|
||||
if constexpr (std::same_as<Layout<0>, std::layout_left_padded<0>>)
|
||||
return PaddingSide::Left;
|
||||
else
|
||||
return PaddingSide::Right;
|
||||
}
|
||||
|
||||
template<typename Layout>
|
||||
constexpr static PaddingSide
|
||||
from_typename()
|
||||
{ return PaddingSide::Left; }
|
||||
{
|
||||
if constexpr (is_left_padded<Layout>)
|
||||
return PaddingSide::Left;
|
||||
else
|
||||
return PaddingSide::Right;
|
||||
}
|
||||
};
|
||||
|
||||
template<PaddingSide Side>
|
||||
|
@ -69,5 +98,52 @@ template<>
|
|||
{ return exts.extent(0); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct LayoutTraits<PaddingSide::Right>
|
||||
{
|
||||
using layout_same = std::layout_right;
|
||||
using layout_other = std::layout_left;
|
||||
|
||||
template<typename IndexType, size_t... Extents>
|
||||
constexpr static auto
|
||||
make_extents(const std::extents<IndexType, Extents...>& exts)
|
||||
{
|
||||
constexpr size_t rank = sizeof...(Extents);
|
||||
auto impl = [&]<size_t... I>(std::index_sequence<I...>)
|
||||
{
|
||||
auto dyn_exts = make_array(dynamic_extents_array(exts));
|
||||
return std::extents<IndexType, Extents...[rank - 1 - I]...>(dyn_exts);
|
||||
};
|
||||
return impl(std::make_index_sequence<rank>());
|
||||
}
|
||||
|
||||
template<typename Extents>
|
||||
using extents_type = decltype(make_extents(std::declval<Extents>()));
|
||||
|
||||
template<typename T, size_t N>
|
||||
constexpr static std::array<T, N>
|
||||
make_array(std::array<T, N> a)
|
||||
{
|
||||
std::ranges::reverse(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename Mapping>
|
||||
constexpr static auto
|
||||
padded_stride(const Mapping& m)
|
||||
{
|
||||
auto rank = Mapping::extents_type::rank();
|
||||
return m.stride(rank - 2);
|
||||
}
|
||||
|
||||
template<typename Extents>
|
||||
constexpr static auto
|
||||
padded_extent(const Extents& exts)
|
||||
{
|
||||
auto rank = Extents::rank();
|
||||
return exts.extent(rank - 1);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue