Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:34

0001 // -*- C++ -*-
0002 //===----------------------------------------------------------------------===//
0003 //
0004 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0005 // See https://llvm.org/LICENSE.txt for license information.
0006 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0007 //
0008 //                        Kokkos v. 4.0
0009 //       Copyright (2022) National Technology & Engineering
0010 //               Solutions of Sandia, LLC (NTESS).
0011 //
0012 // Under the terms of Contract DE-NA0003525 with NTESS,
0013 // the U.S. Government retains certain rights in this software.
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 // ------------ __static_array --------------------------------------
0051 // ------------------------------------------------------------------
0052 // array like class which provides an array of static values with get
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 // ------------ __possibly_empty_array  -----------------------------
0069 // ------------------------------------------------------------------
0070 
0071 // array like class which provides get function and operator [], and
0072 // has a specialization for the size 0 case.
0073 // This is needed to make the __maybe_static_array be truly empty, for
0074 // all static values.
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 // ------------ static_partial_sums ---------------------------------
0091 // ------------------------------------------------------------------
0092 
0093 // Provides a compile time partial sum one can index into
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 // ------------ __maybe_static_array --------------------------------
0114 // ------------------------------------------------------------------
0115 
0116 // array like class which has a mix of static and runtime values but
0117 // only stores the runtime values.
0118 // The type of the static and the runtime values can be different.
0119 // The position of a dynamic value is indicated through a tag value.
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   // Static values member
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   // Dynamic values member
0135   _LIBCPP_NO_UNIQUE_ADDRESS _DynamicValues __dyn_vals_;
0136 
0137   // static mapping of indices to the position in the dynamic values array
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   // constructors from dynamic values only -- this covers the case for rank() == 0
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   // constructors from all values -- here rank will be greater than 0
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         // Not catching this could lead to out of bounds errors later
0176         // e.g. using my_mdspan_t = mdspan<int, extents<int, 10>>; my_mdspan_t = m(new int[5], 5);
0177         // Right-hand-side construction looks ok with allocation and size matching,
0178         // but since (potentially elsewhere defined) my_mdspan_t has static size m now thinks its range is 10 not 5
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         // Not catching this could lead to out of bounds errors later
0195         // e.g. using my_mdspan_t = mdspan<int, extents<int, 10>>; my_mdspan_t = m(new int[N], span<int,1>(&N));
0196         // Right-hand-side construction looks ok with allocation and size matching,
0197         // but since (potentially elsewhere defined) my_mdspan_t has static size m now thinks its range is 10 not N
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   // access functions
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   // observers
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 // Function to check whether a value is representable as another type
0226 // value must be a positive integer otherwise returns false
0227 // if _From is not an integral, we just check positivity
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 } // namespace __mdspan_detail
0268 
0269 // ------------------------------------------------------------------
0270 // ------------ extents ---------------------------------------------
0271 // ------------------------------------------------------------------
0272 
0273 // Class to describe the extents of a multi dimensional array.
0274 // Used by mdspan, mdarray and layout mappings.
0275 // See ISO C++ standard [mdspan.extents]
0276 
0277 template <class _IndexType, size_t... _Extents>
0278 class extents {
0279 public:
0280   // typedefs for integral types used
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   // internal storage type using __maybe_static_array
0295   using _Values = __mdspan_detail::__maybe_static_array<_IndexType, size_t, dynamic_extent, _Extents...>;
0296   [[no_unique_address]] _Values __vals_;
0297 
0298 public:
0299   // [mdspan.extents.obs], observers of multidimensional index space
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   // [mdspan.extents.cons], constructors
0309   _LIBCPP_HIDE_FROM_ABI constexpr extents() noexcept = default;
0310 
0311   // Construction from just dynamic or all values.
0312   // Precondition check is deferred to __maybe_static_array constructor
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     // Not catching this could lead to out of bounds errors later
0320     // e.g. mdspan m(ptr, dextents<char, 1>(200u)); leads to an extent of -56 on m
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     // Not catching this could lead to out of bounds errors later
0333     // e.g. mdspan m(ptr, dextents<char, 1>(array<unsigned,1>(200))); leads to an extent of -56 on m
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     // Not catching this could lead to out of bounds errors later
0346     // e.g. array a{200u}; mdspan<int, dextents<char,1>> m(ptr, extents(span<unsigned,1>(a))); leads to an extent of -56
0347     // on m
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   // Function to construct extents storage from other extents.
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   // Converting constructor from other extents specializations
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           // Not catching this could lead to out of bounds errors later
0399           // e.g. dextents<char,1>> e(dextents<unsigned,1>(200)) leads to an extent of -56 on e
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         // Not catching this could lead to out of bounds errors later
0405         // e.g. mdspan<int, extents<int, 10>> m = mdspan<int, dextents<int, 1>>(new int[5], 5);
0406         // Right-hand-side construction was ok, but m now thinks its range is 10 not 5
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   // Comparison operator
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         // avoid warning when comparing signed and unsigner integers and pick the wider of two types
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 // Recursive helper classes to implement dextents alias for extents
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 } // end namespace __mdspan_detail
0452 
0453 // [mdspan.extents.dextents], alias template
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 // [mdspan.extents.dims], alias template `dims`
0459 template <size_t _Rank, class _IndexType = size_t>
0460 using dims = dextents<_IndexType, _Rank>;
0461 #  endif
0462 
0463 // Deduction guide for extents
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 // Helper type traits for identifying a class as extents.
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 // Function to check whether a set of indices are a multidimensional
0487 // index into extents. This is a word of power in the C++ standard
0488 // requiring that the indices are larger than 0 and smaller than
0489 // the respective extents.
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 } // namespace __mdspan_detail
0525 
0526 #endif // _LIBCPP_STD_VER >= 23
0527 
0528 _LIBCPP_END_NAMESPACE_STD
0529 
0530 _LIBCPP_POP_MACROS
0531 
0532 #endif // _LIBCPP___CXX03___MDSPAN_EXTENTS_H