File indexing completed on 2026-05-03 08:13:55
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef _LIBCPP___MDSPAN_LAYOUT_RIGHT_H
0018 #define _LIBCPP___MDSPAN_LAYOUT_RIGHT_H
0019
0020 #include <__assert>
0021 #include <__config>
0022 #include <__cstddef/size_t.h>
0023 #include <__fwd/mdspan.h>
0024 #include <__mdspan/extents.h>
0025 #include <__type_traits/common_type.h>
0026 #include <__type_traits/is_constructible.h>
0027 #include <__type_traits/is_convertible.h>
0028 #include <__type_traits/is_nothrow_constructible.h>
0029 #include <__utility/integer_sequence.h>
0030
0031 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0032 # pragma GCC system_header
0033 #endif
0034
0035 _LIBCPP_PUSH_MACROS
0036 #include <__undef_macros>
0037
0038 _LIBCPP_BEGIN_NAMESPACE_STD
0039
0040 #if _LIBCPP_STD_VER >= 23
0041
0042 template <class _Extents>
0043 class layout_right::mapping {
0044 public:
0045 static_assert(__mdspan_detail::__is_extents<_Extents>::value,
0046 "layout_right::mapping template argument must be a specialization of extents.");
0047
0048 using extents_type = _Extents;
0049 using index_type = typename extents_type::index_type;
0050 using size_type = typename extents_type::size_type;
0051 using rank_type = typename extents_type::rank_type;
0052 using layout_type = layout_right;
0053
0054 private:
0055 _LIBCPP_HIDE_FROM_ABI static constexpr bool __required_span_size_is_representable(const extents_type& __ext) {
0056 if constexpr (extents_type::rank() == 0)
0057 return true;
0058
0059 index_type __prod = __ext.extent(0);
0060 for (rank_type __r = 1; __r < extents_type::rank(); __r++) {
0061 bool __overflowed = __builtin_mul_overflow(__prod, __ext.extent(__r), &__prod);
0062 if (__overflowed)
0063 return false;
0064 }
0065 return true;
0066 }
0067
0068 static_assert(extents_type::rank_dynamic() > 0 || __required_span_size_is_representable(extents_type()),
0069 "layout_right::mapping product of static extents must be representable as index_type.");
0070
0071 public:
0072
0073 _LIBCPP_HIDE_FROM_ABI constexpr mapping() noexcept = default;
0074 _LIBCPP_HIDE_FROM_ABI constexpr mapping(const mapping&) noexcept = default;
0075 _LIBCPP_HIDE_FROM_ABI constexpr mapping(const extents_type& __ext) noexcept : __extents_(__ext) {
0076
0077
0078 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0079 __required_span_size_is_representable(__ext),
0080 "layout_right::mapping extents ctor: product of extents must be representable as index_type.");
0081 }
0082
0083 template <class _OtherExtents>
0084 requires(is_constructible_v<extents_type, _OtherExtents>)
0085 _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>)
0086 mapping(const mapping<_OtherExtents>& __other) noexcept
0087 : __extents_(__other.extents()) {
0088
0089
0090 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0091 __mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
0092 "layout_right::mapping converting ctor: other.required_span_size() must be representable as index_type.");
0093 }
0094
0095 template <class _OtherExtents>
0096 requires(is_constructible_v<extents_type, _OtherExtents> && _OtherExtents::rank() <= 1)
0097 _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>)
0098 mapping(const layout_left::mapping<_OtherExtents>& __other) noexcept
0099 : __extents_(__other.extents()) {
0100
0101
0102
0103
0104
0105
0106 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0107 __mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
0108 "layout_right::mapping converting ctor: other.required_span_size() must be representable as index_type.");
0109 }
0110
0111 template <class _OtherExtents>
0112 requires(is_constructible_v<extents_type, _OtherExtents>)
0113 _LIBCPP_HIDE_FROM_ABI constexpr explicit(extents_type::rank() > 0)
0114 mapping(const layout_stride::mapping<_OtherExtents>& __other) noexcept
0115 : __extents_(__other.extents()) {
0116 if constexpr (extents_type::rank() > 0) {
0117 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0118 ([&]() {
0119 using _CommonType = common_type_t<typename extents_type::index_type, typename _OtherExtents::index_type>;
0120 for (rank_type __r = 0; __r < extents_type::rank(); __r++)
0121 if (static_cast<_CommonType>(stride(__r)) != static_cast<_CommonType>(__other.stride(__r)))
0122 return false;
0123 return true;
0124 }()),
0125 "layout_right::mapping from layout_stride ctor: strides are not compatible with layout_right.");
0126 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0127 __mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
0128 "layout_right::mapping from layout_stride ctor: other.required_span_size() must be representable as "
0129 "index_type.");
0130 }
0131 }
0132
0133 _LIBCPP_HIDE_FROM_ABI constexpr mapping& operator=(const mapping&) noexcept = default;
0134
0135
0136 _LIBCPP_HIDE_FROM_ABI constexpr const extents_type& extents() const noexcept { return __extents_; }
0137
0138 _LIBCPP_HIDE_FROM_ABI constexpr index_type required_span_size() const noexcept {
0139 index_type __size = 1;
0140 for (size_t __r = 0; __r < extents_type::rank(); __r++)
0141 __size *= __extents_.extent(__r);
0142 return __size;
0143 }
0144
0145 template <class... _Indices>
0146 requires((sizeof...(_Indices) == extents_type::rank()) && (is_convertible_v<_Indices, index_type> && ...) &&
0147 (is_nothrow_constructible_v<index_type, _Indices> && ...))
0148 _LIBCPP_HIDE_FROM_ABI constexpr index_type operator()(_Indices... __idx) const noexcept {
0149
0150
0151
0152
0153 _LIBCPP_ASSERT_UNCATEGORIZED(__mdspan_detail::__is_multidimensional_index_in(__extents_, __idx...),
0154 "layout_right::mapping: out of bounds indexing");
0155 return [&]<size_t... _Pos>(index_sequence<_Pos...>) {
0156 index_type __res = 0;
0157 ((__res = static_cast<index_type>(__idx) + __extents_.extent(_Pos) * __res), ...);
0158 return __res;
0159 }(make_index_sequence<sizeof...(_Indices)>());
0160 }
0161
0162 _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_unique() noexcept { return true; }
0163 _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_exhaustive() noexcept { return true; }
0164 _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_strided() noexcept { return true; }
0165
0166 _LIBCPP_HIDE_FROM_ABI static constexpr bool is_unique() noexcept { return true; }
0167 _LIBCPP_HIDE_FROM_ABI static constexpr bool is_exhaustive() noexcept { return true; }
0168 _LIBCPP_HIDE_FROM_ABI static constexpr bool is_strided() noexcept { return true; }
0169
0170 _LIBCPP_HIDE_FROM_ABI constexpr index_type stride(rank_type __r) const noexcept
0171 requires(extents_type::rank() > 0)
0172 {
0173
0174
0175 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0176 __r < extents_type::rank(), "layout_right::mapping::stride(): invalid rank index");
0177 index_type __s = 1;
0178 for (rank_type __i = extents_type::rank() - 1; __i > __r; __i--)
0179 __s *= __extents_.extent(__i);
0180 return __s;
0181 }
0182
0183 template <class _OtherExtents>
0184 requires(_OtherExtents::rank() == extents_type::rank())
0185 _LIBCPP_HIDE_FROM_ABI friend constexpr bool
0186 operator==(const mapping& __lhs, const mapping<_OtherExtents>& __rhs) noexcept {
0187 return __lhs.extents() == __rhs.extents();
0188 }
0189
0190 private:
0191 _LIBCPP_NO_UNIQUE_ADDRESS extents_type __extents_{};
0192 };
0193
0194 #endif
0195
0196 _LIBCPP_END_NAMESPACE_STD
0197
0198 _LIBCPP_POP_MACROS
0199
0200 #endif