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_EXTENTS_H
0018 #define _LIBCPP___CXX03___MDSPAN_EXTENTS_H
0019
0020 #include <__cxx03/__assert>
0021 #include <__cxx03/__config>
0022 #include <__cxx03/__type_traits/common_type.h>
0023 #include <__cxx03/__type_traits/is_convertible.h>
0024 #include <__cxx03/__type_traits/is_nothrow_constructible.h>
0025 #include <__cxx03/__type_traits/is_same.h>
0026 #include <__cxx03/__type_traits/make_unsigned.h>
0027 #include <__cxx03/__utility/integer_sequence.h>
0028 #include <__cxx03/__utility/unreachable.h>
0029 #include <__cxx03/array>
0030 #include <__cxx03/cinttypes>
0031 #include <__cxx03/concepts>
0032 #include <__cxx03/cstddef>
0033 #include <__cxx03/limits>
0034 #include <__cxx03/span>
0035
0036 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0037 # pragma GCC system_header
0038 #endif
0039
0040 _LIBCPP_PUSH_MACROS
0041 #include <__cxx03/__undef_macros>
0042
0043 _LIBCPP_BEGIN_NAMESPACE_STD
0044
0045 #if _LIBCPP_STD_VER >= 23
0046
0047 namespace __mdspan_detail {
0048
0049
0050
0051
0052
0053 template <class _Tp, _Tp... _Values>
0054 struct __static_array {
0055 static constexpr array<_Tp, sizeof...(_Values)> __array = {_Values...};
0056
0057 public:
0058 _LIBCPP_HIDE_FROM_ABI static constexpr size_t __size() { return sizeof...(_Values); }
0059 _LIBCPP_HIDE_FROM_ABI static constexpr _Tp __get(size_t __index) noexcept { return __array[__index]; }
0060
0061 template <size_t _Index>
0062 _LIBCPP_HIDE_FROM_ABI static constexpr _Tp __get() {
0063 return __get(_Index);
0064 }
0065 };
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 template <class _Tp, size_t _Size>
0077 struct __possibly_empty_array {
0078 _Tp __vals_[_Size];
0079 _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator[](size_t __index) { return __vals_[__index]; }
0080 _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator[](size_t __index) const { return __vals_[__index]; }
0081 };
0082
0083 template <class _Tp>
0084 struct __possibly_empty_array<_Tp, 0> {
0085 _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator[](size_t) { __libcpp_unreachable(); }
0086 _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator[](size_t) const { __libcpp_unreachable(); }
0087 };
0088
0089
0090
0091
0092
0093
0094
0095 template <size_t... _Values>
0096 struct __static_partial_sums {
0097 _LIBCPP_HIDE_FROM_ABI static constexpr array<size_t, sizeof...(_Values)> __static_partial_sums_impl() {
0098 array<size_t, sizeof...(_Values)> __values{_Values...};
0099 array<size_t, sizeof...(_Values)> __partial_sums{{}};
0100 size_t __running_sum = 0;
0101 for (int __i = 0; __i != sizeof...(_Values); ++__i) {
0102 __partial_sums[__i] = __running_sum;
0103 __running_sum += __values[__i];
0104 }
0105 return __partial_sums;
0106 }
0107 static constexpr array<size_t, sizeof...(_Values)> __result{__static_partial_sums_impl()};
0108
0109 _LIBCPP_HIDE_FROM_ABI static constexpr size_t __get(size_t __index) { return __result[__index]; }
0110 };
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120 template <class _TDynamic, class _TStatic, _TStatic _DynTag, _TStatic... _Values>
0121 struct __maybe_static_array {
0122 static_assert(is_convertible<_TStatic, _TDynamic>::value,
0123 "__maybe_static_array: _TStatic must be convertible to _TDynamic");
0124 static_assert(is_convertible<_TDynamic, _TStatic>::value,
0125 "__maybe_static_array: _TDynamic must be convertible to _TStatic");
0126
0127 private:
0128
0129 static constexpr size_t __size_ = sizeof...(_Values);
0130 static constexpr size_t __size_dynamic_ = ((_Values == _DynTag) + ... + 0);
0131 using _StaticValues = __static_array<_TStatic, _Values...>;
0132 using _DynamicValues = __possibly_empty_array<_TDynamic, __size_dynamic_>;
0133
0134
0135 _LIBCPP_NO_UNIQUE_ADDRESS _DynamicValues __dyn_vals_;
0136
0137
0138 using _DynamicIdxMap = __static_partial_sums<static_cast<size_t>(_Values == _DynTag)...>;
0139
0140 template <size_t... _Indices>
0141 _LIBCPP_HIDE_FROM_ABI static constexpr _DynamicValues __zeros(index_sequence<_Indices...>) noexcept {
0142 return _DynamicValues{((void)_Indices, 0)...};
0143 }
0144
0145 public:
0146 _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array() noexcept
0147 : __dyn_vals_{__zeros(make_index_sequence<__size_dynamic_>())} {}
0148
0149
0150 template <class... _DynVals>
0151 requires(sizeof...(_DynVals) == __size_dynamic_)
0152 _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array(_DynVals... __vals)
0153 : __dyn_vals_{static_cast<_TDynamic>(__vals)...} {}
0154
0155 template <class _Tp, size_t _Size >
0156 requires(_Size == __size_dynamic_)
0157 _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array([[maybe_unused]] const span<_Tp, _Size>& __vals) {
0158 if constexpr (_Size > 0) {
0159 for (size_t __i = 0; __i < _Size; __i++)
0160 __dyn_vals_[__i] = static_cast<_TDynamic>(__vals[__i]);
0161 }
0162 }
0163
0164
0165 template <class... _DynVals>
0166 requires(sizeof...(_DynVals) != __size_dynamic_)
0167 _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array(_DynVals... __vals) {
0168 static_assert(sizeof...(_DynVals) == __size_, "Invalid number of values.");
0169 _TDynamic __values[__size_] = {static_cast<_TDynamic>(__vals)...};
0170 for (size_t __i = 0; __i < __size_; __i++) {
0171 _TStatic __static_val = _StaticValues::__get(__i);
0172 if (__static_val == _DynTag) {
0173 __dyn_vals_[_DynamicIdxMap::__get(__i)] = __values[__i];
0174 } else
0175
0176
0177
0178
0179 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0180 __values[__i] == static_cast<_TDynamic>(__static_val),
0181 "extents construction: mismatch of provided arguments with static extents.");
0182 }
0183 }
0184
0185 template <class _Tp, size_t _Size>
0186 requires(_Size != __size_dynamic_)
0187 _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array(const span<_Tp, _Size>& __vals) {
0188 static_assert(_Size == __size_ || __size_ == dynamic_extent);
0189 for (size_t __i = 0; __i < __size_; __i++) {
0190 _TStatic __static_val = _StaticValues::__get(__i);
0191 if (__static_val == _DynTag) {
0192 __dyn_vals_[_DynamicIdxMap::__get(__i)] = static_cast<_TDynamic>(__vals[__i]);
0193 } else
0194
0195
0196
0197
0198 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0199 static_cast<_TDynamic>(__vals[__i]) == static_cast<_TDynamic>(__static_val),
0200 "extents construction: mismatch of provided arguments with static extents.");
0201 }
0202 }
0203
0204
0205 _LIBCPP_HIDE_FROM_ABI static constexpr _TStatic __static_value(size_t __i) noexcept {
0206 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < __size_, "extents access: index must be less than rank");
0207 return _StaticValues::__get(__i);
0208 }
0209
0210 _LIBCPP_HIDE_FROM_ABI constexpr _TDynamic __value(size_t __i) const {
0211 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < __size_, "extents access: index must be less than rank");
0212 _TStatic __static_val = _StaticValues::__get(__i);
0213 return __static_val == _DynTag ? __dyn_vals_[_DynamicIdxMap::__get(__i)] : static_cast<_TDynamic>(__static_val);
0214 }
0215 _LIBCPP_HIDE_FROM_ABI constexpr _TDynamic operator[](size_t __i) const {
0216 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < __size_, "extents access: index must be less than rank");
0217 return __value(__i);
0218 }
0219
0220
0221 _LIBCPP_HIDE_FROM_ABI static constexpr size_t __size() { return __size_; }
0222 _LIBCPP_HIDE_FROM_ABI static constexpr size_t __size_dynamic() { return __size_dynamic_; }
0223 };
0224
0225
0226
0227
0228 template <integral _To, class _From>
0229 requires(integral<_From>)
0230 _LIBCPP_HIDE_FROM_ABI constexpr bool __is_representable_as(_From __value) {
0231 using _To_u = make_unsigned_t<_To>;
0232 using _From_u = make_unsigned_t<_From>;
0233 if constexpr (is_signed_v<_From>) {
0234 if (__value < 0)
0235 return false;
0236 }
0237 if constexpr (static_cast<_To_u>(numeric_limits<_To>::max()) >= static_cast<_From_u>(numeric_limits<_From>::max())) {
0238 return true;
0239 } else {
0240 return static_cast<_To_u>(numeric_limits<_To>::max()) >= static_cast<_From_u>(__value);
0241 }
0242 }
0243
0244 template <integral _To, class _From>
0245 requires(!integral<_From>)
0246 _LIBCPP_HIDE_FROM_ABI constexpr bool __is_representable_as(_From __value) {
0247 if constexpr (is_signed_v<_To>) {
0248 if (static_cast<_To>(__value) < 0)
0249 return false;
0250 }
0251 return true;
0252 }
0253
0254 template <integral _To, class... _From>
0255 _LIBCPP_HIDE_FROM_ABI constexpr bool __are_representable_as(_From... __values) {
0256 return (__mdspan_detail::__is_representable_as<_To>(__values) && ... && true);
0257 }
0258
0259 template <integral _To, class _From, size_t _Size>
0260 _LIBCPP_HIDE_FROM_ABI constexpr bool __are_representable_as(span<_From, _Size> __values) {
0261 for (size_t __i = 0; __i < _Size; __i++)
0262 if (!__mdspan_detail::__is_representable_as<_To>(__values[__i]))
0263 return false;
0264 return true;
0265 }
0266
0267 }
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277 template <class _IndexType, size_t... _Extents>
0278 class extents {
0279 public:
0280
0281 using index_type = _IndexType;
0282 using size_type = make_unsigned_t<index_type>;
0283 using rank_type = size_t;
0284
0285 static_assert(is_integral<index_type>::value && !is_same<index_type, bool>::value,
0286 "extents::index_type must be a signed or unsigned integer type");
0287 static_assert(((__mdspan_detail::__is_representable_as<index_type>(_Extents) || (_Extents == dynamic_extent)) && ...),
0288 "extents ctor: arguments must be representable as index_type and nonnegative");
0289
0290 private:
0291 static constexpr rank_type __rank_ = sizeof...(_Extents);
0292 static constexpr rank_type __rank_dynamic_ = ((_Extents == dynamic_extent) + ... + 0);
0293
0294
0295 using _Values = __mdspan_detail::__maybe_static_array<_IndexType, size_t, dynamic_extent, _Extents...>;
0296 [[no_unique_address]] _Values __vals_;
0297
0298 public:
0299
0300 _LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank() noexcept { return __rank_; }
0301 _LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank_dynamic() noexcept { return __rank_dynamic_; }
0302
0303 _LIBCPP_HIDE_FROM_ABI constexpr index_type extent(rank_type __r) const noexcept { return __vals_.__value(__r); }
0304 _LIBCPP_HIDE_FROM_ABI static constexpr size_t static_extent(rank_type __r) noexcept {
0305 return _Values::__static_value(__r);
0306 }
0307
0308
0309 _LIBCPP_HIDE_FROM_ABI constexpr extents() noexcept = default;
0310
0311
0312
0313 template <class... _OtherIndexTypes>
0314 requires((is_convertible_v<_OtherIndexTypes, index_type> && ...) &&
0315 (is_nothrow_constructible_v<index_type, _OtherIndexTypes> && ...) &&
0316 (sizeof...(_OtherIndexTypes) == __rank_ || sizeof...(_OtherIndexTypes) == __rank_dynamic_))
0317 _LIBCPP_HIDE_FROM_ABI constexpr explicit extents(_OtherIndexTypes... __dynvals) noexcept
0318 : __vals_(static_cast<index_type>(__dynvals)...) {
0319
0320
0321 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__are_representable_as<index_type>(__dynvals...),
0322 "extents ctor: arguments must be representable as index_type and nonnegative");
0323 }
0324
0325 template <class _OtherIndexType, size_t _Size>
0326 requires(is_convertible_v<const _OtherIndexType&, index_type> &&
0327 is_nothrow_constructible_v<index_type, const _OtherIndexType&> &&
0328 (_Size == __rank_ || _Size == __rank_dynamic_))
0329 explicit(_Size != __rank_dynamic_)
0330 _LIBCPP_HIDE_FROM_ABI constexpr extents(const array<_OtherIndexType, _Size>& __exts) noexcept
0331 : __vals_(span(__exts)) {
0332
0333
0334 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__are_representable_as<index_type>(span(__exts)),
0335 "extents ctor: arguments must be representable as index_type and nonnegative");
0336 }
0337
0338 template <class _OtherIndexType, size_t _Size>
0339 requires(is_convertible_v<const _OtherIndexType&, index_type> &&
0340 is_nothrow_constructible_v<index_type, const _OtherIndexType&> &&
0341 (_Size == __rank_ || _Size == __rank_dynamic_))
0342 explicit(_Size != __rank_dynamic_)
0343 _LIBCPP_HIDE_FROM_ABI constexpr extents(const span<_OtherIndexType, _Size>& __exts) noexcept
0344 : __vals_(__exts) {
0345
0346
0347
0348 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__are_representable_as<index_type>(__exts),
0349 "extents ctor: arguments must be representable as index_type and nonnegative");
0350 }
0351
0352 private:
0353
0354 template <size_t _DynCount, size_t _Idx, class _OtherExtents, class... _DynamicValues>
0355 requires(_Idx < __rank_)
0356 _LIBCPP_HIDE_FROM_ABI constexpr _Values __construct_vals_from_extents(
0357 integral_constant<size_t, _DynCount>,
0358 integral_constant<size_t, _Idx>,
0359 const _OtherExtents& __exts,
0360 _DynamicValues... __dynamic_values) noexcept {
0361 if constexpr (static_extent(_Idx) == dynamic_extent)
0362 return __construct_vals_from_extents(
0363 integral_constant<size_t, _DynCount + 1>(),
0364 integral_constant<size_t, _Idx + 1>(),
0365 __exts,
0366 __dynamic_values...,
0367 __exts.extent(_Idx));
0368 else
0369 return __construct_vals_from_extents(
0370 integral_constant<size_t, _DynCount>(), integral_constant<size_t, _Idx + 1>(), __exts, __dynamic_values...);
0371 }
0372
0373 template <size_t _DynCount, size_t _Idx, class _OtherExtents, class... _DynamicValues>
0374 requires((_Idx == __rank_) && (_DynCount == __rank_dynamic_))
0375 _LIBCPP_HIDE_FROM_ABI constexpr _Values __construct_vals_from_extents(
0376 integral_constant<size_t, _DynCount>,
0377 integral_constant<size_t, _Idx>,
0378 const _OtherExtents&,
0379 _DynamicValues... __dynamic_values) noexcept {
0380 return _Values{static_cast<index_type>(__dynamic_values)...};
0381 }
0382
0383 public:
0384
0385 template <class _OtherIndexType, size_t... _OtherExtents>
0386 requires((sizeof...(_OtherExtents) == sizeof...(_Extents)) &&
0387 ((_OtherExtents == dynamic_extent || _Extents == dynamic_extent || _OtherExtents == _Extents) && ...))
0388 explicit((((_Extents != dynamic_extent) && (_OtherExtents == dynamic_extent)) || ...) ||
0389 (static_cast<make_unsigned_t<index_type>>(numeric_limits<index_type>::max()) <
0390 static_cast<make_unsigned_t<_OtherIndexType>>(numeric_limits<_OtherIndexType>::max())))
0391 _LIBCPP_HIDE_FROM_ABI constexpr extents(const extents<_OtherIndexType, _OtherExtents...>& __other) noexcept
0392 : __vals_(
0393 __construct_vals_from_extents(integral_constant<size_t, 0>(), integral_constant<size_t, 0>(), __other)) {
0394 if constexpr (rank() > 0) {
0395 for (size_t __r = 0; __r < rank(); __r++) {
0396 if constexpr (static_cast<make_unsigned_t<index_type>>(numeric_limits<index_type>::max()) <
0397 static_cast<make_unsigned_t<_OtherIndexType>>(numeric_limits<_OtherIndexType>::max())) {
0398
0399
0400 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0401 __mdspan_detail::__is_representable_as<index_type>(__other.extent(__r)),
0402 "extents ctor: arguments must be representable as index_type and nonnegative");
0403 }
0404
0405
0406
0407 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0408 (_Values::__static_value(__r) == dynamic_extent) ||
0409 (static_cast<index_type>(__other.extent(__r)) == static_cast<index_type>(_Values::__static_value(__r))),
0410 "extents construction: mismatch of provided arguments with static extents.");
0411 }
0412 }
0413 }
0414
0415
0416 template <class _OtherIndexType, size_t... _OtherExtents>
0417 _LIBCPP_HIDE_FROM_ABI friend constexpr bool
0418 operator==(const extents& __lhs, const extents<_OtherIndexType, _OtherExtents...>& __rhs) noexcept {
0419 if constexpr (rank() != sizeof...(_OtherExtents)) {
0420 return false;
0421 } else {
0422 for (rank_type __r = 0; __r < __rank_; __r++) {
0423
0424 using _CommonType = common_type_t<index_type, _OtherIndexType>;
0425 if (static_cast<_CommonType>(__lhs.extent(__r)) != static_cast<_CommonType>(__rhs.extent(__r))) {
0426 return false;
0427 }
0428 }
0429 }
0430 return true;
0431 }
0432 };
0433
0434
0435 namespace __mdspan_detail {
0436
0437 template <class _IndexType, size_t _Rank, class _Extents = extents<_IndexType>>
0438 struct __make_dextents;
0439
0440 template <class _IndexType, size_t _Rank, size_t... _ExtentsPack>
0441 struct __make_dextents< _IndexType, _Rank, extents<_IndexType, _ExtentsPack...>> {
0442 using type =
0443 typename __make_dextents< _IndexType, _Rank - 1, extents<_IndexType, dynamic_extent, _ExtentsPack...>>::type;
0444 };
0445
0446 template <class _IndexType, size_t... _ExtentsPack>
0447 struct __make_dextents< _IndexType, 0, extents<_IndexType, _ExtentsPack...>> {
0448 using type = extents<_IndexType, _ExtentsPack...>;
0449 };
0450
0451 }
0452
0453
0454 template <class _IndexType, size_t _Rank>
0455 using dextents = typename __mdspan_detail::__make_dextents<_IndexType, _Rank>::type;
0456
0457 # if _LIBCPP_STD_VER >= 26
0458
0459 template <size_t _Rank, class _IndexType = size_t>
0460 using dims = dextents<_IndexType, _Rank>;
0461 # endif
0462
0463
0464 # if _LIBCPP_STD_VER >= 26
0465 template <class... _IndexTypes>
0466 requires(is_convertible_v<_IndexTypes, size_t> && ...)
0467 explicit extents(_IndexTypes...) -> extents<size_t, __maybe_static_ext<_IndexTypes>...>;
0468 # else
0469 template <class... _IndexTypes>
0470 requires(is_convertible_v<_IndexTypes, size_t> && ...)
0471 explicit extents(_IndexTypes...) -> extents<size_t, size_t(((void)sizeof(_IndexTypes), dynamic_extent))...>;
0472 # endif
0473
0474 namespace __mdspan_detail {
0475
0476
0477 template <class _Tp>
0478 struct __is_extents : false_type {};
0479
0480 template <class _IndexType, size_t... _ExtentsPack>
0481 struct __is_extents<extents<_IndexType, _ExtentsPack...>> : true_type {};
0482
0483 template <class _Tp>
0484 inline constexpr bool __is_extents_v = __is_extents<_Tp>::value;
0485
0486
0487
0488
0489
0490
0491 template <integral _IndexType, class _From>
0492 requires(integral<_From>)
0493 _LIBCPP_HIDE_FROM_ABI constexpr bool __is_index_in_extent(_IndexType __extent, _From __value) {
0494 if constexpr (is_signed_v<_From>) {
0495 if (__value < 0)
0496 return false;
0497 }
0498 using _Tp = common_type_t<_IndexType, _From>;
0499 return static_cast<_Tp>(__value) < static_cast<_Tp>(__extent);
0500 }
0501
0502 template <integral _IndexType, class _From>
0503 requires(!integral<_From>)
0504 _LIBCPP_HIDE_FROM_ABI constexpr bool __is_index_in_extent(_IndexType __extent, _From __value) {
0505 if constexpr (is_signed_v<_IndexType>) {
0506 if (static_cast<_IndexType>(__value) < 0)
0507 return false;
0508 }
0509 return static_cast<_IndexType>(__value) < __extent;
0510 }
0511
0512 template <size_t... _Idxs, class _Extents, class... _From>
0513 _LIBCPP_HIDE_FROM_ABI constexpr bool
0514 __is_multidimensional_index_in_impl(index_sequence<_Idxs...>, const _Extents& __ext, _From... __values) {
0515 return (__mdspan_detail::__is_index_in_extent(__ext.extent(_Idxs), __values) && ...);
0516 }
0517
0518 template <class _Extents, class... _From>
0519 _LIBCPP_HIDE_FROM_ABI constexpr bool __is_multidimensional_index_in(const _Extents& __ext, _From... __values) {
0520 return __mdspan_detail::__is_multidimensional_index_in_impl(
0521 make_index_sequence<_Extents::rank()>(), __ext, __values...);
0522 }
0523
0524 }
0525
0526 #endif
0527
0528 _LIBCPP_END_NAMESPACE_STD
0529
0530 _LIBCPP_POP_MACROS
0531
0532 #endif