brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.2 KiB · d16bbd2 Raw
537 lines · c
1// -*- C++ -*-2//===----------------------------------------------------------------------===//3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//                        Kokkos v. 4.09//       Copyright (2022) National Technology & Engineering10//               Solutions of Sandia, LLC (NTESS).11//12// Under the terms of Contract DE-NA0003525 with NTESS,13// the U.S. Government retains certain rights in this software.14//15//===---------------------------------------------------------------------===//16 17#ifndef _LIBCPP___MDSPAN_EXTENTS_H18#define _LIBCPP___MDSPAN_EXTENTS_H19 20#include <__assert>21#include <__config>22 23#include <__concepts/arithmetic.h>24#include <__type_traits/common_type.h>25#include <__type_traits/integer_traits.h>26#include <__type_traits/is_convertible.h>27#include <__type_traits/is_nothrow_constructible.h>28#include <__type_traits/is_signed.h>29#include <__type_traits/make_unsigned.h>30#include <__utility/integer_sequence.h>31#include <__utility/unreachable.h>32#include <array>33#include <concepts>34#include <limits>35#include <span>36 37#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)38#  pragma GCC system_header39#endif40 41_LIBCPP_PUSH_MACROS42#include <__undef_macros>43 44_LIBCPP_BEGIN_NAMESPACE_STD45 46#if _LIBCPP_STD_VER >= 2347 48namespace __mdspan_detail {49 50// ------------------------------------------------------------------51// ------------ __static_array --------------------------------------52// ------------------------------------------------------------------53// array like class which provides an array of static values with get54template <class _Tp, _Tp... _Values>55struct __static_array {56  static constexpr array<_Tp, sizeof...(_Values)> __array = {_Values...};57 58public:59  _LIBCPP_HIDE_FROM_ABI static constexpr size_t __size() { return sizeof...(_Values); }60  _LIBCPP_HIDE_FROM_ABI static constexpr _Tp __get(size_t __index) noexcept { return __array[__index]; }61 62  template <size_t _Index>63  _LIBCPP_HIDE_FROM_ABI static constexpr _Tp __get() {64    return __get(_Index);65  }66};67 68// ------------------------------------------------------------------69// ------------ __possibly_empty_array  -----------------------------70// ------------------------------------------------------------------71 72// array like class which provides get function and operator [], and73// has a specialization for the size 0 case.74// This is needed to make the __maybe_static_array be truly empty, for75// all static values.76 77template <class _Tp, size_t _Size>78struct __possibly_empty_array {79  _Tp __vals_[_Size];80  _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator[](size_t __index) { return __vals_[__index]; }81  _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator[](size_t __index) const { return __vals_[__index]; }82};83 84template <class _Tp>85struct __possibly_empty_array<_Tp, 0> {86  _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator[](size_t) { __libcpp_unreachable(); }87  _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator[](size_t) const { __libcpp_unreachable(); }88};89 90// ------------------------------------------------------------------91// ------------ static_partial_sums ---------------------------------92// ------------------------------------------------------------------93 94// Provides a compile time partial sum one can index into95 96template <size_t... _Values>97struct __static_partial_sums {98  _LIBCPP_HIDE_FROM_ABI static constexpr array<size_t, sizeof...(_Values)> __static_partial_sums_impl() {99    array<size_t, sizeof...(_Values)> __values{_Values...};100    array<size_t, sizeof...(_Values)> __partial_sums{{}};101    size_t __running_sum = 0;102    for (int __i = 0; __i != sizeof...(_Values); ++__i) {103      __partial_sums[__i] = __running_sum;104      __running_sum += __values[__i];105    }106    return __partial_sums;107  }108  static constexpr array<size_t, sizeof...(_Values)> __result{__static_partial_sums_impl()};109 110  _LIBCPP_HIDE_FROM_ABI static constexpr size_t __get(size_t __index) { return __result[__index]; }111};112 113// ------------------------------------------------------------------114// ------------ __maybe_static_array --------------------------------115// ------------------------------------------------------------------116 117// array like class which has a mix of static and runtime values but118// only stores the runtime values.119// The type of the static and the runtime values can be different.120// The position of a dynamic value is indicated through a tag value.121template <class _TDynamic, class _TStatic, _TStatic _DynTag, _TStatic... _Values>122struct __maybe_static_array {123  static_assert(is_convertible<_TStatic, _TDynamic>::value,124                "__maybe_static_array: _TStatic must be convertible to _TDynamic");125  static_assert(is_convertible<_TDynamic, _TStatic>::value,126                "__maybe_static_array: _TDynamic must be convertible to _TStatic");127 128private:129  // Static values member130  static constexpr size_t __size_         = sizeof...(_Values);131  static constexpr size_t __size_dynamic_ = ((_Values == _DynTag) + ... + 0);132  using _StaticValues _LIBCPP_NODEBUG     = __static_array<_TStatic, _Values...>;133  using _DynamicValues _LIBCPP_NODEBUG    = __possibly_empty_array<_TDynamic, __size_dynamic_>;134 135  // Dynamic values member136  _LIBCPP_NO_UNIQUE_ADDRESS _DynamicValues __dyn_vals_;137 138  // static mapping of indices to the position in the dynamic values array139  using _DynamicIdxMap _LIBCPP_NODEBUG = __static_partial_sums<static_cast<size_t>(_Values == _DynTag)...>;140 141  template <size_t... _Indices>142  _LIBCPP_HIDE_FROM_ABI static constexpr _DynamicValues __zeros(index_sequence<_Indices...>) noexcept {143    return _DynamicValues{((void)_Indices, 0)...};144  }145 146public:147  _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array() noexcept148      : __dyn_vals_{__zeros(make_index_sequence<__size_dynamic_>())} {}149 150  // constructors from dynamic values only -- this covers the case for rank() == 0151  template <class... _DynVals>152    requires(sizeof...(_DynVals) == __size_dynamic_)153  _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array(_DynVals... __vals)154      : __dyn_vals_{static_cast<_TDynamic>(__vals)...} {}155 156  template <class _Tp, size_t _Size >157    requires(_Size == __size_dynamic_)158  _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array([[maybe_unused]] const span<_Tp, _Size>& __vals) {159    if constexpr (_Size > 0) {160      for (size_t __i = 0; __i < _Size; __i++)161        __dyn_vals_[__i] = static_cast<_TDynamic>(__vals[__i]);162    }163  }164 165  // constructors from all values -- here rank will be greater than 0166  template <class... _DynVals>167    requires(sizeof...(_DynVals) != __size_dynamic_)168  _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array(_DynVals... __vals) {169    static_assert(sizeof...(_DynVals) == __size_, "Invalid number of values.");170    _TDynamic __values[__size_] = {static_cast<_TDynamic>(__vals)...};171    for (size_t __i = 0; __i < __size_; __i++) {172      _TStatic __static_val = _StaticValues::__get(__i);173      if (__static_val == _DynTag) {174        __dyn_vals_[_DynamicIdxMap::__get(__i)] = __values[__i];175      } else176        // Not catching this could lead to out of bounds errors later177        // e.g. using my_mdspan_t = mdspan<int, extents<int, 10>>; my_mdspan_t = m(new int[5], 5);178        // Right-hand-side construction looks ok with allocation and size matching,179        // but since (potentially elsewhere defined) my_mdspan_t has static size m now thinks its range is 10 not 5180        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(181            __values[__i] == static_cast<_TDynamic>(__static_val),182            "extents construction: mismatch of provided arguments with static extents.");183    }184  }185 186  template <class _Tp, size_t _Size>187    requires(_Size != __size_dynamic_)188  _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array(const span<_Tp, _Size>& __vals) {189    static_assert(_Size == __size_ || __size_ == dynamic_extent);190    for (size_t __i = 0; __i < __size_; __i++) {191      _TStatic __static_val = _StaticValues::__get(__i);192      if (__static_val == _DynTag) {193        __dyn_vals_[_DynamicIdxMap::__get(__i)] = static_cast<_TDynamic>(__vals[__i]);194      } else195        // Not catching this could lead to out of bounds errors later196        // e.g. using my_mdspan_t = mdspan<int, extents<int, 10>>; my_mdspan_t = m(new int[N], span<int,1>(&N));197        // Right-hand-side construction looks ok with allocation and size matching,198        // but since (potentially elsewhere defined) my_mdspan_t has static size m now thinks its range is 10 not N199        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(200            static_cast<_TDynamic>(__vals[__i]) == static_cast<_TDynamic>(__static_val),201            "extents construction: mismatch of provided arguments with static extents.");202    }203  }204 205  // access functions206  _LIBCPP_HIDE_FROM_ABI static constexpr _TStatic __static_value(size_t __i) noexcept {207    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < __size_, "extents access: index must be less than rank");208    return _StaticValues::__get(__i);209  }210 211  _LIBCPP_HIDE_FROM_ABI constexpr _TDynamic __value(size_t __i) const {212    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < __size_, "extents access: index must be less than rank");213    _TStatic __static_val = _StaticValues::__get(__i);214    return __static_val == _DynTag ? __dyn_vals_[_DynamicIdxMap::__get(__i)] : static_cast<_TDynamic>(__static_val);215  }216  _LIBCPP_HIDE_FROM_ABI constexpr _TDynamic operator[](size_t __i) const {217    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < __size_, "extents access: index must be less than rank");218    return __value(__i);219  }220 221  // observers222  _LIBCPP_HIDE_FROM_ABI static constexpr size_t __size() { return __size_; }223  _LIBCPP_HIDE_FROM_ABI static constexpr size_t __size_dynamic() { return __size_dynamic_; }224};225 226// Function to check whether a value is representable as another type227// value must be a positive integer otherwise returns false228// if _From is not an integral, we just check positivity229template <integral _To, class _From>230  requires(integral<_From>)231_LIBCPP_HIDE_FROM_ABI constexpr bool __is_representable_as(_From __value) {232  using _To_u   = make_unsigned_t<_To>;233  using _From_u = make_unsigned_t<_From>;234  if constexpr (is_signed_v<_From>) {235    if (__value < 0)236      return false;237  }238  if constexpr (static_cast<_To_u>(numeric_limits<_To>::max()) >= static_cast<_From_u>(numeric_limits<_From>::max())) {239    return true;240  } else {241    return static_cast<_To_u>(numeric_limits<_To>::max()) >= static_cast<_From_u>(__value);242  }243}244 245template <integral _To, class _From>246  requires(!integral<_From>)247_LIBCPP_HIDE_FROM_ABI constexpr bool __is_representable_as(_From __value) {248  if constexpr (is_signed_v<_To>) {249    if (static_cast<_To>(__value) < 0)250      return false;251  }252  return true;253}254 255template <integral _To, class... _From>256_LIBCPP_HIDE_FROM_ABI constexpr bool __are_representable_as(_From... __values) {257  return (__mdspan_detail::__is_representable_as<_To>(__values) && ... && true);258}259 260template <integral _To, class _From, size_t _Size>261_LIBCPP_HIDE_FROM_ABI constexpr bool __are_representable_as(span<_From, _Size> __values) {262  for (size_t __i = 0; __i < _Size; __i++)263    if (!__mdspan_detail::__is_representable_as<_To>(__values[__i]))264      return false;265  return true;266}267 268} // namespace __mdspan_detail269 270// ------------------------------------------------------------------271// ------------ extents ---------------------------------------------272// ------------------------------------------------------------------273 274// Class to describe the extents of a multi dimensional array.275// Used by mdspan, mdarray and layout mappings.276// See ISO C++ standard [mdspan.extents]277 278template <class _IndexType, size_t... _Extents>279class extents {280public:281  // typedefs for integral types used282  using index_type = _IndexType;283  using size_type  = make_unsigned_t<index_type>;284  using rank_type  = size_t;285 286  static_assert(__signed_or_unsigned_integer<index_type>,287                "extents::index_type must be a signed or unsigned integer type");288  static_assert(((__mdspan_detail::__is_representable_as<index_type>(_Extents) || (_Extents == dynamic_extent)) && ...),289                "extents ctor: arguments must be representable as index_type and nonnegative");290 291private:292  static constexpr rank_type __rank_         = sizeof...(_Extents);293  static constexpr rank_type __rank_dynamic_ = ((_Extents == dynamic_extent) + ... + 0);294 295  // internal storage type using __maybe_static_array296  using _Values _LIBCPP_NODEBUG =297      __mdspan_detail::__maybe_static_array<_IndexType, size_t, dynamic_extent, _Extents...>;298  [[no_unique_address]] _Values __vals_;299 300public:301  // [mdspan.extents.obs], observers of multidimensional index space302  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank() noexcept { return __rank_; }303  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank_dynamic() noexcept { return __rank_dynamic_; }304 305  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr index_type extent(rank_type __r) const noexcept {306    return __vals_.__value(__r);307  }308  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr size_t static_extent(rank_type __r) noexcept {309    return _Values::__static_value(__r);310  }311 312  // [mdspan.extents.cons], constructors313  _LIBCPP_HIDE_FROM_ABI constexpr extents() noexcept = default;314 315  // Construction from just dynamic or all values.316  // Precondition check is deferred to __maybe_static_array constructor317  template <class... _OtherIndexTypes>318    requires((is_convertible_v<_OtherIndexTypes, index_type> && ...) &&319             (is_nothrow_constructible_v<index_type, _OtherIndexTypes> && ...) &&320             (sizeof...(_OtherIndexTypes) == __rank_ || sizeof...(_OtherIndexTypes) == __rank_dynamic_))321  _LIBCPP_HIDE_FROM_ABI constexpr explicit extents(_OtherIndexTypes... __dynvals) noexcept322      : __vals_(static_cast<index_type>(__dynvals)...) {323    // Not catching this could lead to out of bounds errors later324    // e.g. mdspan m(ptr, dextents<char, 1>(200u)); leads to an extent of -56 on m325    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__are_representable_as<index_type>(__dynvals...),326                                        "extents ctor: arguments must be representable as index_type and nonnegative");327  }328 329  template <class _OtherIndexType, size_t _Size>330    requires(is_convertible_v<const _OtherIndexType&, index_type> &&331             is_nothrow_constructible_v<index_type, const _OtherIndexType&> &&332             (_Size == __rank_ || _Size == __rank_dynamic_))333  explicit(_Size != __rank_dynamic_)334      _LIBCPP_HIDE_FROM_ABI constexpr extents(const array<_OtherIndexType, _Size>& __exts) noexcept335      : __vals_(span(__exts)) {336    // Not catching this could lead to out of bounds errors later337    // e.g. mdspan m(ptr, dextents<char, 1>(array<unsigned,1>(200))); leads to an extent of -56 on m338    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__are_representable_as<index_type>(span(__exts)),339                                        "extents ctor: arguments must be representable as index_type and nonnegative");340  }341 342  template <class _OtherIndexType, size_t _Size>343    requires(is_convertible_v<const _OtherIndexType&, index_type> &&344             is_nothrow_constructible_v<index_type, const _OtherIndexType&> &&345             (_Size == __rank_ || _Size == __rank_dynamic_))346  explicit(_Size != __rank_dynamic_)347      _LIBCPP_HIDE_FROM_ABI constexpr extents(const span<_OtherIndexType, _Size>& __exts) noexcept348      : __vals_(__exts) {349    // Not catching this could lead to out of bounds errors later350    // e.g. array a{200u}; mdspan<int, dextents<char,1>> m(ptr, extents(span<unsigned,1>(a))); leads to an extent of -56351    // on m352    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__are_representable_as<index_type>(__exts),353                                        "extents ctor: arguments must be representable as index_type and nonnegative");354  }355 356private:357  // Function to construct extents storage from other extents.358  template <size_t _DynCount, size_t _Idx, class _OtherExtents, class... _DynamicValues>359    requires(_Idx < __rank_)360  _LIBCPP_HIDE_FROM_ABI constexpr _Values __construct_vals_from_extents(361      integral_constant<size_t, _DynCount>,362      integral_constant<size_t, _Idx>,363      const _OtherExtents& __exts,364      _DynamicValues... __dynamic_values) noexcept {365    if constexpr (static_extent(_Idx) == dynamic_extent)366      return __construct_vals_from_extents(367          integral_constant<size_t, _DynCount + 1>(),368          integral_constant<size_t, _Idx + 1>(),369          __exts,370          __dynamic_values...,371          __exts.extent(_Idx));372    else373      return __construct_vals_from_extents(374          integral_constant<size_t, _DynCount>(), integral_constant<size_t, _Idx + 1>(), __exts, __dynamic_values...);375  }376 377  template <size_t _DynCount, size_t _Idx, class _OtherExtents, class... _DynamicValues>378    requires((_Idx == __rank_) && (_DynCount == __rank_dynamic_))379  _LIBCPP_HIDE_FROM_ABI constexpr _Values __construct_vals_from_extents(380      integral_constant<size_t, _DynCount>,381      integral_constant<size_t, _Idx>,382      const _OtherExtents&,383      _DynamicValues... __dynamic_values) noexcept {384    return _Values{static_cast<index_type>(__dynamic_values)...};385  }386 387public:388  // Converting constructor from other extents specializations389  template <class _OtherIndexType, size_t... _OtherExtents>390    requires((sizeof...(_OtherExtents) == sizeof...(_Extents)) &&391             ((_OtherExtents == dynamic_extent || _Extents == dynamic_extent || _OtherExtents == _Extents) && ...))392  explicit((((_Extents != dynamic_extent) && (_OtherExtents == dynamic_extent)) || ...) ||393           (static_cast<make_unsigned_t<index_type>>(numeric_limits<index_type>::max()) <394            static_cast<make_unsigned_t<_OtherIndexType>>(numeric_limits<_OtherIndexType>::max())))395      _LIBCPP_HIDE_FROM_ABI constexpr extents(const extents<_OtherIndexType, _OtherExtents...>& __other) noexcept396      : __vals_(397            __construct_vals_from_extents(integral_constant<size_t, 0>(), integral_constant<size_t, 0>(), __other)) {398    if constexpr (rank() > 0) {399      for (size_t __r = 0; __r < rank(); __r++) {400        if constexpr (static_cast<make_unsigned_t<index_type>>(numeric_limits<index_type>::max()) <401                      static_cast<make_unsigned_t<_OtherIndexType>>(numeric_limits<_OtherIndexType>::max())) {402          // Not catching this could lead to out of bounds errors later403          // e.g. dextents<char,1>> e(dextents<unsigned,1>(200)) leads to an extent of -56 on e404          _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(405              __mdspan_detail::__is_representable_as<index_type>(__other.extent(__r)),406              "extents ctor: arguments must be representable as index_type and nonnegative");407        }408        // Not catching this could lead to out of bounds errors later409        // e.g. mdspan<int, extents<int, 10>> m = mdspan<int, dextents<int, 1>>(new int[5], 5);410        // Right-hand-side construction was ok, but m now thinks its range is 10 not 5411        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(412            (_Values::__static_value(__r) == dynamic_extent) ||413                (static_cast<index_type>(__other.extent(__r)) == static_cast<index_type>(_Values::__static_value(__r))),414            "extents construction: mismatch of provided arguments with static extents.");415      }416    }417  }418 419  // Comparison operator420  template <class _OtherIndexType, size_t... _OtherExtents>421  _LIBCPP_HIDE_FROM_ABI friend constexpr bool422  operator==(const extents& __lhs, const extents<_OtherIndexType, _OtherExtents...>& __rhs) noexcept {423    if constexpr (rank() != sizeof...(_OtherExtents)) {424      return false;425    } else {426      for (rank_type __r = 0; __r < __rank_; __r++) {427        // avoid warning when comparing signed and unsigner integers and pick the wider of two types428        using _CommonType = common_type_t<index_type, _OtherIndexType>;429        if (static_cast<_CommonType>(__lhs.extent(__r)) != static_cast<_CommonType>(__rhs.extent(__r))) {430          return false;431        }432      }433    }434    return true;435  }436};437 438// Recursive helper classes to implement dextents alias for extents439namespace __mdspan_detail {440 441template <class _IndexType, size_t _Rank, class _Extents = extents<_IndexType>>442struct __make_dextents;443 444template <class _IndexType, size_t _Rank, size_t... _ExtentsPack>445struct __make_dextents< _IndexType, _Rank, extents<_IndexType, _ExtentsPack...>> {446  using type _LIBCPP_NODEBUG =447      typename __make_dextents< _IndexType, _Rank - 1, extents<_IndexType, dynamic_extent, _ExtentsPack...>>::type;448};449 450template <class _IndexType, size_t... _ExtentsPack>451struct __make_dextents< _IndexType, 0, extents<_IndexType, _ExtentsPack...>> {452  using type _LIBCPP_NODEBUG = extents<_IndexType, _ExtentsPack...>;453};454 455} // namespace __mdspan_detail456 457// [mdspan.extents.dextents], alias template458template <class _IndexType, size_t _Rank>459using dextents = typename __mdspan_detail::__make_dextents<_IndexType, _Rank>::type;460 461#  if _LIBCPP_STD_VER >= 26462// [mdspan.extents.dims], alias template `dims`463template <size_t _Rank, class _IndexType = size_t>464using dims = dextents<_IndexType, _Rank>;465#  endif466 467// Deduction guide for extents468#  if _LIBCPP_STD_VER >= 26469template <class... _IndexTypes>470  requires(is_convertible_v<_IndexTypes, size_t> && ...)471explicit extents(_IndexTypes...) -> extents<size_t, __maybe_static_ext<_IndexTypes>...>;472#  else473template <class... _IndexTypes>474  requires(is_convertible_v<_IndexTypes, size_t> && ...)475explicit extents(_IndexTypes...) -> extents<size_t, size_t(((void)sizeof(_IndexTypes), dynamic_extent))...>;476#  endif477 478namespace __mdspan_detail {479 480// Helper type traits for identifying a class as extents.481template <class _Tp>482struct __is_extents : false_type {};483 484template <class _IndexType, size_t... _ExtentsPack>485struct __is_extents<extents<_IndexType, _ExtentsPack...>> : true_type {};486 487template <class _Tp>488inline constexpr bool __is_extents_v = __is_extents<_Tp>::value;489 490// Function to check whether a set of indices are a multidimensional491// index into extents. This is a word of power in the C++ standard492// requiring that the indices are larger than 0 and smaller than493// the respective extents.494 495template <integral _IndexType, class _From>496  requires(integral<_From>)497_LIBCPP_HIDE_FROM_ABI constexpr bool __is_index_in_extent(_IndexType __extent, _From __value) {498  if constexpr (is_signed_v<_From>) {499    if (__value < 0)500      return false;501  }502  using _Tp = common_type_t<_IndexType, _From>;503  return static_cast<_Tp>(__value) < static_cast<_Tp>(__extent);504}505 506template <integral _IndexType, class _From>507  requires(!integral<_From>)508_LIBCPP_HIDE_FROM_ABI constexpr bool __is_index_in_extent(_IndexType __extent, _From __value) {509  if constexpr (is_signed_v<_IndexType>) {510    if (static_cast<_IndexType>(__value) < 0)511      return false;512  }513  return static_cast<_IndexType>(__value) < __extent;514}515 516template <size_t... _Idxs, class _Extents, class... _From>517_LIBCPP_HIDE_FROM_ABI constexpr bool518__is_multidimensional_index_in_impl(index_sequence<_Idxs...>, const _Extents& __ext, _From... __values) {519  return (__mdspan_detail::__is_index_in_extent(__ext.extent(_Idxs), __values) && ...);520}521 522template <class _Extents, class... _From>523_LIBCPP_HIDE_FROM_ABI constexpr bool __is_multidimensional_index_in(const _Extents& __ext, _From... __values) {524  return __mdspan_detail::__is_multidimensional_index_in_impl(525      make_index_sequence<_Extents::rank()>(), __ext, __values...);526}527 528} // namespace __mdspan_detail529 530#endif // _LIBCPP_STD_VER >= 23531 532_LIBCPP_END_NAMESPACE_STD533 534_LIBCPP_POP_MACROS535 536#endif // _LIBCPP___MDSPAN_EXTENTS_H537