Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/libcxx/include/__mdspan/extents.h
35262 views
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-exception
7
//
8
// Kokkos v. 4.0
9
// Copyright (2022) National Technology & Engineering
10
// 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_H
18
#define _LIBCPP___MDSPAN_EXTENTS_H
19
20
#include <__assert>
21
#include <__config>
22
#include <__type_traits/common_type.h>
23
#include <__type_traits/is_convertible.h>
24
#include <__type_traits/is_nothrow_constructible.h>
25
#include <__type_traits/is_same.h>
26
#include <__type_traits/make_unsigned.h>
27
#include <__utility/integer_sequence.h>
28
#include <__utility/unreachable.h>
29
#include <array>
30
#include <cinttypes>
31
#include <concepts>
32
#include <cstddef>
33
#include <limits>
34
#include <span>
35
36
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
37
# pragma GCC system_header
38
#endif
39
40
_LIBCPP_PUSH_MACROS
41
#include <__undef_macros>
42
43
_LIBCPP_BEGIN_NAMESPACE_STD
44
45
#if _LIBCPP_STD_VER >= 23
46
47
namespace __mdspan_detail {
48
49
// ------------------------------------------------------------------
50
// ------------ __static_array --------------------------------------
51
// ------------------------------------------------------------------
52
// array like class which provides an array of static values with get
53
template <class _Tp, _Tp... _Values>
54
struct __static_array {
55
static constexpr array<_Tp, sizeof...(_Values)> __array = {_Values...};
56
57
public:
58
_LIBCPP_HIDE_FROM_ABI static constexpr size_t __size() { return sizeof...(_Values); }
59
_LIBCPP_HIDE_FROM_ABI static constexpr _Tp __get(size_t __index) noexcept { return __array[__index]; }
60
61
template <size_t _Index>
62
_LIBCPP_HIDE_FROM_ABI static constexpr _Tp __get() {
63
return __get(_Index);
64
}
65
};
66
67
// ------------------------------------------------------------------
68
// ------------ __possibly_empty_array -----------------------------
69
// ------------------------------------------------------------------
70
71
// array like class which provides get function and operator [], and
72
// has a specialization for the size 0 case.
73
// This is needed to make the __maybe_static_array be truly empty, for
74
// all static values.
75
76
template <class _Tp, size_t _Size>
77
struct __possibly_empty_array {
78
_Tp __vals_[_Size];
79
_LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator[](size_t __index) { return __vals_[__index]; }
80
_LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator[](size_t __index) const { return __vals_[__index]; }
81
};
82
83
template <class _Tp>
84
struct __possibly_empty_array<_Tp, 0> {
85
_LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator[](size_t) { __libcpp_unreachable(); }
86
_LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator[](size_t) const { __libcpp_unreachable(); }
87
};
88
89
// ------------------------------------------------------------------
90
// ------------ static_partial_sums ---------------------------------
91
// ------------------------------------------------------------------
92
93
// Provides a compile time partial sum one can index into
94
95
template <size_t... _Values>
96
struct __static_partial_sums {
97
_LIBCPP_HIDE_FROM_ABI static constexpr array<size_t, sizeof...(_Values)> __static_partial_sums_impl() {
98
array<size_t, sizeof...(_Values)> __values{_Values...};
99
array<size_t, sizeof...(_Values)> __partial_sums{{}};
100
size_t __running_sum = 0;
101
for (int __i = 0; __i != sizeof...(_Values); ++__i) {
102
__partial_sums[__i] = __running_sum;
103
__running_sum += __values[__i];
104
}
105
return __partial_sums;
106
}
107
static constexpr array<size_t, sizeof...(_Values)> __result{__static_partial_sums_impl()};
108
109
_LIBCPP_HIDE_FROM_ABI static constexpr size_t __get(size_t __index) { return __result[__index]; }
110
};
111
112
// ------------------------------------------------------------------
113
// ------------ __maybe_static_array --------------------------------
114
// ------------------------------------------------------------------
115
116
// array like class which has a mix of static and runtime values but
117
// only stores the runtime values.
118
// The type of the static and the runtime values can be different.
119
// The position of a dynamic value is indicated through a tag value.
120
template <class _TDynamic, class _TStatic, _TStatic _DynTag, _TStatic... _Values>
121
struct __maybe_static_array {
122
static_assert(is_convertible<_TStatic, _TDynamic>::value,
123
"__maybe_static_array: _TStatic must be convertible to _TDynamic");
124
static_assert(is_convertible<_TDynamic, _TStatic>::value,
125
"__maybe_static_array: _TDynamic must be convertible to _TStatic");
126
127
private:
128
// Static values member
129
static constexpr size_t __size_ = sizeof...(_Values);
130
static constexpr size_t __size_dynamic_ = ((_Values == _DynTag) + ... + 0);
131
using _StaticValues = __static_array<_TStatic, _Values...>;
132
using _DynamicValues = __possibly_empty_array<_TDynamic, __size_dynamic_>;
133
134
// Dynamic values member
135
_LIBCPP_NO_UNIQUE_ADDRESS _DynamicValues __dyn_vals_;
136
137
// static mapping of indices to the position in the dynamic values array
138
using _DynamicIdxMap = __static_partial_sums<static_cast<size_t>(_Values == _DynTag)...>;
139
140
template <size_t... _Indices>
141
_LIBCPP_HIDE_FROM_ABI static constexpr _DynamicValues __zeros(index_sequence<_Indices...>) noexcept {
142
return _DynamicValues{((void)_Indices, 0)...};
143
}
144
145
public:
146
_LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array() noexcept
147
: __dyn_vals_{__zeros(make_index_sequence<__size_dynamic_>())} {}
148
149
// constructors from dynamic values only -- this covers the case for rank() == 0
150
template <class... _DynVals>
151
requires(sizeof...(_DynVals) == __size_dynamic_)
152
_LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array(_DynVals... __vals)
153
: __dyn_vals_{static_cast<_TDynamic>(__vals)...} {}
154
155
template <class _Tp, size_t _Size >
156
requires(_Size == __size_dynamic_)
157
_LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array([[maybe_unused]] const span<_Tp, _Size>& __vals) {
158
if constexpr (_Size > 0) {
159
for (size_t __i = 0; __i < _Size; __i++)
160
__dyn_vals_[__i] = static_cast<_TDynamic>(__vals[__i]);
161
}
162
}
163
164
// constructors from all values -- here rank will be greater than 0
165
template <class... _DynVals>
166
requires(sizeof...(_DynVals) != __size_dynamic_)
167
_LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array(_DynVals... __vals) {
168
static_assert(sizeof...(_DynVals) == __size_, "Invalid number of values.");
169
_TDynamic __values[__size_] = {static_cast<_TDynamic>(__vals)...};
170
for (size_t __i = 0; __i < __size_; __i++) {
171
_TStatic __static_val = _StaticValues::__get(__i);
172
if (__static_val == _DynTag) {
173
__dyn_vals_[_DynamicIdxMap::__get(__i)] = __values[__i];
174
} else
175
// Not catching this could lead to out of bounds errors later
176
// e.g. using my_mdspan_t = mdspan<int, extents<int, 10>>; my_mdspan_t = m(new int[5], 5);
177
// Right-hand-side construction looks ok with allocation and size matching,
178
// but since (potentially elsewhere defined) my_mdspan_t has static size m now thinks its range is 10 not 5
179
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
180
__values[__i] == static_cast<_TDynamic>(__static_val),
181
"extents construction: mismatch of provided arguments with static extents.");
182
}
183
}
184
185
template <class _Tp, size_t _Size>
186
requires(_Size != __size_dynamic_)
187
_LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array(const span<_Tp, _Size>& __vals) {
188
static_assert(_Size == __size_ || __size_ == dynamic_extent);
189
for (size_t __i = 0; __i < __size_; __i++) {
190
_TStatic __static_val = _StaticValues::__get(__i);
191
if (__static_val == _DynTag) {
192
__dyn_vals_[_DynamicIdxMap::__get(__i)] = static_cast<_TDynamic>(__vals[__i]);
193
} else
194
// Not catching this could lead to out of bounds errors later
195
// e.g. using my_mdspan_t = mdspan<int, extents<int, 10>>; my_mdspan_t = m(new int[N], span<int,1>(&N));
196
// Right-hand-side construction looks ok with allocation and size matching,
197
// but since (potentially elsewhere defined) my_mdspan_t has static size m now thinks its range is 10 not N
198
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
199
static_cast<_TDynamic>(__vals[__i]) == static_cast<_TDynamic>(__static_val),
200
"extents construction: mismatch of provided arguments with static extents.");
201
}
202
}
203
204
// access functions
205
_LIBCPP_HIDE_FROM_ABI static constexpr _TStatic __static_value(size_t __i) noexcept {
206
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < __size_, "extents access: index must be less than rank");
207
return _StaticValues::__get(__i);
208
}
209
210
_LIBCPP_HIDE_FROM_ABI constexpr _TDynamic __value(size_t __i) const {
211
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < __size_, "extents access: index must be less than rank");
212
_TStatic __static_val = _StaticValues::__get(__i);
213
return __static_val == _DynTag ? __dyn_vals_[_DynamicIdxMap::__get(__i)] : static_cast<_TDynamic>(__static_val);
214
}
215
_LIBCPP_HIDE_FROM_ABI constexpr _TDynamic operator[](size_t __i) const {
216
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < __size_, "extents access: index must be less than rank");
217
return __value(__i);
218
}
219
220
// observers
221
_LIBCPP_HIDE_FROM_ABI static constexpr size_t __size() { return __size_; }
222
_LIBCPP_HIDE_FROM_ABI static constexpr size_t __size_dynamic() { return __size_dynamic_; }
223
};
224
225
// Function to check whether a value is representable as another type
226
// value must be a positive integer otherwise returns false
227
// if _From is not an integral, we just check positivity
228
template <integral _To, class _From>
229
requires(integral<_From>)
230
_LIBCPP_HIDE_FROM_ABI constexpr bool __is_representable_as(_From __value) {
231
using _To_u = make_unsigned_t<_To>;
232
using _From_u = make_unsigned_t<_From>;
233
if constexpr (is_signed_v<_From>) {
234
if (__value < 0)
235
return false;
236
}
237
if constexpr (static_cast<_To_u>(numeric_limits<_To>::max()) >= static_cast<_From_u>(numeric_limits<_From>::max())) {
238
return true;
239
} else {
240
return static_cast<_To_u>(numeric_limits<_To>::max()) >= static_cast<_From_u>(__value);
241
}
242
}
243
244
template <integral _To, class _From>
245
requires(!integral<_From>)
246
_LIBCPP_HIDE_FROM_ABI constexpr bool __is_representable_as(_From __value) {
247
if constexpr (is_signed_v<_To>) {
248
if (static_cast<_To>(__value) < 0)
249
return false;
250
}
251
return true;
252
}
253
254
template <integral _To, class... _From>
255
_LIBCPP_HIDE_FROM_ABI constexpr bool __are_representable_as(_From... __values) {
256
return (__mdspan_detail::__is_representable_as<_To>(__values) && ... && true);
257
}
258
259
template <integral _To, class _From, size_t _Size>
260
_LIBCPP_HIDE_FROM_ABI constexpr bool __are_representable_as(span<_From, _Size> __values) {
261
for (size_t __i = 0; __i < _Size; __i++)
262
if (!__mdspan_detail::__is_representable_as<_To>(__values[__i]))
263
return false;
264
return true;
265
}
266
267
} // namespace __mdspan_detail
268
269
// ------------------------------------------------------------------
270
// ------------ extents ---------------------------------------------
271
// ------------------------------------------------------------------
272
273
// Class to describe the extents of a multi dimensional array.
274
// Used by mdspan, mdarray and layout mappings.
275
// See ISO C++ standard [mdspan.extents]
276
277
template <class _IndexType, size_t... _Extents>
278
class extents {
279
public:
280
// typedefs for integral types used
281
using index_type = _IndexType;
282
using size_type = make_unsigned_t<index_type>;
283
using rank_type = size_t;
284
285
static_assert(is_integral<index_type>::value && !is_same<index_type, bool>::value,
286
"extents::index_type must be a signed or unsigned integer type");
287
static_assert(((__mdspan_detail::__is_representable_as<index_type>(_Extents) || (_Extents == dynamic_extent)) && ...),
288
"extents ctor: arguments must be representable as index_type and nonnegative");
289
290
private:
291
static constexpr rank_type __rank_ = sizeof...(_Extents);
292
static constexpr rank_type __rank_dynamic_ = ((_Extents == dynamic_extent) + ... + 0);
293
294
// internal storage type using __maybe_static_array
295
using _Values = __mdspan_detail::__maybe_static_array<_IndexType, size_t, dynamic_extent, _Extents...>;
296
[[no_unique_address]] _Values __vals_;
297
298
public:
299
// [mdspan.extents.obs], observers of multidimensional index space
300
_LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank() noexcept { return __rank_; }
301
_LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank_dynamic() noexcept { return __rank_dynamic_; }
302
303
_LIBCPP_HIDE_FROM_ABI constexpr index_type extent(rank_type __r) const noexcept { return __vals_.__value(__r); }
304
_LIBCPP_HIDE_FROM_ABI static constexpr size_t static_extent(rank_type __r) noexcept {
305
return _Values::__static_value(__r);
306
}
307
308
// [mdspan.extents.cons], constructors
309
_LIBCPP_HIDE_FROM_ABI constexpr extents() noexcept = default;
310
311
// Construction from just dynamic or all values.
312
// Precondition check is deferred to __maybe_static_array constructor
313
template <class... _OtherIndexTypes>
314
requires((is_convertible_v<_OtherIndexTypes, index_type> && ...) &&
315
(is_nothrow_constructible_v<index_type, _OtherIndexTypes> && ...) &&
316
(sizeof...(_OtherIndexTypes) == __rank_ || sizeof...(_OtherIndexTypes) == __rank_dynamic_))
317
_LIBCPP_HIDE_FROM_ABI constexpr explicit extents(_OtherIndexTypes... __dynvals) noexcept
318
: __vals_(static_cast<index_type>(__dynvals)...) {
319
// Not catching this could lead to out of bounds errors later
320
// e.g. mdspan m(ptr, dextents<char, 1>(200u)); leads to an extent of -56 on m
321
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__are_representable_as<index_type>(__dynvals...),
322
"extents ctor: arguments must be representable as index_type and nonnegative");
323
}
324
325
template <class _OtherIndexType, size_t _Size>
326
requires(is_convertible_v<const _OtherIndexType&, index_type> &&
327
is_nothrow_constructible_v<index_type, const _OtherIndexType&> &&
328
(_Size == __rank_ || _Size == __rank_dynamic_))
329
explicit(_Size != __rank_dynamic_)
330
_LIBCPP_HIDE_FROM_ABI constexpr extents(const array<_OtherIndexType, _Size>& __exts) noexcept
331
: __vals_(span(__exts)) {
332
// Not catching this could lead to out of bounds errors later
333
// e.g. mdspan m(ptr, dextents<char, 1>(array<unsigned,1>(200))); leads to an extent of -56 on m
334
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__are_representable_as<index_type>(span(__exts)),
335
"extents ctor: arguments must be representable as index_type and nonnegative");
336
}
337
338
template <class _OtherIndexType, size_t _Size>
339
requires(is_convertible_v<const _OtherIndexType&, index_type> &&
340
is_nothrow_constructible_v<index_type, const _OtherIndexType&> &&
341
(_Size == __rank_ || _Size == __rank_dynamic_))
342
explicit(_Size != __rank_dynamic_)
343
_LIBCPP_HIDE_FROM_ABI constexpr extents(const span<_OtherIndexType, _Size>& __exts) noexcept
344
: __vals_(__exts) {
345
// Not catching this could lead to out of bounds errors later
346
// e.g. array a{200u}; mdspan<int, dextents<char,1>> m(ptr, extents(span<unsigned,1>(a))); leads to an extent of -56
347
// on m
348
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__are_representable_as<index_type>(__exts),
349
"extents ctor: arguments must be representable as index_type and nonnegative");
350
}
351
352
private:
353
// Function to construct extents storage from other extents.
354
template <size_t _DynCount, size_t _Idx, class _OtherExtents, class... _DynamicValues>
355
requires(_Idx < __rank_)
356
_LIBCPP_HIDE_FROM_ABI constexpr _Values __construct_vals_from_extents(
357
integral_constant<size_t, _DynCount>,
358
integral_constant<size_t, _Idx>,
359
const _OtherExtents& __exts,
360
_DynamicValues... __dynamic_values) noexcept {
361
if constexpr (static_extent(_Idx) == dynamic_extent)
362
return __construct_vals_from_extents(
363
integral_constant<size_t, _DynCount + 1>(),
364
integral_constant<size_t, _Idx + 1>(),
365
__exts,
366
__dynamic_values...,
367
__exts.extent(_Idx));
368
else
369
return __construct_vals_from_extents(
370
integral_constant<size_t, _DynCount>(), integral_constant<size_t, _Idx + 1>(), __exts, __dynamic_values...);
371
}
372
373
template <size_t _DynCount, size_t _Idx, class _OtherExtents, class... _DynamicValues>
374
requires((_Idx == __rank_) && (_DynCount == __rank_dynamic_))
375
_LIBCPP_HIDE_FROM_ABI constexpr _Values __construct_vals_from_extents(
376
integral_constant<size_t, _DynCount>,
377
integral_constant<size_t, _Idx>,
378
const _OtherExtents&,
379
_DynamicValues... __dynamic_values) noexcept {
380
return _Values{static_cast<index_type>(__dynamic_values)...};
381
}
382
383
public:
384
// Converting constructor from other extents specializations
385
template <class _OtherIndexType, size_t... _OtherExtents>
386
requires((sizeof...(_OtherExtents) == sizeof...(_Extents)) &&
387
((_OtherExtents == dynamic_extent || _Extents == dynamic_extent || _OtherExtents == _Extents) && ...))
388
explicit((((_Extents != dynamic_extent) && (_OtherExtents == dynamic_extent)) || ...) ||
389
(static_cast<make_unsigned_t<index_type>>(numeric_limits<index_type>::max()) <
390
static_cast<make_unsigned_t<_OtherIndexType>>(numeric_limits<_OtherIndexType>::max())))
391
_LIBCPP_HIDE_FROM_ABI constexpr extents(const extents<_OtherIndexType, _OtherExtents...>& __other) noexcept
392
: __vals_(
393
__construct_vals_from_extents(integral_constant<size_t, 0>(), integral_constant<size_t, 0>(), __other)) {
394
if constexpr (rank() > 0) {
395
for (size_t __r = 0; __r < rank(); __r++) {
396
if constexpr (static_cast<make_unsigned_t<index_type>>(numeric_limits<index_type>::max()) <
397
static_cast<make_unsigned_t<_OtherIndexType>>(numeric_limits<_OtherIndexType>::max())) {
398
// Not catching this could lead to out of bounds errors later
399
// e.g. dextents<char,1>> e(dextents<unsigned,1>(200)) leads to an extent of -56 on e
400
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
401
__mdspan_detail::__is_representable_as<index_type>(__other.extent(__r)),
402
"extents ctor: arguments must be representable as index_type and nonnegative");
403
}
404
// Not catching this could lead to out of bounds errors later
405
// e.g. mdspan<int, extents<int, 10>> m = mdspan<int, dextents<int, 1>>(new int[5], 5);
406
// Right-hand-side construction was ok, but m now thinks its range is 10 not 5
407
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
408
(_Values::__static_value(__r) == dynamic_extent) ||
409
(static_cast<index_type>(__other.extent(__r)) == static_cast<index_type>(_Values::__static_value(__r))),
410
"extents construction: mismatch of provided arguments with static extents.");
411
}
412
}
413
}
414
415
// Comparison operator
416
template <class _OtherIndexType, size_t... _OtherExtents>
417
_LIBCPP_HIDE_FROM_ABI friend constexpr bool
418
operator==(const extents& __lhs, const extents<_OtherIndexType, _OtherExtents...>& __rhs) noexcept {
419
if constexpr (rank() != sizeof...(_OtherExtents)) {
420
return false;
421
} else {
422
for (rank_type __r = 0; __r < __rank_; __r++) {
423
// avoid warning when comparing signed and unsigner integers and pick the wider of two types
424
using _CommonType = common_type_t<index_type, _OtherIndexType>;
425
if (static_cast<_CommonType>(__lhs.extent(__r)) != static_cast<_CommonType>(__rhs.extent(__r))) {
426
return false;
427
}
428
}
429
}
430
return true;
431
}
432
};
433
434
// Recursive helper classes to implement dextents alias for extents
435
namespace __mdspan_detail {
436
437
template <class _IndexType, size_t _Rank, class _Extents = extents<_IndexType>>
438
struct __make_dextents;
439
440
template <class _IndexType, size_t _Rank, size_t... _ExtentsPack>
441
struct __make_dextents< _IndexType, _Rank, extents<_IndexType, _ExtentsPack...>> {
442
using type =
443
typename __make_dextents< _IndexType, _Rank - 1, extents<_IndexType, dynamic_extent, _ExtentsPack...>>::type;
444
};
445
446
template <class _IndexType, size_t... _ExtentsPack>
447
struct __make_dextents< _IndexType, 0, extents<_IndexType, _ExtentsPack...>> {
448
using type = extents<_IndexType, _ExtentsPack...>;
449
};
450
451
} // end namespace __mdspan_detail
452
453
// [mdspan.extents.dextents], alias template
454
template <class _IndexType, size_t _Rank>
455
using dextents = typename __mdspan_detail::__make_dextents<_IndexType, _Rank>::type;
456
457
# if _LIBCPP_STD_VER >= 26
458
// [mdspan.extents.dims], alias template `dims`
459
template <size_t _Rank, class _IndexType = size_t>
460
using dims = dextents<_IndexType, _Rank>;
461
# endif
462
463
// Deduction guide for extents
464
# if _LIBCPP_STD_VER >= 26
465
template <class... _IndexTypes>
466
requires(is_convertible_v<_IndexTypes, size_t> && ...)
467
explicit extents(_IndexTypes...) -> extents<size_t, __maybe_static_ext<_IndexTypes>...>;
468
# else
469
template <class... _IndexTypes>
470
requires(is_convertible_v<_IndexTypes, size_t> && ...)
471
explicit extents(_IndexTypes...) -> extents<size_t, size_t(((void)sizeof(_IndexTypes), dynamic_extent))...>;
472
# endif
473
474
namespace __mdspan_detail {
475
476
// Helper type traits for identifying a class as extents.
477
template <class _Tp>
478
struct __is_extents : false_type {};
479
480
template <class _IndexType, size_t... _ExtentsPack>
481
struct __is_extents<extents<_IndexType, _ExtentsPack...>> : true_type {};
482
483
template <class _Tp>
484
inline constexpr bool __is_extents_v = __is_extents<_Tp>::value;
485
486
// Function to check whether a set of indices are a multidimensional
487
// index into extents. This is a word of power in the C++ standard
488
// requiring that the indices are larger than 0 and smaller than
489
// the respective extents.
490
491
template <integral _IndexType, class _From>
492
requires(integral<_From>)
493
_LIBCPP_HIDE_FROM_ABI constexpr bool __is_index_in_extent(_IndexType __extent, _From __value) {
494
if constexpr (is_signed_v<_From>) {
495
if (__value < 0)
496
return false;
497
}
498
using _Tp = common_type_t<_IndexType, _From>;
499
return static_cast<_Tp>(__value) < static_cast<_Tp>(__extent);
500
}
501
502
template <integral _IndexType, class _From>
503
requires(!integral<_From>)
504
_LIBCPP_HIDE_FROM_ABI constexpr bool __is_index_in_extent(_IndexType __extent, _From __value) {
505
if constexpr (is_signed_v<_IndexType>) {
506
if (static_cast<_IndexType>(__value) < 0)
507
return false;
508
}
509
return static_cast<_IndexType>(__value) < __extent;
510
}
511
512
template <size_t... _Idxs, class _Extents, class... _From>
513
_LIBCPP_HIDE_FROM_ABI constexpr bool
514
__is_multidimensional_index_in_impl(index_sequence<_Idxs...>, const _Extents& __ext, _From... __values) {
515
return (__mdspan_detail::__is_index_in_extent(__ext.extent(_Idxs), __values) && ...);
516
}
517
518
template <class _Extents, class... _From>
519
_LIBCPP_HIDE_FROM_ABI constexpr bool __is_multidimensional_index_in(const _Extents& __ext, _From... __values) {
520
return __mdspan_detail::__is_multidimensional_index_in_impl(
521
make_index_sequence<_Extents::rank()>(), __ext, __values...);
522
}
523
524
} // namespace __mdspan_detail
525
526
#endif // _LIBCPP_STD_VER >= 23
527
528
_LIBCPP_END_NAMESPACE_STD
529
530
_LIBCPP_POP_MACROS
531
532
#endif // _LIBCPP___MDSPAN_EXTENTS_H
533
534