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