Implement the parts of layout_left that depend on layout_right; and the parts of layout_right that don't depend on layout_stride.
libstdc++-v3/ChangeLog: * include/std/mdspan (layout_right): New class. Signed-off-by: Luc Grosheintz <luc.groshei...@gmail.com> --- libstdc++-v3/include/std/mdspan | 153 +++++++++++++++++++++++++++++++- 1 file changed, 152 insertions(+), 1 deletion(-) diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index d90fed57a19..13ed27bcaaf 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -390,6 +390,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class mapping; }; + struct layout_right + { + template<typename _Extents> + class mapping; + }; + namespace __mdspan { template<typename _Tp> @@ -494,7 +500,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Mapping>; template<typename _Mapping> - concept __standardized_mapping = __mapping_of<layout_left, _Mapping>; + concept __standardized_mapping = __mapping_of<layout_left, _Mapping> + || __mapping_of<layout_right, _Mapping>; template<typename M> concept __mapping_like = requires @@ -544,6 +551,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : mapping(__other.extents(), __mdspan::__internal_ctor{}) { } + template<typename _OExtents> + requires (_Extents::rank() <= 1 + && is_constructible_v<_Extents, _OExtents>) + constexpr explicit(!is_convertible_v<_OExtents, _Extents>) + mapping(const layout_right::mapping<_OExtents>& __other) noexcept + : mapping(__other.extents(), __mdspan::__internal_ctor{}) + { } + constexpr mapping& operator=(const mapping&) noexcept = default; @@ -611,6 +626,142 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION [[no_unique_address]] _Extents _M_extents; }; + namespace __mdspan + { + template<typename _Extents, typename... _Indices> + constexpr typename _Extents::index_type + __linear_index_right(const _Extents& __exts, _Indices... __indices) + { + using _IndexType = typename _Extents::index_type; + array<_IndexType, sizeof...(__indices)> __ind_arr{__indices...}; + _IndexType __res = 0; + if constexpr (sizeof...(__indices) > 0) + { + _IndexType __mult = 1; + auto __update = [&, __pos = __exts.rank()](_IndexType) mutable + { + --__pos; + __res += __ind_arr[__pos] * __mult; + __mult *= __exts.extent(__pos); + }; + (__update(__indices), ...); + } + return __res; + } + } + + template<typename _Extents> + class layout_right::mapping + { + public: + 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; + + static_assert(__mdspan::__representable_size<_Extents, index_type>, + "The size of extents_type must be representable as index_type"); + + constexpr + mapping() noexcept = default; + + constexpr + mapping(const mapping&) noexcept = default; + + constexpr + mapping(const _Extents& __extents) noexcept + : _M_extents(__extents) + { __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); } + + template<typename _OExtents> + requires (is_constructible_v<extents_type, _OExtents>) + constexpr explicit(!is_convertible_v<_OExtents, extents_type>) + mapping(const mapping<_OExtents>& __other) noexcept + : mapping(__other.extents(), __mdspan::__internal_ctor{}) + { } + + template<class _OExtents> + requires (extents_type::rank() <= 1 + && is_constructible_v<extents_type, _OExtents>) + constexpr explicit(!is_convertible_v<_OExtents, extents_type>) + mapping(const layout_left::mapping<_OExtents>& __other) noexcept + : mapping(__other.extents(), __mdspan::__internal_ctor{}) + { } + + constexpr mapping& + operator=(const mapping&) noexcept = default; + + constexpr const _Extents& + extents() const noexcept { return _M_extents; } + + constexpr index_type + required_span_size() const noexcept + { return __mdspan::__fwd_prod(_M_extents, extents_type::rank()); } + + template<__mdspan::__valid_index_type<index_type>... _Indices> + requires (sizeof...(_Indices) == extents_type::rank()) + constexpr index_type + operator()(_Indices... __indices) const noexcept + { + return __mdspan::__linear_index_right( + _M_extents, static_cast<index_type>(__indices)...); + } + + static constexpr bool + is_always_unique() noexcept + { return true; } + + static constexpr bool + is_always_exhaustive() noexcept + { return true; } + + static constexpr bool + is_always_strided() noexcept + { return true; } + + static constexpr bool + is_unique() noexcept + { return true; } + + static constexpr bool + is_exhaustive() noexcept + { return true; } + + static constexpr bool + is_strided() noexcept + { return true; } + + constexpr index_type + stride(rank_type __i) const noexcept + requires (extents_type::rank() > 0) + { + __glibcxx_assert(__i < extents_type::rank()); + return __mdspan::__rev_prod(_M_extents, __i); + } + + template<typename _OExtents> + requires (extents_type::rank() == _OExtents::rank()) + friend constexpr bool + operator==(const mapping& __self, const mapping<_OExtents>& __other) + noexcept + { return __self.extents() == __other.extents(); } + + private: + template<typename _OExtents> + constexpr explicit + mapping(const _OExtents& __oexts, __mdspan::__internal_ctor) noexcept + : _M_extents(extents_type(__oexts)) + { + static_assert(__mdspan::__representable_size<_OExtents, index_type>, + "The size of OtherExtents must be representable as index_type"); + __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); + } + + public: + [[no_unique_address]] _Extents _M_extents; + }; + _GLIBCXX_END_NAMESPACE_VERSION } #endif -- 2.49.0