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++/ChangeLog: * include/std/mdspan (layout_right): New class. Signed-off-by: Luc Grosheintz <luc.groshei...@gmail.com> --- libstdc++-v3/include/std/mdspan | 147 ++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index e05048a5b93..583792b5269 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -330,6 +330,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class mapping; }; + struct layout_right + { + template<typename _Extents> + class mapping; + }; + namespace __mdspan { template<typename _Tp> @@ -427,6 +433,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _M_extents(__other.extents()) { } + 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 + : _M_extents(__other.extents()) + { } + constexpr mapping& operator=(const mapping&) noexcept = default; @@ -483,6 +497,139 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION [[no_unique_address]] extents_type _M_extents; }; + namespace __mdspan + { + template<size_t _Count> + struct _LinearIndexRight + { + template<typename _Extents> + static constexpr typename _Extents::index_type + _S_value(typename _Extents::index_type __accumulated, + const _Extents&) noexcept + { return __accumulated; } + + template<typename _Extents, typename... _Indices> + static constexpr typename _Extents::index_type + _S_value(typename _Extents::index_type __accumulated, + const _Extents& __exts, typename _Extents::index_type __idx, + _Indices... __indices) noexcept + { + // (...) * __exts[r-1] + __indices[r-1]; + return _LinearIndexRight<_Count + 1>::_S_value( + __accumulated * __exts.extent(_Count) + __idx, __exts, + __indices...); + } + }; + + template<typename _Extents, typename... _Indices> + constexpr typename _Extents::index_type + __linear_index_right(const _Extents& __exts, _Indices... __indices) + { + return _LinearIndexRight<0>::_S_value(0, __exts, __indices...); + } + } + + template<typename _Extents> + class layout_right::mapping + { + static_assert(__mdspan::__layout_extent<_Extents>, + "The size of extents_type is not representable as index_type."); + 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; + + constexpr + mapping() noexcept = default; + + constexpr + mapping(const mapping&) noexcept = default; + + constexpr + mapping(const extents_type& __extents) noexcept + : _M_extents(__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 + : _M_extents(__other.extents()) + { } + + 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 + : _M_extents(__other.extents()) + { } + + constexpr mapping& + operator=(const mapping&) noexcept = default; + + constexpr const extents_type& + extents() const noexcept { return _M_extents; } + + constexpr index_type + required_span_size() const noexcept + { return __mdspan::__fwd_prod(_M_extents, _M_extents.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: + [[no_unique_address]] _Extents _M_extents; + }; + _GLIBCXX_END_NAMESPACE_VERSION } #endif -- 2.49.0