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_LEFT_H
0018 #define _LIBCPP___MDSPAN_LAYOUT_LEFT_H
0019
0020 #include <__assert>
0021 #include <__config>
0022 #include <__fwd/mdspan.h>
0023 #include <__mdspan/extents.h>
0024 #include <__type_traits/common_type.h>
0025 #include <__type_traits/is_constructible.h>
0026 #include <__type_traits/is_convertible.h>
0027 #include <__type_traits/is_nothrow_constructible.h>
0028 #include <__utility/integer_sequence.h>
0029 #include <array>
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_left::mapping {
0044 public:
0045 static_assert(__mdspan_detail::__is_extents<_Extents>::value,
0046 "layout_left::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_left;
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_left::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_left::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_left::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_right::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_left::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_left::mapping from layout_stride ctor: strides are not compatible with layout_left.");
0126 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0127 __mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
0128 "layout_left::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_left::mapping: out of bounds indexing");
0155 array<index_type, extents_type::rank()> __idx_a{static_cast<index_type>(__idx)...};
0156 return [&]<size_t... _Pos>(index_sequence<_Pos...>) {
0157 index_type __res = 0;
0158 ((__res = __idx_a[extents_type::rank() - 1 - _Pos] + __extents_.extent(extents_type::rank() - 1 - _Pos) * __res),
0159 ...);
0160 return __res;
0161 }(make_index_sequence<sizeof...(_Indices)>());
0162 }
0163
0164 _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_unique() noexcept { return true; }
0165 _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_exhaustive() noexcept { return true; }
0166 _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_strided() noexcept { return true; }
0167
0168 _LIBCPP_HIDE_FROM_ABI static constexpr bool is_unique() noexcept { return true; }
0169 _LIBCPP_HIDE_FROM_ABI static constexpr bool is_exhaustive() noexcept { return true; }
0170 _LIBCPP_HIDE_FROM_ABI static constexpr bool is_strided() noexcept { return true; }
0171
0172 _LIBCPP_HIDE_FROM_ABI constexpr index_type stride(rank_type __r) const noexcept
0173 requires(extents_type::rank() > 0)
0174 {
0175
0176
0177 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0178 __r < extents_type::rank(), "layout_left::mapping::stride(): invalid rank index");
0179 index_type __s = 1;
0180 for (rank_type __i = 0; __i < __r; __i++)
0181 __s *= __extents_.extent(__i);
0182 return __s;
0183 }
0184
0185 template <class _OtherExtents>
0186 requires(_OtherExtents::rank() == extents_type::rank())
0187 _LIBCPP_HIDE_FROM_ABI friend constexpr bool
0188 operator==(const mapping& __lhs, const mapping<_OtherExtents>& __rhs) noexcept {
0189 return __lhs.extents() == __rhs.extents();
0190 }
0191
0192 private:
0193 _LIBCPP_NO_UNIQUE_ADDRESS extents_type __extents_{};
0194 };
0195
0196 #endif
0197
0198 _LIBCPP_END_NAMESPACE_STD
0199
0200 _LIBCPP_POP_MACROS
0201
0202 #endif