29#ifndef _GLIBCXX_MDSPAN
30#define _GLIBCXX_MDSPAN 1
33#pragma GCC system_header
41#define __glibcxx_want_mdspan
42#define __glibcxx_want_aligned_accessor
43#define __glibcxx_want_submdspan
46#if __glibcxx_aligned_accessor
50#if __glibcxx_submdspan
54#if __cplusplus > 202302L
58#ifdef __glibcxx_mdspan
60namespace std _GLIBCXX_VISIBILITY(default)
62_GLIBCXX_BEGIN_NAMESPACE_VERSION
66 __all_static(std::span<const size_t> __extents)
68 for(
auto __ext : __extents)
69 if (__ext == dynamic_extent)
75 __all_dynamic(std::span<const size_t> __extents)
77 for(
auto __ext : __extents)
78 if (__ext != dynamic_extent)
83 template<
typename _IndexType,
typename _OIndexType>
85 __index_type_cast(_OIndexType&& __other)
87 if constexpr (std::is_integral_v<_OIndexType>)
89 constexpr _IndexType __index_type_max
90 = __gnu_cxx::__int_traits<_IndexType>::__max;
91 constexpr _OIndexType __oindex_type_max
92 = __gnu_cxx::__int_traits<_OIndexType>::__max;
94 if constexpr (__index_type_max < __oindex_type_max)
95 __glibcxx_assert(cmp_less_equal(__other, __index_type_max));
97 if constexpr (std::is_signed_v<_OIndexType>)
98 __glibcxx_assert(__other >= 0);
99 return static_cast<_IndexType
>(__other);
103 auto __ret =
static_cast<_IndexType
>(
std::move(__other));
104 if constexpr (std::is_signed_v<_IndexType>)
105 __glibcxx_assert(__ret >= 0);
110 template<array _Extents>
114 static constexpr size_t _S_rank = _Extents.size();
122 static constexpr size_t
123 _S_dynamic_index(
size_t __r)
noexcept
124 {
return _S_dynamic_index_data[__r]; }
126 static constexpr auto _S_dynamic_index_data = []
consteval
128 array<size_t, _S_rank+1> __ret;
130 for (
size_t __i = 0; __i < _S_rank; ++__i)
133 __dyn += (_Extents[__i] == dynamic_extent);
135 __ret[_S_rank] = __dyn;
139 static constexpr size_t _S_rank_dynamic = _S_dynamic_index(_S_rank);
143 static constexpr size_t
144 _S_dynamic_index_inv(
size_t __r)
noexcept
145 {
return _S_dynamic_index_inv_data[__r]; }
147 static constexpr auto _S_dynamic_index_inv_data = []
consteval
149 array<size_t, _S_rank_dynamic> __ret;
150 for (
size_t __i = 0, __r = 0; __i < _S_rank; ++__i)
151 if (_Extents[__i] == dynamic_extent)
156 static constexpr size_t
157 _S_static_extent(
size_t __r)
noexcept
158 {
return _Extents[__r]; }
161 template<array _Extents>
162 requires (__all_dynamic<_Extents>())
163 class _StaticExtents<_Extents>
166 static constexpr size_t _S_rank = _Extents.size();
168 static constexpr size_t
169 _S_dynamic_index(
size_t __r)
noexcept
172 static constexpr size_t _S_rank_dynamic = _S_rank;
174 static constexpr size_t
175 _S_dynamic_index_inv(
size_t __k)
noexcept
178 static constexpr size_t
179 _S_static_extent(
size_t)
noexcept
180 {
return dynamic_extent; }
183 template<
typename _IndexType, array _Extents>
184 class _ExtentsStorage :
public _StaticExtents<_Extents>
187 using _Base = _StaticExtents<_Extents>;
190 using _Base::_S_rank;
191 using _Base::_S_rank_dynamic;
192 using _Base::_S_dynamic_index;
193 using _Base::_S_dynamic_index_inv;
194 using _Base::_S_static_extent;
196 static constexpr bool
197 _S_is_dynamic(
size_t __r)
noexcept
199 if constexpr (__all_static(_Extents))
201 else if constexpr (__all_dynamic(_Extents))
204 return _Extents[__r] == dynamic_extent;
207 template<
typename _OIndexType>
208 static constexpr _IndexType
209 _S_int_cast(
const _OIndexType& __other)
noexcept
210 {
return _IndexType(__other); }
213 _M_extent(
size_t __r)
const noexcept
215 if (_S_is_dynamic(__r))
216 return _M_dyn_exts[_S_dynamic_index(__r)];
218 return _S_static_extent(__r);
221 template<
size_t _OtherRank,
typename _GetOtherExtent>
222 static constexpr bool
223 _S_is_compatible_extents(_GetOtherExtent __get_extent)
noexcept
225 if constexpr (_OtherRank == _S_rank)
226 for (
size_t __i = 0; __i < _S_rank; ++__i)
227 if (!_S_is_dynamic(__i)
228 && !cmp_equal(_Extents[__i], _S_int_cast(__get_extent(__i))))
233 template<
size_t _OtherRank,
typename _GetOtherExtent>
235 _M_init_dynamic_extents(_GetOtherExtent __get_extent)
noexcept
237 __glibcxx_assert(_S_is_compatible_extents<_OtherRank>(__get_extent));
238 for (
size_t __i = 0; __i < _S_rank_dynamic; ++__i)
241 if constexpr (_OtherRank != _S_rank_dynamic)
242 __di = _S_dynamic_index_inv(__i);
243 _M_dyn_exts[__i] = _S_int_cast(__get_extent(__di));
248 _ExtentsStorage() noexcept = default;
250 template<typename _OIndexType, array _OExtents>
252 _ExtentsStorage(const _ExtentsStorage<_OIndexType, _OExtents>&
255 _M_init_dynamic_extents<_S_rank>([&__other](
size_t __i)
256 {
return __other._M_extent(__i); });
259 template<
typename _OIndexType,
size_t _Nm>
261 _ExtentsStorage(span<const _OIndexType, _Nm> __exts)
noexcept
263 _M_init_dynamic_extents<_Nm>(
264 [&__exts](
size_t __i) ->
const _OIndexType&
265 {
return __exts[__i]; });
268 static constexpr const array<size_t, _S_rank>&
269 _S_static_extents() noexcept
272 constexpr span<const _IndexType>
273 _M_dynamic_extents(
size_t __begin,
size_t __end)
const noexcept
274 requires (_Extents.size() > 0)
276 return {_M_dyn_exts + _S_dynamic_index(__begin),
277 _S_dynamic_index(__end) - _S_dynamic_index(__begin)};
281 using _Storage = __array_traits<_IndexType, _S_rank_dynamic>::_Type;
282 [[no_unique_address]] _Storage _M_dyn_exts{};
285 template<
typename _OIndexType,
typename _SIndexType>
286 concept __valid_index_type =
287 is_convertible_v<_OIndexType, _SIndexType> &&
288 is_nothrow_constructible_v<_SIndexType, _OIndexType>;
290 template<
size_t _Extent,
typename _IndexType>
292 __valid_static_extent = _Extent == dynamic_extent
293 || _Extent <= __gnu_cxx::__int_traits<_IndexType>::__max;
295 template<
typename _Extents>
296 constexpr const array<size_t, _Extents::rank()>&
297 __static_extents() noexcept
298 {
return _Extents::_Storage::_S_static_extents(); }
300 template<
typename _Extents>
301 constexpr span<const size_t>
302 __static_extents(
size_t __begin,
size_t __end)
noexcept
304 const auto& __sta_exts = __static_extents<_Extents>();
305 return span<const size_t>(__sta_exts.data() + __begin, __end - __begin);
309 template<array _Extents>
310 constexpr auto __fwd_partial_prods = []
consteval
312 constexpr size_t __rank = _Extents.size();
313 std::array<size_t, __rank> __ret;
315 for (
size_t __r = 0; __r < __rank; ++__r)
318 if (
size_t __ext = _Extents[__r]; __ext != dynamic_extent)
325 template<array _Extents>
326 constexpr auto __rev_partial_prods = []
consteval
328 constexpr size_t __rank = _Extents.size();
329 std::array<size_t, __rank> __ret;
331 for (
size_t __r = __rank; __r > 0; --__r)
333 __ret[__r - 1] = __prod;
334 if (
size_t __ext = _Extents[__r - 1]; __ext != dynamic_extent)
340 template<
typename _Extents>
341 constexpr span<const typename _Extents::index_type>
342 __dynamic_extents(
const _Extents& __exts,
size_t __begin = 0,
343 size_t __end = _Extents::rank()) noexcept
344 {
return __exts._M_exts._M_dynamic_extents(__begin, __end); }
347#if __glibcxx_submdspan
350 explicit full_extent_t() =
default;
353 inline constexpr full_extent_t full_extent{};
355 template<
typename _OffsetType,
typename _ExtentType,
typename _Str
ideType>
358 static_assert(__is_signed_or_unsigned_integer<_OffsetType>::value
359 || __detail::__integral_constant_like<_OffsetType>);
360 static_assert(__is_signed_or_unsigned_integer<_ExtentType>::value
361 || __detail::__integral_constant_like<_ExtentType>);
362 static_assert(__is_signed_or_unsigned_integer<_StrideType>::value
363 || __detail::__integral_constant_like<_StrideType>);
365 using offset_type = _OffsetType;
366 using extent_type = _ExtentType;
367 using stride_type = _StrideType;
369 [[no_unique_address]] offset_type offset{};
370 [[no_unique_address]] extent_type extent{};
371 [[no_unique_address]] stride_type stride{};
374 template<
typename _Mapping>
375 struct submdspan_mapping_result
377 [[no_unique_address]] _Mapping mapping = _Mapping();
381 template<
typename _Tp>
382 constexpr bool __is_submdspan_mapping_result =
false;
384 template<
typename _Mapping>
385 constexpr bool __is_submdspan_mapping_result<submdspan_mapping_result<_Mapping>> =
true;
387 template<
typename _Mapping>
388 concept __submdspan_mapping_result = __is_submdspan_mapping_result<_Mapping>;
392 template<
typename _IndexType,
size_t... _Extents>
395 static_assert(__is_signed_or_unsigned_integer<_IndexType>::value,
396 "IndexType must be a signed or unsigned integer type");
398 (__mdspan::__valid_static_extent<_Extents, _IndexType> && ...),
399 "Extents must either be dynamic or representable as IndexType");
401 using _Storage = __mdspan::_ExtentsStorage<
402 _IndexType, array<size_t,
sizeof...(_Extents)>{_Extents...}>;
403 [[no_unique_address]] _Storage _M_exts;
406 using index_type = _IndexType;
407 using size_type = make_unsigned_t<index_type>;
408 using rank_type = size_t;
410 static constexpr rank_type
411 rank() noexcept {
return _Storage::_S_rank; }
413 static constexpr rank_type
414 rank_dynamic() noexcept {
return _Storage::_S_rank_dynamic; }
416 static constexpr size_t
417 static_extent(rank_type __r)
noexcept
419 __glibcxx_assert(__r < rank());
420 if constexpr (rank() == 0)
423 return _Storage::_S_static_extent(__r);
427 extent(rank_type __r)
const noexcept
429 __glibcxx_assert(__r < rank());
430 if constexpr (rank() == 0)
433 return _M_exts._M_extent(__r);
437 extents() noexcept = default;
440 static consteval
bool
441 _S_is_less_dynamic(
size_t __ext,
size_t __oext)
442 {
return (__ext != dynamic_extent) && (__oext == dynamic_extent); }
444 template<
typename _OIndexType,
size_t... _OExtents>
445 static consteval bool
448 return (_S_is_less_dynamic(_Extents, _OExtents) || ...)
449 || (__gnu_cxx::__int_traits<index_type>::__max
450 < __gnu_cxx::__int_traits<_OIndexType>::__max);
453 template<
size_t... _OExtents>
454 static consteval bool
455 _S_is_compatible_extents()
457 if constexpr (
sizeof...(_OExtents) != rank())
460 return ((_OExtents == dynamic_extent || _Extents == dynamic_extent
461 || _OExtents == _Extents) && ...);
465 template<
typename _OIndexType,
size_t... _OExtents>
466 requires (_S_is_compatible_extents<_OExtents...>())
467 constexpr explicit(_S_ctor_explicit<_OIndexType, _OExtents...>())
468 extents(
const extents<_OIndexType, _OExtents...>& __other) noexcept
469 : _M_exts(__other._M_exts)
472 template<__mdspan::__val
id_index_type<index_type>... _OIndexTypes>
473 requires (
sizeof...(_OIndexTypes) == rank()
474 ||
sizeof...(_OIndexTypes) == rank_dynamic())
475 constexpr explicit extents(_OIndexTypes... __exts) noexcept
476 : _M_exts(span<
const _IndexType,
sizeof...(_OIndexTypes)>(
477 initializer_list{
static_cast<_IndexType
>(
std::move(__exts))...}))
480 template<
typename _OIndexType,
size_t _Nm>
481 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
482 && (_Nm == rank() || _Nm == rank_dynamic())
483 constexpr explicit(_Nm != rank_dynamic())
484 extents(span<_OIndexType, _Nm> __exts) noexcept
485 : _M_exts(span<const _OIndexType, _Nm>(__exts))
488 template<
typename _OIndexType,
size_t _Nm>
489 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
490 && (_Nm == rank() || _Nm == rank_dynamic())
491 constexpr explicit(_Nm != rank_dynamic())
492 extents(
const array<_OIndexType, _Nm>& __exts) noexcept
493 : _M_exts(span<const _OIndexType, _Nm>(__exts))
496 template<
typename _OIndexType,
size_t... _OExtents>
497 friend constexpr bool
498 operator==(
const extents& __self,
499 const extents<_OIndexType, _OExtents...>& __other)
noexcept
501 if constexpr (!_S_is_compatible_extents<_OExtents...>())
505 auto __impl = [&__self, &__other]<
size_t... _Counts>(
507 {
return (cmp_equal(__self.extent(_Counts),
508 __other.extent(_Counts)) && ...); };
509 return __impl(make_index_sequence<__self.rank()>());
514 friend constexpr const array<size_t, rank()>&
515 __mdspan::__static_extents<extents>() noexcept;
517 friend constexpr span<const index_type>
518 __mdspan::__dynamic_extents<extents>(const extents&,
size_t,
size_t)
521 template<typename _OIndexType,
size_t... _OExtents>
522 friend class extents;
527 template<
typename _Tp,
size_t _Nm>
529 __contains_zero(span<_Tp, _Nm> __exts)
noexcept
531 for (
size_t __i = 0; __i < __exts.size(); ++__i)
532 if (__exts[__i] == 0)
537 template<
typename _Tp,
size_t _Nm>
539 __contains_zero(
const array<_Tp, _Nm>& __exts)
noexcept
540 {
return __contains_zero(span<const _Tp>(__exts)); }
542 template<
typename _Extents>
544 __empty(
const _Extents& __exts)
noexcept
546 if constexpr (__contains_zero(__static_extents<_Extents>()))
548 else if constexpr (_Extents::rank_dynamic() > 0)
549 return __contains_zero(__dynamic_extents(__exts));
554 template<
typename _Extents>
555 constexpr typename _Extents::index_type
556 __extents_prod(
const _Extents& __exts,
size_t __sta_prod,
size_t __begin,
557 size_t __end)
noexcept
562 size_t __ret = __sta_prod;
563 if constexpr (_Extents::rank_dynamic() > 0)
564 for (
auto __factor : __dynamic_extents(__exts, __begin, __end))
565 __ret *= size_t(__factor);
566 return static_cast<typename _Extents::index_type
>(__ret);
570 template<
typename _Extents>
571 constexpr typename _Extents::index_type
572 __fwd_prod(
const _Extents& __exts,
size_t __begin,
size_t __end)
noexcept
574 size_t __sta_prod = [__begin, __end] {
575 span<const size_t> __sta_exts
576 = __static_extents<_Extents>(__begin, __end);
578 for(
auto __ext : __sta_exts)
579 if (__ext != dynamic_extent)
583 return __extents_prod(__exts, __sta_prod, __begin, __end);
586 template<
typename _Extents>
587 constexpr typename _Extents::index_type
588 __fwd_prod(
const _Extents& __exts,
size_t __r)
noexcept
590 constexpr size_t __rank = _Extents::rank();
591 constexpr auto& __sta_exts = __static_extents<_Extents>();
592 if constexpr (__rank == 1)
594 else if constexpr (__rank == 2)
595 return __r == 0 ? 1 : __exts.extent(0);
596 else if constexpr (__all_dynamic(std::span(__sta_exts).first(__rank-1)))
597 return __extents_prod(__exts, 1, 0, __r);
600 size_t __sta_prod = __fwd_partial_prods<__sta_exts>[__r];
601 return __extents_prod(__exts, __sta_prod, 0, __r);
605 template<
typename _IndexType,
size_t _Nm>
607 __fwd_prod(span<const _IndexType, _Nm> __values)
609 _IndexType __ret = 1;
610 for(
auto __value : __values)
616 template<
typename _Extents>
617 constexpr typename _Extents::index_type
618 __rev_prod(
const _Extents& __exts,
size_t __r)
noexcept
620 constexpr size_t __rank = _Extents::rank();
621 constexpr auto& __sta_exts = __static_extents<_Extents>();
622 if constexpr (__rank == 1)
624 else if constexpr (__rank == 2)
625 return __r == 0 ? __exts.extent(1) : 1;
626 else if constexpr (__all_dynamic(std::span(__sta_exts).last(__rank-1)))
627 return __extents_prod(__exts, 1, __r + 1, __rank);
630 size_t __sta_prod = __rev_partial_prods<__sta_exts>[__r];
631 return __extents_prod(__exts, __sta_prod, __r + 1, __rank);
635 template<
typename _Extents>
636 constexpr typename _Extents::index_type
637 __size(
const _Extents& __exts)
noexcept
639 constexpr size_t __sta_prod = [] {
640 span<const size_t> __sta_exts = __static_extents<_Extents>();
642 for(
auto __ext : __sta_exts)
643 if (__ext != dynamic_extent)
647 return __extents_prod(__exts, __sta_prod, 0, _Extents::rank());
650 template<
typename _IndexType,
size_t... _Counts>
651 auto __build_dextents_type(integer_sequence<size_t, _Counts...>)
652 -> extents<_IndexType, ((void) _Counts, dynamic_extent)...>;
655 template<
typename _IndexType,
size_t _Rank>
656 using dextents =
decltype(__mdspan::__build_dextents_type<_IndexType>(
657 make_index_sequence<_Rank>()));
659#if __glibcxx_mdspan >= 202406L
660 template<
size_t _Rank,
typename _IndexType =
size_t>
661 using dims = dextents<_IndexType, _Rank>;
664 template<
typename... _Integrals>
665 requires (is_convertible_v<_Integrals, size_t> && ...)
666 explicit extents(_Integrals...) ->
667 extents<size_t, __detail::__maybe_static_ext<_Integrals>...>;
671 template<
typename _Extents>
677 template<
typename _Extents>
683 template<
typename _Extents>
687#ifdef __glibcxx_padded_layouts
688 template<
size_t _PaddingValue>
689 struct layout_left_padded
691 template<
typename _Extents>
695 template<
size_t _PaddingValue>
696 struct layout_right_padded
698 template<
typename _Extents>
705 template<
typename _Tp>
706 constexpr bool __is_extents =
false;
708 template<
typename _IndexType,
size_t... _Extents>
709 constexpr bool __is_extents<extents<_IndexType, _Extents...>> =
true;
711 template<
typename _Extents,
typename... _Indices>
712 constexpr typename _Extents::index_type
713 __linear_index_left(
const _Extents& __exts, _Indices... __indices)
716 using _IndexType =
typename _Extents::index_type;
717 _IndexType __res = 0;
718 if constexpr (
sizeof...(__indices) > 0)
720 _IndexType __mult = 1;
721 auto __update = [&, __pos = 0u](_IndexType __idx)
mutable
723 _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx, __exts.extent(__pos)));
724 __res += __idx * __mult;
725 __mult *= __exts.extent(__pos);
728 (__update(__indices), ...);
733 template<
typename _IndexType>
735 __static_quotient(std::span<const size_t> __sta_exts,
736 _IndexType __nom = __gnu_cxx::__int_traits<_IndexType>::__max)
738 for (
auto __factor : __sta_exts)
740 if (__factor != dynamic_extent)
741 __nom /= _IndexType(__factor);
748 template<
typename _Extents,
749 typename _IndexType =
typename _Extents::index_type>
750 requires __is_extents<_Extents>
752 __static_quotient(_IndexType __nom
753 = __gnu_cxx::__int_traits<_IndexType>::__max)
755 std::span<const size_t> __sta_exts = __static_extents<_Extents>();
756 return __static_quotient<_IndexType>(__sta_exts, __nom);
759 template<
typename _Extents>
761 __is_representable_extents(
const _Extents& __exts)
noexcept
763 using _IndexType = _Extents::index_type;
765 if constexpr (__contains_zero(__static_extents<_Extents>()))
769 constexpr auto __sta_quo = __static_quotient<_Extents>();
770 if constexpr (_Extents::rank_dynamic() == 0)
771 return __sta_quo != 0;
774 auto __dyn_exts = __dynamic_extents(__exts);
775 if (__contains_zero(__dyn_exts))
778 if constexpr (__sta_quo == 0)
782 auto __dyn_quo = _IndexType(__sta_quo);
783 for (
auto __factor : __dyn_exts)
785 __dyn_quo /= __factor;
795 template<
typename _Extents,
typename _IndexType>
796 concept __representable_size = _Extents::rank_dynamic() != 0
797 || __contains_zero(__static_extents<_Extents>())
798 || (__static_quotient<_Extents, _IndexType>() != 0);
800 template<
typename _Layout,
typename _Mapping>
801 concept __mapping_of =
802 is_same_v<
typename _Layout::template mapping<
803 typename _Mapping::extents_type>,
806 template<
template<
size_t>
typename _Layout,
typename _Mapping>
807 concept __padded_mapping_of = __mapping_of<
808 _Layout<_Mapping::padding_value>, _Mapping>;
810#ifdef __glibcxx_padded_layouts
811 template<
typename _Mapping>
812 constexpr bool __is_left_padded_mapping = __padded_mapping_of<
813 layout_left_padded, _Mapping>;
815 template<
typename _Mapping>
816 constexpr bool __is_right_padded_mapping = __padded_mapping_of<
817 layout_right_padded, _Mapping>;
819 template<
typename _Mapping>
820 constexpr bool __is_padded_mapping = __is_left_padded_mapping<_Mapping>
821 || __is_right_padded_mapping<_Mapping>;
824 template<
typename _PaddedMapping>
826 __get_static_stride()
827 {
return _PaddedMapping::_PaddedStorage::_S_static_stride; }
829 template<
typename _Mapping>
830 concept __standardized_mapping = __mapping_of<layout_left, _Mapping>
831 || __mapping_of<layout_right, _Mapping>
832 || __mapping_of<layout_stride, _Mapping>
833#ifdef __glibcxx_padded_layouts
834 || __is_left_padded_mapping<_Mapping>
835 || __is_right_padded_mapping<_Mapping>
840 class __internal_ctor
843 template<
typename _Mapping>
844 constexpr typename _Mapping::index_type
845 __offset(
const _Mapping& __m)
noexcept
847 using _IndexType =
typename _Mapping::index_type;
848 constexpr auto __rank = _Mapping::extents_type::rank();
850 if constexpr (__standardized_mapping<_Mapping>)
852 else if (__empty(__m.extents()))
856 auto __impl = [&__m]<
size_t... _Counts>(
index_sequence<_Counts...>)
857 {
return __m(((
void) _Counts, _IndexType(0))...); };
858 return __impl(make_index_sequence<__rank>());
862#ifdef __glibcxx_submdspan
863 template<
typename _Tp>
864 constexpr bool __is_strided_slice =
false;
866 template<
typename _OffsetType,
typename _ExtentType,
typename _Str
ideType>
867 constexpr bool __is_strided_slice<strided_slice<_OffsetType,
868 _ExtentType, _StrideType>> =
true;
870 template<
typename _IndexType,
typename _OIndexType>
872 __is_representable_integer(_OIndexType __value)
874 constexpr auto __min = __gnu_cxx::__int_traits<_IndexType>::__min;
875 constexpr auto __max = __gnu_cxx::__int_traits<_IndexType>::__max;
876 return std::cmp_less_equal(__min, __value)
877 && std::cmp_less_equal(__value, __max);
880 template<
typename _Tp>
881 constexpr bool __is_constant_wrapper =
false;
883 template<_CwFixedValue _Xv,
typename _Tp>
884 constexpr bool __is_constant_wrapper<constant_wrapper<_Xv, _Tp>>
887 template<
size_t _Index,
typename _Extents>
889 __extract_extent(
const _Extents& __exts)
891 using _IndexType =
typename _Extents::index_type;
892 return extents<_IndexType, _Extents::static_extent(_Index)>{
893 __exts.extent(_Index)};
896 template<
typename _Slice,
typename _IndexType>
897 concept __acceptable_slice_type = same_as<_Slice, full_extent_t>
898 || same_as<_Slice, _IndexType> || __is_constant_wrapper<_Slice>
899 || __is_strided_slice<_Slice>;
901 template<
typename _IndexType,
typename... _Slices>
905 return (
static_cast<size_t>(!convertible_to<_Slices, _IndexType>)
909 template<
typename _IndexType,
typename... _Slices>
913 constexpr auto __rank =
sizeof...(_Slices);
914 constexpr auto __sub_rank = __subrank<_IndexType, _Slices...>();
915 auto __map = std::array<size_t, __sub_rank>{};
916 auto __is_int_like = std::array<bool, __rank>{
917 convertible_to<_Slices, _IndexType>...};
920 for (
size_t __k = 0; __k < __rank; ++__k)
921 if (!__is_int_like[__k])
926 template<
typename _Slice>
928 __slice_begin(_Slice __slice)
930 if constexpr (same_as<_Slice, full_extent_t>)
932 else if constexpr (__is_strided_slice<_Slice>)
933 return __slice.offset;
938 template<
typename _Mapping,
typename... _Slices>
940 __suboffset(
const _Mapping& __mapping,
const _Slices&... __slices)
942 using _IndexType =
typename _Mapping::index_type;
943 auto __any_past_the_end = [&]<
size_t... _Is>(
index_sequence<_Is...>)
945 auto __is_past_the_end = [](
const auto& __slice,
const auto& __ext)
947 using _Slice = remove_cvref_t<
decltype(__slice)>;
948 if constexpr (is_convertible_v<_Slice, _IndexType>)
950 else if constexpr (same_as<_Slice, full_extent_t>
951 && __ext.static_extent(0) != 0
952 && __ext.static_extent(0) != dynamic_extent)
955 return __mdspan::__slice_begin(__slice) == __ext.extent(0);
958 const auto& __exts = __mapping.extents();
959 return ((__is_past_the_end(__slices...[_Is],
960 __mdspan::__extract_extent<_Is>(__exts))) || ...);
963 if constexpr ((same_as<_Slices, full_extent_t> && ...))
964 return __mdspan::__offset(__mapping);
967 return __mapping.required_span_size();
968 return __mapping(__mdspan::__slice_begin(__slices)...);
971 template<
typename _IndexType,
size_t _Extent,
typename _Slice>
973 __static_slice_extent()
975 if constexpr (same_as<_Slice, full_extent_t>)
977 else if constexpr (same_as<_Slice, constant_wrapper<_IndexType(0)>>)
979 else if constexpr (__is_constant_wrapper<typename _Slice::extent_type>
980 && __is_constant_wrapper<typename _Slice::stride_type>)
981 return 1 + ((
typename _Slice::extent_type{}) - 1)
982 / (
typename _Slice::stride_type{});
984 return dynamic_extent;
987 template<
size_t _K,
typename _Extents,
typename _Slice>
988 constexpr typename _Extents::index_type
989 __dynamic_slice_extent(
const _Extents& __exts, _Slice __slice)
991 if constexpr (__is_strided_slice<_Slice>)
992 return __slice.extent == 0 ? 0 : 1 + (__slice.extent - 1) / __slice.stride;
994 return __exts.extent(_K);
997 template<
typename _IndexType,
size_t... _Extents,
typename... _Slices>
998 requires (
sizeof...(_Slices) ==
sizeof...(_Extents))
1000 __subextents(
const extents<_IndexType, _Extents...>& __exts,
1001 _Slices... __slices)
1003 constexpr auto __inv_map = __mdspan::__inv_map_rank<_IndexType, _Slices...>();
1006 using _SubExts = extents<_IndexType,
1007 __mdspan::__static_slice_extent<_IndexType,
1008 _Extents...[__inv_map[_Indices]],
1009 _Slices...[__inv_map[_Indices]]>()...>;
1010 if constexpr (_SubExts::rank_dynamic() == 0)
1014 using _StaticSubExtents = __mdspan::_StaticExtents<
1015 __mdspan::__static_extents<_SubExts>()>;
1018 constexpr auto __slice_idx = [__inv_map](
size_t __i)
consteval
1020 return __inv_map[_StaticSubExtents::_S_dynamic_index_inv(__i)];
1023 return _SubExts{__mdspan::__dynamic_slice_extent<__slice_idx(_Is)>(
1024 __exts, __slices...[__slice_idx(_Is)])...};
1026 constexpr auto __dyn_subrank = _SubExts::rank_dynamic();
1034 enum class _LayoutSide
1041 template<
typename _Mapping>
1042 consteval _LayoutSide
1045 if constexpr (__is_left_padded_mapping<_Mapping>
1046 || __mapping_of<layout_left, _Mapping>)
1047 return _LayoutSide::__left;
1048 if constexpr (__is_right_padded_mapping<_Mapping>
1049 || __mapping_of<layout_right, _Mapping>)
1050 return _LayoutSide::__right;
1052 return _LayoutSide::__unknown;
1055 template<_LayoutS
ide _S
ide,
size_t _Rank>
1056 struct _StridesTrait
1058 static constexpr const _LayoutSide _S_side = _Side;
1060 static constexpr size_t
1061 _S_idx(
size_t __k)
noexcept
1063 if constexpr (_Side == _LayoutSide::__left)
1066 return _Rank - 1 - __k;
1071 template<
typename _Mapping>
1072 static constexpr typename _Mapping::index_type
1073 _S_padded_extent(
const _Mapping& __mapping,
size_t __k)
1076 return __mapping.stride(_S_idx(1));
1078 return __mapping.extents().extent(_S_idx(__k));
1081 template<
typename _IndexType,
typename... _Slices>
1082 static consteval auto
1085 static_assert(_Side != _LayoutSide::__unknown);
1088 return __mdspan::__inv_map_rank<_IndexType, _Slices...[_S_idx(_Is)]...>();
1094 template<
typename _SubExts,
typename _Mapping,
typename... _Slices>
1096 __substrides_generic(
const _Mapping& __mapping,
const _Slices&... __slices)
1098 using _IndexType =
typename _Mapping::index_type;
1099 if constexpr (_SubExts::rank() == 0)
1100 return array<_IndexType, _SubExts::rank()>{};
1103 auto __stride = [&__mapping](
size_t __k,
auto __slice) -> _IndexType
1105 if constexpr (__is_strided_slice<
decltype(__slice)>)
1106 if (__slice.stride < __slice.extent)
1107 return __mapping.stride(__k) * __slice.stride;
1108 return __mapping.stride(__k);
1113 constexpr auto __inv_map
1114 = __mdspan::__inv_map_rank<_IndexType, _Slices...>();
1115 return array<_IndexType, _SubExts::rank()>{
1116 __stride(__inv_map[_Is], __slices...[__inv_map[_Is]])...};
1122 template<
typename _SubExts,
typename _Mapping,
typename... _Slices>
1124 __substrides_standardized(
const _Mapping& __mapping,
1125 const _Slices&... __slices)
1127 using _IndexType =
typename _Mapping::index_type;
1128 using _Trait = _StridesTrait<__mapping_side<_Mapping>(),
1129 _Mapping::extents_type::rank()>;
1130 using _SubTrait = _StridesTrait<__mapping_side<_Mapping>(), _SubExts::rank()>;
1132 constexpr size_t __sub_rank = _SubExts::rank();
1134 std::array<_IndexType, __sub_rank> __ret;
1135 if constexpr (__sub_rank > 0)
1137 constexpr auto __inv_map
1138 = _Trait::template _S_inv_map<_IndexType, _Slices...>();
1142 size_t __stride = 1;
1143 auto __body = [&](
size_t __k,
auto __slice)
1145 for (
size_t __i = __i0; __i < __inv_map[__k]; ++__i)
1146 __stride *= _Trait::_S_padded_extent(__mapping, __i);
1148 size_t __krev = _SubTrait::_S_idx(__k);
1149 if constexpr (__is_strided_slice<
decltype(__slice)>)
1151 if (__slice.stride < __slice.extent)
1152 __ret[__krev] = __stride * __slice.stride;
1154 __ret[__krev] = __stride;
1157 __ret[__krev] = __stride;
1159 __i0 = __inv_map[__k];
1162 ((__body(_Ks, __slices...[_Trait::_S_idx(__inv_map[_Ks])])),...);
1170 template<
typename _SubExts,
typename _Mapping,
typename... _Slices>
1172 __substrides(
const _Mapping& __mapping,
const _Slices&... __slices)
1174 if constexpr (__mdspan::__mapping_side<_Mapping>() == _LayoutSide::__unknown)
1175 return __mdspan::__substrides_generic<_SubExts>(__mapping, __slices...);
1177 return __mdspan::__substrides_standardized<_SubExts>(__mapping, __slices...);
1180 template<
typename _Slice>
1181 concept __is_unit_stride_slice = (__mdspan::__is_strided_slice<_Slice>
1182 && __mdspan::__is_constant_wrapper<typename _Slice::stride_type>
1183 && _Slice::stride_type::value == 1)
1184 || std::same_as<_Slice, full_extent_t>;
1190 enum class _SliceKind
1193 __unit_strided_slice,
1198 template<
typename _Slice>
1199 consteval _SliceKind
1202 if constexpr (std::same_as<_Slice, full_extent_t>)
1203 return _SliceKind::__full;
1204 else if constexpr (__mdspan::__is_strided_slice<_Slice>)
1206 if constexpr (__mdspan::__is_unit_stride_slice<_Slice>)
1207 return _SliceKind::__unit_strided_slice;
1209 return _SliceKind::__strided_slice;
1212 return _SliceKind::__collapsing;
1215 template<
typename... _Slices>
1216 consteval array<_SliceKind,
sizeof...(_Slices)>
1217 __make_slice_kind_array()
1219 return array<_SliceKind,
sizeof...(_Slices)>{
1220 __mdspan::__make_slice_kind<_Slices>()...};
1226 __is_block(span<const _SliceKind> __slice_kinds,
size_t __block_size)
1228 if (__block_size == 0)
1231 if (__block_size > __slice_kinds.size())
1234 for (
size_t __i = 0; __i < __block_size - 1; ++__i)
1235 if (__slice_kinds[__i] != _SliceKind::__full)
1238 auto __last = __slice_kinds[__block_size - 1];
1239 return __last == _SliceKind::__full
1240 || __last == _SliceKind::__unit_strided_slice;
1245 static consteval size_t
1246 __padded_block_begin_generic(span<const _SliceKind> __slice_kinds,
1249 if (__slice_kinds[0] != _SliceKind::__full
1250 && __slice_kinds[0] != _SliceKind::__unit_strided_slice)
1251 return dynamic_extent;
1252 else if (__slice_kinds.size() == 1)
1253 return dynamic_extent;
1257 while(__u < __slice_kinds.size()
1258 && __slice_kinds[__u] == _SliceKind::__collapsing)
1261 if (__mdspan::__is_block(__slice_kinds.subspan(__u), __sub_rank -1))
1263 return dynamic_extent;
1267 template<_LayoutS
ide _S
ide,
size_t _Nm>
1268 static consteval size_t
1269 __padded_block_begin(span<const _SliceKind, _Nm> __slice_kinds,
size_t __sub_rank)
1271 if constexpr (_Side == _LayoutSide::__left)
1272 return __mdspan::__padded_block_begin_generic(__slice_kinds, __sub_rank);
1275 std::array<_SliceKind, _Nm> __rev_slices;
1276 for(
size_t __i = 0; __i < _Nm; ++__i)
1277 __rev_slices[__i] = __slice_kinds[_Nm - 1 - __i];
1278 auto __rev_slice_kinds = span<const _SliceKind>(__rev_slices);
1280 auto __u = __mdspan::__padded_block_begin_generic(__rev_slice_kinds,
1282 return __u == dynamic_extent ? dynamic_extent : _Nm - 1 - __u;
1286 template<_LayoutS
ide _S
ide,
bool _Padded>
1287 struct _SubMdspanMapping;
1290 struct _SubMdspanMapping<_LayoutSide::__left, false>
1292 using _Layout = layout_left;
1293 template<
size_t _Pad>
using _PaddedLayout = layout_left_padded<_Pad>;
1295 template<
typename _Mapping,
size_t _Us>
1296 static consteval size_t
1299 using _Extents =
typename _Mapping::extents_type;
1300 constexpr auto __sta_exts = __mdspan::__static_extents<_Extents>(0, _Us);
1301 if constexpr (!__mdspan::__all_static(__sta_exts))
1302 return dynamic_extent;
1304 return __mdspan::__fwd_prod(__sta_exts);
1307 template<
size_t _Nm>
1308 static consteval bool
1309 _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
size_t __sub_rank)
1310 {
return __mdspan::__is_block(__slice_kinds, __sub_rank); }
1314 struct _SubMdspanMapping<_LayoutSide::__left, true>
1316 using _Layout = layout_left;
1317 template<
size_t _Pad>
using _PaddedLayout = layout_left_padded<_Pad>;
1319 template<
typename _Mapping,
size_t _Us>
1320 static consteval size_t
1323 using _Extents =
typename _Mapping::extents_type;
1324 constexpr auto __sta_exts
1325 = __mdspan::__static_extents<_Extents>(1, _Us);
1326 constexpr auto __sta_padstride
1327 = __mdspan::__get_static_stride<_Mapping>();
1328 if constexpr (__sta_padstride == dynamic_extent
1329 || !__mdspan::__all_static(__sta_exts))
1330 return dynamic_extent;
1332 return __sta_padstride * __mdspan::__fwd_prod(__sta_exts);
1335 template<
size_t _Nm>
1336 static consteval bool
1337 _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
1340 if (__sub_rank == 1)
1341 return __slice_kinds[0] == _SliceKind::__unit_strided_slice
1342 || __slice_kinds[0] == _SliceKind::__full;
1349 struct _SubMdspanMapping<_LayoutSide::__right, false>
1351 using _Layout = layout_right;
1352 template<
size_t _Pad>
using _PaddedLayout = layout_right_padded<_Pad>;
1354 template<
typename _Mapping,
size_t _Us>
1355 static consteval size_t
1358 using _Extents =
typename _Mapping::extents_type;
1359 constexpr auto __rank = _Extents::rank();
1360 constexpr auto __sta_exts
1361 = __mdspan::__static_extents<_Extents>(_Us + 1, __rank);
1362 if constexpr (!__mdspan::__all_static(__sta_exts))
1363 return dynamic_extent;
1365 return __fwd_prod(__sta_exts);
1368 template<
size_t _Nm>
1369 static consteval bool
1370 _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
1373 auto __rev_slice_kinds = array<_SliceKind, _Nm>{};
1374 for(
size_t __i = 0; __i < _Nm; ++__i)
1375 __rev_slice_kinds[__i] = __slice_kinds[_Nm - 1 - __i];
1376 return __mdspan::__is_block(span(__rev_slice_kinds), __sub_rank);
1381 struct _SubMdspanMapping<_LayoutSide::__right, true>
1383 using _Layout = layout_right;
1384 template<
size_t _Pad>
using _PaddedLayout = layout_right_padded<_Pad>;
1386 template<
typename _Mapping,
size_t _Us>
1387 static consteval size_t
1390 using _Extents =
typename _Mapping::extents_type;
1391 constexpr auto __rank = _Extents::rank();
1392 constexpr auto __sta_exts
1393 = __mdspan::__static_extents<_Extents>(_Us + 1, __rank - 1);
1394 constexpr auto __sta_padstride
1395 = __mdspan::__get_static_stride<_Mapping>();
1396 if constexpr (__sta_padstride == dynamic_extent
1397 || !__mdspan::__all_static(__sta_exts))
1398 return dynamic_extent;
1400 return __sta_padstride * __mdspan::__fwd_prod(__sta_exts);
1403 template<
size_t _Nm>
1404 static consteval bool
1405 _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
1408 if (__sub_rank == 1)
1409 return __slice_kinds[_Nm - 1] == _SliceKind::__unit_strided_slice
1410 || __slice_kinds[_Nm - 1] == _SliceKind::__full;
1417 template<
typename _Mapping>
1419 __submdspan_mapping_impl(
const _Mapping& __mapping)
1420 {
return submdspan_mapping_result{__mapping, 0}; }
1422 template<
typename _Mapping,
typename... _Slices>
1423 requires (
sizeof...(_Slices) > 0)
1425 __submdspan_mapping_impl(
const _Mapping& __mapping, _Slices... __slices)
1427 using _IndexType =
typename _Mapping::index_type;
1428 static_assert((__acceptable_slice_type<_Slices, _IndexType> && ...));
1430 constexpr auto __side = __mdspan::__mapping_side<_Mapping>();
1431 constexpr auto __rank =
sizeof...(_Slices);
1432 using _Trait = _SubMdspanMapping<__side, __is_padded_mapping<_Mapping>>;
1433 using _SliceView = span<const _SliceKind, __rank>;
1435 constexpr auto __slice_kinds = __mdspan::__make_slice_kind_array<_Slices...>();
1436 auto __offset = __mdspan::__suboffset(__mapping, __slices...);
1437 auto __sub_exts = __mdspan::__subextents(__mapping.extents(), __slices...);
1438 using _SubExts =
decltype(__sub_exts);
1439 constexpr auto __sub_rank = _SubExts::rank();
1440 if constexpr (__sub_rank == 0)
1441 return submdspan_mapping_result{
1442 typename _Trait::_Layout::mapping(__sub_exts), __offset};
1443 else if constexpr (_Trait::_S_is_unpadded_submdspan(
1444 _SliceView(__slice_kinds), __sub_rank))
1445 return submdspan_mapping_result{
1446 typename _Trait::_Layout::mapping(__sub_exts), __offset};
1448 constexpr auto __u = __padded_block_begin<__side>(
1449 _SliceView(__slice_kinds), __sub_rank);
1450 __u != dynamic_extent)
1452 constexpr auto __pad = _Trait::template _S_pad<_Mapping, __u>();
1453 using _Layout =
typename _Trait::template _PaddedLayout<__pad>;
1454 return submdspan_mapping_result{
1455 typename _Layout::mapping(__sub_exts, __mapping.stride(__u)),
1461 = __mdspan::__substrides<_SubExts>(__mapping, __slices...);
1462 return submdspan_mapping_result{
1463 layout_stride::mapping(__sub_exts, __sub_strides), __offset};
1469 template<
typename _Extents>
1470 class layout_left::mapping
1473 using extents_type = _Extents;
1474 using index_type =
typename extents_type::index_type;
1475 using size_type =
typename extents_type::size_type;
1476 using rank_type =
typename extents_type::rank_type;
1477 using layout_type = layout_left;
1479 static_assert(__mdspan::__representable_size<extents_type, index_type>,
1480 "The size of extents_type must be representable as index_type");
1483 mapping() noexcept = default;
1486 mapping(const mapping&) noexcept = default;
1489 mapping(const extents_type& __extents) noexcept
1490 : _M_extents(__extents)
1491 { __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); }
1493 template<
typename _OExtents>
1494 requires is_constructible_v<extents_type, _OExtents>
1495 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
1496 mapping(
const mapping<_OExtents>& __other) noexcept
1497 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1500 template<
typename _OExtents>
1501 requires (extents_type::rank() <= 1)
1502 && is_constructible_v<extents_type, _OExtents>
1503 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
1504 mapping(
const layout_right::mapping<_OExtents>& __other) noexcept
1505 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1509 template<
typename _OExtents>
1510 requires is_constructible_v<extents_type, _OExtents>
1511 constexpr explicit(!(extents_type::rank() == 0
1512 && is_convertible_v<_OExtents, extents_type>))
1513 mapping(
const layout_stride::mapping<_OExtents>& __other) noexcept
1514 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1515 { __glibcxx_assert(*
this == __other); }
1517#if __glibcxx_padded_layouts
1518 template<
typename _LeftpadMapping>
1519 requires __mdspan::__is_left_padded_mapping<_LeftpadMapping>
1520 && is_constructible_v<extents_type,
1521 typename _LeftpadMapping::extents_type>
1523 explicit(!is_convertible_v<
typename _LeftpadMapping::extents_type,
1525 mapping(
const _LeftpadMapping& __other) noexcept
1526 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1528 constexpr size_t __ostride_sta
1529 = __mdspan::__get_static_stride<_LeftpadMapping>();
1531 if constexpr (extents_type::rank() > 1)
1533 if constexpr (extents_type::static_extent(0) != dynamic_extent
1534 && __ostride_sta != dynamic_extent)
1535 static_assert(extents_type::static_extent(0) == __ostride_sta);
1537 __glibcxx_assert(__other.stride(1)
1538 == __other.extents().extent(0));
1544 operator=(
const mapping&)
noexcept =
default;
1546 constexpr const extents_type&
1547 extents() const noexcept {
return _M_extents; }
1549 constexpr index_type
1550 required_span_size() const noexcept
1551 {
return __mdspan::__size(_M_extents); }
1555 template<__mdspan::__val
id_index_type<index_type>... _Indices>
1556 requires (
sizeof...(_Indices) == extents_type::rank())
1557 constexpr index_type
1558 operator()(_Indices... __indices)
const noexcept
1560 return __mdspan::__linear_index_left(_M_extents,
1561 static_cast<index_type
>(
std::move(__indices))...);
1564 static constexpr bool
1565 is_always_unique() noexcept {
return true; }
1567 static constexpr bool
1568 is_always_exhaustive() noexcept {
return true; }
1570 static constexpr bool
1571 is_always_strided() noexcept {
return true; }
1573 static constexpr bool
1574 is_unique() noexcept {
return true; }
1576 static constexpr bool
1577 is_exhaustive() noexcept {
return true; }
1579 static constexpr bool
1580 is_strided() noexcept {
return true; }
1582 constexpr index_type
1583 stride(rank_type __i)
const noexcept
1584 requires (extents_type::rank() > 0)
1586 __glibcxx_assert(__i < extents_type::rank());
1587 return __mdspan::__fwd_prod(_M_extents, __i);
1590 template<
typename _OExtents>
1591 requires (extents_type::rank() == _OExtents::rank())
1592 friend constexpr bool
1593 operator==(
const mapping& __self,
const mapping<_OExtents>& __other)
1595 {
return __self.extents() == __other.extents(); }
1598 template<
typename _OExtents>
1600 mapping(
const _OExtents& __oexts, __mdspan::__internal_ctor) noexcept
1601 : _M_extents(__oexts)
1603 static_assert(__mdspan::__representable_size<_OExtents, index_type>,
1604 "The size of OtherExtents must be representable as index_type");
1605 __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents));
1608#if __glibcxx_submdspan
1609 template<
typename... _Slices>
1610 requires (extents_type::rank() ==
sizeof...(_Slices))
1611 friend constexpr auto
1612 submdspan_mapping(
const mapping& __mapping, _Slices... __slices)
1613 {
return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
1616 [[no_unique_address]] extents_type _M_extents{};
1621 template<
typename _Extents,
typename... _Indices>
1622 constexpr typename _Extents::index_type
1623 __linear_index_right(
const _Extents& __exts, _Indices... __indices)
1626 using _IndexType =
typename _Extents::index_type;
1627 array<_IndexType,
sizeof...(__indices)> __ind_arr{__indices...};
1628 _IndexType __res = 0;
1629 if constexpr (
sizeof...(__indices) > 0)
1631 _IndexType __mult = 1;
1632 auto __update = [&, __pos = __exts.rank()](_IndexType)
mutable
1635 _GLIBCXX_DEBUG_ASSERT(cmp_less(__ind_arr[__pos],
1636 __exts.extent(__pos)));
1637 __res += __ind_arr[__pos] * __mult;
1638 __mult *= __exts.extent(__pos);
1640 (__update(__indices), ...);
1646 template<
typename _Extents>
1647 class layout_right::mapping
1650 using extents_type = _Extents;
1651 using index_type =
typename extents_type::index_type;
1652 using size_type =
typename extents_type::size_type;
1653 using rank_type =
typename extents_type::rank_type;
1654 using layout_type = layout_right;
1656 static_assert(__mdspan::__representable_size<extents_type, index_type>,
1657 "The size of extents_type must be representable as index_type");
1660 mapping() noexcept = default;
1663 mapping(const mapping&) noexcept = default;
1666 mapping(const extents_type& __extents) noexcept
1667 : _M_extents(__extents)
1668 { __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); }
1670 template<
typename _OExtents>
1671 requires is_constructible_v<extents_type, _OExtents>
1672 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
1673 mapping(
const mapping<_OExtents>& __other) noexcept
1674 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1677 template<
typename _OExtents>
1678 requires (extents_type::rank() <= 1)
1679 && is_constructible_v<extents_type, _OExtents>
1680 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
1681 mapping(
const layout_left::mapping<_OExtents>& __other) noexcept
1682 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1685 template<
typename _OExtents>
1686 requires is_constructible_v<extents_type, _OExtents>
1687 constexpr explicit(!(extents_type::rank() == 0
1688 && is_convertible_v<_OExtents, extents_type>))
1689 mapping(
const layout_stride::mapping<_OExtents>& __other) noexcept
1690 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1691 { __glibcxx_assert(*
this == __other); }
1693#if __glibcxx_padded_layouts
1694 template<
typename _RightPaddedMapping>
1695 requires __mdspan::__is_right_padded_mapping<_RightPaddedMapping>
1696 && is_constructible_v<extents_type,
1697 typename _RightPaddedMapping::extents_type>
1699 explicit(!is_convertible_v<
typename _RightPaddedMapping::extents_type,
1701 mapping(
const _RightPaddedMapping& __other) noexcept
1702 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1704 constexpr size_t __rank = extents_type::rank();
1705 constexpr size_t __ostride_sta
1706 = __mdspan::__get_static_stride<_RightPaddedMapping>();
1708 if constexpr (__rank > 1)
1710 if constexpr (extents_type::static_extent(__rank - 1) != dynamic_extent
1711 && __ostride_sta != dynamic_extent)
1712 static_assert(extents_type::static_extent(__rank - 1)
1715 __glibcxx_assert(__other.stride(__rank - 2)
1716 == __other.extents().extent(__rank - 1));
1722 operator=(
const mapping&)
noexcept =
default;
1724 constexpr const extents_type&
1725 extents() const noexcept {
return _M_extents; }
1727 constexpr index_type
1728 required_span_size() const noexcept
1729 {
return __mdspan::__size(_M_extents); }
1733 template<__mdspan::__val
id_index_type<index_type>... _Indices>
1734 requires (
sizeof...(_Indices) == extents_type::rank())
1735 constexpr index_type
1736 operator()(_Indices... __indices)
const noexcept
1738 return __mdspan::__linear_index_right(
1739 _M_extents,
static_cast<index_type
>(
std::move(__indices))...);
1742 static constexpr bool
1743 is_always_unique() noexcept
1746 static constexpr bool
1747 is_always_exhaustive() noexcept
1750 static constexpr bool
1751 is_always_strided() noexcept
1754 static constexpr bool
1755 is_unique() noexcept
1758 static constexpr bool
1759 is_exhaustive() noexcept
1762 static constexpr bool
1763 is_strided() noexcept
1766 constexpr index_type
1767 stride(rank_type __i)
const noexcept
1768 requires (extents_type::rank() > 0)
1770 __glibcxx_assert(__i < extents_type::rank());
1771 return __mdspan::__rev_prod(_M_extents, __i);
1774 template<
typename _OExtents>
1775 requires (extents_type::rank() == _OExtents::rank())
1776 friend constexpr bool
1777 operator==(
const mapping& __self,
const mapping<_OExtents>& __other)
1779 {
return __self.extents() == __other.extents(); }
1782 template<
typename _OExtents>
1784 mapping(
const _OExtents& __oexts, __mdspan::__internal_ctor) noexcept
1785 : _M_extents(__oexts)
1787 static_assert(__mdspan::__representable_size<_OExtents, index_type>,
1788 "The size of OtherExtents must be representable as index_type");
1789 __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents));
1792#if __glibcxx_submdspan
1793 template<
typename... _Slices>
1794 requires (extents_type::rank() ==
sizeof...(_Slices))
1795 friend constexpr auto
1796 submdspan_mapping(
const mapping& __mapping, _Slices... __slices)
1797 {
return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
1800 [[no_unique_address]] extents_type _M_extents{};
1805 template<
typename _Mp>
1806 concept __mapping_alike =
requires
1808 requires __is_extents<typename _Mp::extents_type>;
1809 { _Mp::is_always_strided() } -> same_as<bool>;
1810 { _Mp::is_always_exhaustive() } -> same_as<bool>;
1811 { _Mp::is_always_unique() } -> same_as<bool>;
1812 bool_constant<_Mp::is_always_strided()>::value;
1813 bool_constant<_Mp::is_always_exhaustive()>::value;
1814 bool_constant<_Mp::is_always_unique()>::value;
1817 template<
typename _Mapping,
typename... _Indices>
1818 constexpr typename _Mapping::index_type
1819 __linear_index_strides(
const _Mapping& __m, _Indices... __indices)
1822 using _IndexType =
typename _Mapping::index_type;
1823 _IndexType __res = 0;
1824 if constexpr (
sizeof...(__indices) > 0)
1826 auto __update = [&, __pos = 0u](_IndexType __idx)
mutable
1828 _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx,
1829 __m.extents().extent(__pos)));
1830 __res += __idx * __m.stride(__pos++);
1832 (__update(__indices), ...);
1838 template<
typename _Extents>
1839 class layout_stride::mapping
1842 using extents_type = _Extents;
1843 using index_type =
typename extents_type::index_type;
1844 using size_type =
typename extents_type::size_type;
1845 using rank_type =
typename extents_type::rank_type;
1846 using layout_type = layout_stride;
1848 static_assert(__mdspan::__representable_size<extents_type, index_type>,
1849 "The size of extents_type must be representable as index_type");
1856 size_t __stride = 1;
1857 for (
size_t __i = extents_type::rank(); __i > 0; --__i)
1859 _M_strides[__i - 1] = index_type(__stride);
1860 __stride *= size_t(_M_extents.extent(__i - 1));
1865 mapping(
const mapping&)
noexcept =
default;
1867 template<
typename _OIndexType>
1868 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
1870 mapping(
const extents_type& __exts,
1871 span<_OIndexType, extents_type::rank()> __strides) noexcept
1872 : _M_extents(__exts)
1874 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
1875 _M_strides[__i] = index_type(as_const(__strides[__i]));
1878 template<
typename _OIndexType>
1879 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
1881 mapping(
const extents_type& __exts,
1882 const array<_OIndexType, extents_type::rank()>& __strides)
1885 span<
const _OIndexType, extents_type::rank()>(__strides))
1888 template<__mdspan::__mapping_alike _Str
idedMapping>
1889 requires (is_constructible_v<extents_type,
1890 typename _StridedMapping::extents_type>
1891 && _StridedMapping::is_always_unique()
1892 && _StridedMapping::is_always_strided())
1893 constexpr explicit(!(
1894 is_convertible_v<typename _StridedMapping::extents_type, extents_type>
1895 && __mdspan::__standardized_mapping<_StridedMapping>))
1896 mapping(
const _StridedMapping& __other) noexcept
1897 : _M_extents(__other.extents())
1899 using _OIndexType = _StridedMapping::index_type;
1900 using _OExtents = _StridedMapping::extents_type;
1902 __glibcxx_assert(__mdspan::__offset(__other) == 0);
1903 static_assert(__mdspan::__representable_size<_OExtents, index_type>,
1904 "The size of StridedMapping::extents_type must be representable as"
1906 if constexpr (cmp_greater(__gnu_cxx::__int_traits<_OIndexType>::__max,
1907 __gnu_cxx::__int_traits<index_type>::__max))
1908 __glibcxx_assert(!cmp_less(
1909 __gnu_cxx::__int_traits<index_type>::__max,
1910 __other.required_span_size())
1911 &&
"other.required_span_size() must be representable"
1913 if constexpr (extents_type::rank() > 0)
1914 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
1915 _M_strides[__i] = index_type(__other.stride(__i));
1919 operator=(
const mapping&)
noexcept =
default;
1921 constexpr const extents_type&
1922 extents() const noexcept {
return _M_extents; }
1924 constexpr array<index_type, extents_type::rank()>
1925 strides() const noexcept
1927 array<index_type, extents_type::rank()> __ret;
1928 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
1929 __ret[__i] = _M_strides[__i];
1933 constexpr index_type
1934 required_span_size() const noexcept
1936 if (__mdspan::__empty(_M_extents))
1939 index_type __ret = 1;
1940 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
1941 __ret += (_M_extents.extent(__i) - 1) * _M_strides[__i];
1947 template<__mdspan::__val
id_index_type<index_type>... _Indices>
1948 requires (
sizeof...(_Indices) == extents_type::rank())
1949 constexpr index_type
1950 operator()(_Indices... __indices)
const noexcept
1952 return __mdspan::__linear_index_strides(*
this,
1953 static_cast<index_type
>(
std::move(__indices))...);
1956 static constexpr bool
1957 is_always_unique() noexcept {
return true; }
1961 static constexpr bool
1962 is_always_exhaustive() noexcept
1964 return (_Extents::rank() == 0) || __mdspan::__contains_zero(
1965 __mdspan::__static_extents<extents_type>());
1968 static constexpr bool
1969 is_always_strided() noexcept {
return true; }
1971 static constexpr bool
1972 is_unique() noexcept {
return true; }
1977 is_exhaustive() const noexcept
1979 if constexpr (!is_always_exhaustive())
1981 auto __size = __mdspan::__size(_M_extents);
1983 return __size == required_span_size();
1988 static constexpr bool
1989 is_strided() noexcept {
return true; }
1991 constexpr index_type
1992 stride(rank_type __r)
const noexcept {
return _M_strides[__r]; }
1994 template<__mdspan::__mapping_alike _OMapping>
1995 requires ((extents_type::rank() == _OMapping::extents_type::rank())
1996 && _OMapping::is_always_strided())
1997 friend constexpr bool
1998 operator==(
const mapping& __self,
const _OMapping& __other)
noexcept
2000 if (__self.extents() != __other.extents())
2002 if constexpr (extents_type::rank() > 0)
2003 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
2004 if (!cmp_equal(__self.stride(__i), __other.stride(__i)))
2006 return __mdspan::__offset(__other) == 0;
2010#if __glibcxx_submdspan
2011 template<
typename... _Slices>
2012 requires (extents_type::rank() ==
sizeof...(_Slices))
2013 friend constexpr auto
2014 submdspan_mapping(
const mapping& __mapping, _Slices... __slices)
2016 if constexpr (
sizeof...(_Slices) == 0)
2017 return submdspan_mapping_result{__mapping, 0};
2020 auto __offset = __mdspan::__suboffset(__mapping, __slices...);
2021 auto __sub_exts = __mdspan::__subextents(__mapping.extents(), __slices...);
2023 = __mdspan::__substrides<decltype(__sub_exts)>(__mapping, __slices...);
2024 return submdspan_mapping_result{
2025 layout_stride::mapping(__sub_exts, __sub_strides), __offset};
2030 using _Strides =
typename __array_traits<index_type,
2031 extents_type::rank()>::_Type;
2032 [[no_unique_address]] extents_type _M_extents;
2033 [[no_unique_address]] _Strides _M_strides;
2036#ifdef __glibcxx_padded_layouts
2040 __least_multiple(
size_t __x,
size_t __y)
2044 return (__y / __x + (__y % __x != 0)) * __x ;
2047 template<
typename _IndexType>
2049 __is_representable_least_multiple(
size_t __x,
size_t __y)
2051 constexpr auto __y_max = __gnu_cxx::__int_traits<_IndexType>::__max;
2052 if(std::cmp_greater(__y, __y_max))
2058 auto __max_delta = __y_max -
static_cast<_IndexType
>(__y);
2059 auto __y_mod_x = __y % __x;
2060 auto __delta = (__y_mod_x == 0) ?
size_t(0) : (__x - __y_mod_x);
2061 return std::cmp_less_equal(__delta, __max_delta);
2064 template<
typename _Extents,
size_t _PaddingValue,
typename _LayoutTraits,
2065 size_t _Rank = _Extents::rank()>
2066 concept __valid_static_stride = (_Extents::rank() <= 1)
2067 || (_PaddingValue == dynamic_extent)
2068 || (_Extents::static_extent(_LayoutTraits::_S_ext_idx) == dynamic_extent)
2069 || (__is_representable_least_multiple<size_t>(
2070 _PaddingValue, _Extents::static_extent(_LayoutTraits::_S_ext_idx)));
2072 template<
size_t _PaddedStride,
typename _Extents,
2073 typename _LayoutTraits>
2075 __is_representable_padded_size()
2077 using _IndexType =
typename _Extents::index_type;
2078 auto __sta_exts = __static_extents<_Extents>(
2079 _LayoutTraits::_S_unpad_begin, _LayoutTraits::_S_unpad_end);
2080 size_t __max = __gnu_cxx::__int_traits<_IndexType>::__max;
2081 return __static_quotient(__sta_exts, __max / _PaddedStride) != 0;
2084 template<
typename _Extents,
size_t _PaddedStride,
typename _LayoutTraits,
2085 size_t _Rank = _Extents::rank()>
2086 concept __valid_padded_size = (_Rank <= 1)
2087 || (_PaddedStride == dynamic_extent)
2088 || (!__all_static(__static_extents<_Extents>()))
2089 || (__contains_zero(__static_extents<_Extents>()))
2090 || (__is_representable_padded_size<_PaddedStride, _Extents,
2093 template<
typename _Extents,
typename _Stride,
typename... _Indices>
2094 constexpr typename _Extents::index_type
2095 __linear_index_leftpad(
const _Extents& __exts, _Stride __stride,
2096 _Indices... __indices)
2099 using _IndexType =
typename _Extents::index_type;
2100 _IndexType __res = 0;
2101 if constexpr (
sizeof...(__indices) > 0)
2103 _IndexType __mult = 1;
2105 auto __update_rest = [&, __pos = 1u](_IndexType __idx)
mutable
2107 __res += __idx * __mult;
2108 __mult *= __exts.extent(__pos);
2112 auto __update = [&](_IndexType __idx,
auto... __rest)
2115 __mult = __stride.extent(0);
2116 (__update_rest(__rest), ...);
2118 __update(__indices...);
2123 template<
typename _Extents,
typename _Stride,
typename... _Indices>
2124 constexpr typename _Extents::index_type
2125 __linear_index_rightpad(
const _Extents& __exts, _Stride __stride,
2126 _Indices... __indices)
2129 using _IndexType =
typename _Extents::index_type;
2130 _IndexType __res = 0;
2131 if constexpr (
sizeof...(__indices) > 0)
2133 _IndexType __mult = 1;
2134 array<_IndexType,
sizeof...(__indices)> __ind_arr{__indices...};
2136 auto __update_rest = [&, __pos = __exts.rank()-1](_IndexType)
mutable
2139 __res += __ind_arr[__pos] * __mult;
2140 __mult *= __exts.extent(__pos);
2143 auto __update = [&](_IndexType,
auto... __rest)
2145 __res += __ind_arr[__exts.rank() - 1];
2146 __mult = __stride.extent(0);
2147 (__update_rest(__rest), ...);
2149 __update(__indices...);
2154 template<
size_t _Rank>
2155 struct _LeftPaddedLayoutTraits
2157 using _LayoutSame = layout_left;
2158 using _LayoutOther = layout_right;
2160 constexpr static const size_t _S_ext_idx = 0;
2161 constexpr static const size_t _S_stride_idx = 1;
2162 constexpr static const size_t _S_unpad_begin = 1;
2163 constexpr static const size_t _S_unpad_end = _Rank;
2165 template<
typename _IndexType,
size_t _StaticStride,
size_t..._Extents>
2166 constexpr static auto
2167 _S_make_padded_extent(
2168 extents<_IndexType, _StaticStride> __stride,
2169 const extents<_IndexType, _Extents...>& __exts)
2171 auto __impl = [&]<
size_t... _Is>(integer_sequence<size_t, _Is...>)
2173 return extents<_IndexType, _StaticStride,
2174 (_Extents...[_Is + 1])...>{
2175 __stride.extent(0), __exts.extent(_Is + 1)...};
2177 return __impl(make_index_sequence<
sizeof...(_Extents) - 1>());
2181 template<
size_t _Rank>
2182 struct _RightPaddedLayoutTraits
2184 using _LayoutSame = layout_right;
2185 using _LayoutOther = layout_left;
2187 constexpr static size_t _S_ext_idx = _Rank - 1;
2188 constexpr static size_t _S_stride_idx = _Rank - 2;
2189 constexpr static size_t _S_unpad_begin = 0;
2190 constexpr static size_t _S_unpad_end = _Rank - 1;
2192 template<
typename _IndexType,
size_t _StaticStride,
size_t..._Extents>
2193 constexpr static auto
2194 _S_make_padded_extent(
2195 extents<_IndexType, _StaticStride> __stride,
2196 const extents<_IndexType, _Extents...>& __exts)
2198 auto __impl = [&]<
size_t... _Is>(integer_sequence<size_t, _Is...>)
2200 return extents<_IndexType, (_Extents...[_Is])..., _StaticStride>{
2201 __exts.extent(_Is)..., __stride.extent(0)};
2203 return __impl(make_index_sequence<
sizeof...(_Extents) - 1>());
2207 template<
size_t _PaddingValue,
typename _Extents,
typename _LayoutTraits>
2208 class _PaddedStorage
2210 using _LayoutSame =
typename _LayoutTraits::_LayoutSame;
2213 using _IndexType =
typename _Extents::index_type;
2214 constexpr static size_t _S_rank = _Extents::rank();
2218 static_assert((_PaddingValue == dynamic_extent)
2219 || (cmp_less_equal(_PaddingValue,
2220 __gnu_cxx::__int_traits<_IndexType>::__max)),
2221 "padding_value must be representable as index_type");
2223 static_assert(__representable_size<_Extents, _IndexType>,
2224 "The size of extents_type must be representable as index_type");
2226 static_assert(__valid_static_stride<_Extents, _PaddingValue,
2228 "The padded stride must be representable as size_t");
2230 static constexpr size_t _S_static_stride = []
consteval
2232 constexpr size_t __rank = _Extents::rank();
2233 if constexpr (__rank <= 1)
2237 constexpr size_t __ext_idx = _LayoutTraits::_S_ext_idx;
2238 constexpr size_t __sta_ext = _Extents::static_extent(__ext_idx);
2239 if constexpr (__sta_ext == 0)
2241 else if constexpr (_PaddingValue == dynamic_extent
2242 || __sta_ext == dynamic_extent)
2243 return dynamic_extent;
2245 return __least_multiple(_PaddingValue, __sta_ext);
2249 static_assert(_S_static_stride == dynamic_extent
2250 || cmp_less_equal(_S_static_stride,
2251 __gnu_cxx::__int_traits<_IndexType>::__max),
2252 "Padded stride must be representable as index_type");
2254 static_assert(__valid_padded_size<_Extents, _S_static_stride,
2258 _PaddedStorage() noexcept
2260 if constexpr (_S_rank > 1)
2261 if constexpr (_S_static_stride == dynamic_extent
2262 && _S_static_padextent() != dynamic_extent)
2263 _M_stride = _Stride{_S_static_padextent()};
2267 _PaddedStorage(
const _Extents& __exts)
2268 : _M_extents(__exts)
2270 if constexpr (!__all_static(__static_extents<_Extents>()))
2271 __glibcxx_assert(__is_representable_extents(_M_extents));
2273 if constexpr (_S_rank > 1)
2275 _IndexType __stride;
2276 if constexpr (_PaddingValue == dynamic_extent)
2277 __stride = _M_padextent();
2278 else if constexpr (_S_static_padextent() != dynamic_extent)
2283 __is_representable_least_multiple<_IndexType>(
2284 _PaddingValue, _M_padextent()));
2286 __stride =
static_cast<_IndexType
>(
2287 __least_multiple(_PaddingValue, _M_padextent()));
2289 __glibcxx_assert(__is_representable_extents(
2290 _LayoutTraits::_S_make_padded_extent(
2291 std::dextents<_IndexType, 1>{__stride},
2294 _M_stride = _Stride{__stride};
2299 _PaddedStorage(
const _Extents& __exts, _IndexType __pad)
2300 : _M_extents(__exts)
2302 if constexpr (_PaddingValue != dynamic_extent)
2303 __glibcxx_assert(cmp_equal(_PaddingValue, __pad));
2304 if constexpr (_S_rank > 1 && _S_static_stride == dynamic_extent)
2307 __is_representable_least_multiple<_IndexType>(
2308 __pad, _M_padextent()));
2310 _M_stride = _Stride{
static_cast<_IndexType
>(
2311 __least_multiple(__pad, _M_padextent()))};
2313 __glibcxx_assert(__is_representable_extents(
2314 _LayoutTraits::_S_make_padded_extent(
2315 _M_stride, _M_extents)));
2319 template<
typename _OExtents>
2322 const typename _LayoutSame::template mapping<_OExtents>& __other)
2323 : _PaddedStorage(_Extents(__other.extents()))
2325 constexpr size_t __stride_idx = _LayoutTraits::_S_stride_idx;
2326 constexpr size_t __ext_idx = _LayoutTraits::_S_ext_idx;
2327 if constexpr (_S_rank > 1 && _PaddingValue != dynamic_extent)
2329 static_assert(_S_static_stride == dynamic_extent
2330 || _OExtents::static_extent(__ext_idx) == dynamic_extent
2331 || _S_static_stride == _OExtents::static_extent(__ext_idx),
2332 "The padded stride must be compatible with other");
2334 if constexpr (_S_static_stride == dynamic_extent
2335 || _OExtents::static_extent(__stride_idx) == dynamic_extent)
2336 __glibcxx_assert(std::cmp_equal(_M_padstride(),
2341 template<
typename _OExtents>
2343 _PaddedStorage(
const typename layout_stride::mapping<_OExtents>&
2345 : _M_extents(__other.extents())
2347 __glibcxx_assert(cmp_less_equal(__other.required_span_size(),
2351 constexpr size_t __stride_idx = _LayoutTraits::_S_stride_idx;
2352 if constexpr (_S_rank > 1)
2354 if constexpr (_PaddingValue != dynamic_extent)
2355 __glibcxx_assert(cmp_equal(__other.stride(__stride_idx),
2356 _M_calc_padstride())
2357 &&
"The padded stride must be compatible with other");
2358 if constexpr (_S_static_stride == dynamic_extent)
2359 _M_stride = _Stride{__other.stride(__stride_idx)};
2363 template<
typename _SamePaddedMapping>
2365 _PaddedStorage(_LayoutTraits::_LayoutSame,
2366 const _SamePaddedMapping& __other)
2367 : _M_extents(__other.extents())
2369 if constexpr (_S_rank > 1)
2371 static_assert(_PaddingValue == dynamic_extent
2372 || _SamePaddedMapping::padding_value == dynamic_extent
2373 || _PaddingValue == _SamePaddedMapping::padding_value,
2374 "If neither PaddingValue is dynamic_extent, then they must "
2377 constexpr size_t __stride_idx = _LayoutTraits::_S_stride_idx;
2378 if constexpr (_PaddingValue != dynamic_extent)
2379 __glibcxx_assert(cmp_equal(__other.stride(__stride_idx),
2380 _M_calc_padstride())
2381 &&
"The padded stride must be compatible with other");
2382 if constexpr (_S_static_stride == dynamic_extent)
2383 _M_stride = _Stride{__other.stride(__stride_idx)};
2385 __glibcxx_assert(cmp_less_equal(__other.required_span_size(),
2386 __gnu_cxx::__int_traits<_IndexType>::__max));
2389 template<
typename _OtherPaddedMapping>
2391 _PaddedStorage(_LayoutTraits::_LayoutOther,
2392 const _OtherPaddedMapping& __other) noexcept
2393 : _M_extents(__other.extents())
2395 __glibcxx_assert(cmp_less_equal(__other.required_span_size(),
2396 __gnu_cxx::__int_traits<_IndexType>::__max));
2399 static constexpr bool
2400 _M_is_always_exhaustive() noexcept
2402 if constexpr (_S_rank <= 1)
2405 return _S_static_padextent() != dynamic_extent
2406 && _S_static_stride != dynamic_extent
2407 && _S_static_padextent() == _S_static_stride;
2411 _M_is_exhaustive() const noexcept
2413 if constexpr (_M_is_always_exhaustive())
2416 return cmp_equal(_M_padextent(), _M_padstride());
2419 constexpr static size_t
2420 _S_static_padextent() noexcept
2421 {
return _Extents::static_extent(_LayoutTraits::_S_ext_idx); }
2423 constexpr _IndexType
2424 _M_padextent() const noexcept
2425 {
return _M_extents.extent(_LayoutTraits::_S_ext_idx); }
2427 constexpr _IndexType
2428 _M_calc_padstride() const noexcept
2430 if constexpr (_S_static_stride != dynamic_extent)
2431 return _S_static_stride;
2432 else if constexpr (_PaddingValue != dynamic_extent)
2433 return __least_multiple(_PaddingValue, _M_padextent());
2435 return _M_padextent();
2438 constexpr _IndexType
2439 _M_padstride() const noexcept
2440 {
return _M_stride.extent(0); }
2442 constexpr _IndexType
2443 _M_required_span_size() const noexcept
2445 if constexpr (_S_rank == 0)
2447 else if (__mdspan::__empty(_M_extents))
2451 size_t __stride =
static_cast<size_t>(_M_padstride());
2452 size_t __prod_rest = __mdspan::__fwd_prod(_M_extents,
2453 _LayoutTraits::_S_unpad_begin, _LayoutTraits::_S_unpad_end);
2454 size_t __delta = _M_padstride() - _M_padextent();
2455 return static_cast<_IndexType
>(__stride * __prod_rest - __delta);
2459 template<
typename _SamePaddedMapping>
2461 _M_equal(
const _SamePaddedMapping& __other)
const noexcept
2463 return _M_extents == __other.extents()
2465 || cmp_equal(_M_stride.extent(0),
2466 __other.stride(_LayoutTraits::_S_stride_idx)));
2469 using _Stride = std::extents<_IndexType, _S_static_stride>;
2470 [[no_unique_address]] _Stride _M_stride;
2471 [[no_unique_address]] _Extents _M_extents;
2475 template<
size_t _PaddingValue>
2476 template<
typename _Extents>
2477 class layout_left_padded<_PaddingValue>::mapping
2480 static constexpr size_t padding_value = _PaddingValue;
2482 using extents_type = _Extents;
2483 using index_type =
typename extents_type::index_type;
2484 using size_type =
typename extents_type::size_type;
2485 using rank_type =
typename extents_type::rank_type;
2486 using layout_type = layout_left_padded<padding_value>;
2489 static constexpr size_t _S_rank = extents_type::rank();
2490 using _PaddedStorage = __mdspan::_PaddedStorage<_PaddingValue,
2491 _Extents, __mdspan::_LeftPaddedLayoutTraits<_S_rank>>;
2492 [[no_unique_address]] _PaddedStorage _M_storage;
2494 consteval friend size_t
2495 __mdspan::__get_static_stride<mapping>();
2497 constexpr index_type
2498 _M_extent(
size_t __r)
const noexcept
2499 {
return _M_storage._M_extents.extent(__r); }
2501 constexpr index_type
2502 _M_padstride() const noexcept
2503 {
return _M_storage._M_stride.extent(0); }
2511 mapping(
const mapping&)
noexcept =
default;
2514 mapping(
const extents_type& __exts)
2515 : _M_storage(__exts)
2518 template<__mdspan::__val
id_index_type<index_type> _OIndexType>
2520 mapping(
const extents_type& __exts, _OIndexType __pad)
2521 : _M_storage(__exts,
2522 __mdspan::__index_type_cast<index_type>(std::move(__pad)))
2525 template<
typename _OExtents>
2526 requires is_constructible_v<extents_type, _OExtents>
2527 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
2528 mapping(
const layout_left::mapping<_OExtents>& __other)
2529 : _M_storage(__other)
2532 template<
typename _OExtents>
2533 requires is_constructible_v<_OExtents, extents_type>
2534 constexpr explicit(!(_OExtents::rank() == 0
2535 && is_convertible_v<_OExtents, extents_type>))
2536 mapping(
const typename layout_stride::mapping<_OExtents>& __other)
2537 : _M_storage(__other)
2538 { __glibcxx_assert(*
this == __other); }
2540 template<
typename _LeftPaddedMapping>
2541 requires __mdspan::__is_left_padded_mapping<_LeftPaddedMapping>
2542 && is_constructible_v<extents_type,
2543 typename _LeftPaddedMapping::extents_type>
2545 !is_convertible_v<
typename _LeftPaddedMapping::extents_type,
2547 || _S_rank > 1 && (padding_value != dynamic_extent
2548 || _LeftPaddedMapping::padding_value == dynamic_extent))
2549 mapping(
const _LeftPaddedMapping& __other)
2550 : _M_storage(layout_left{}, __other)
2553 template<
typename _RightPaddedMapping>
2554 requires (__mdspan::__is_right_padded_mapping<_RightPaddedMapping>
2555 || __mdspan::__mapping_of<layout_right, _RightPaddedMapping>)
2557 && is_constructible_v<extents_type,
2558 typename _RightPaddedMapping::extents_type>
2559 constexpr explicit(!is_convertible_v<
2560 typename _RightPaddedMapping::extents_type, extents_type>)
2561 mapping(
const _RightPaddedMapping& __other) noexcept
2562 : _M_storage(layout_right{}, __other)
2566 operator=(
const mapping&)
noexcept =
default;
2568 constexpr const extents_type&
2569 extents() const noexcept {
return _M_storage._M_extents; }
2571 constexpr array<index_type, _S_rank>
2572 strides() const noexcept
2574 array<index_type, _S_rank> __ret;
2575 if constexpr (_S_rank > 0)
2577 if constexpr (_S_rank > 1)
2578 __ret[1] = _M_padstride();
2579 if constexpr (_S_rank > 2)
2580 for(
size_t __i = 2; __i < _S_rank; ++__i)
2581 __ret[__i] = __ret[__i - 1] * _M_extent(__i - 1);
2585 constexpr index_type
2586 required_span_size() const noexcept
2587 {
return _M_storage._M_required_span_size(); }
2591 template<__mdspan::__val
id_index_type<index_type>... _Indices>
2592 requires (
sizeof...(_Indices) == _S_rank)
2593 constexpr index_type
2594 operator()(_Indices... __indices)
const noexcept
2596 return __mdspan::__linear_index_leftpad(
2597 extents(), _M_storage._M_stride,
2598 static_cast<index_type
>(
std::move(__indices))...);
2601 static constexpr bool
2602 is_always_exhaustive() noexcept
2603 {
return _PaddedStorage::_M_is_always_exhaustive(); }
2606 is_exhaustive() noexcept
2607 {
return _M_storage._M_is_exhaustive(); }
2609 static constexpr bool
2610 is_always_unique() noexcept {
return true; }
2612 static constexpr bool
2613 is_unique() noexcept {
return true; }
2615 static constexpr bool
2616 is_always_strided() noexcept {
return true; }
2618 static constexpr bool
2619 is_strided() noexcept {
return true; }
2621 constexpr index_type
2622 stride(rank_type __r)
const noexcept
2624 __glibcxx_assert(__r < _S_rank);
2628 return static_cast<index_type
>(
2629 static_cast<size_t>(_M_padstride()) *
2630 static_cast<size_t>(__mdspan::__fwd_prod(extents(), 1, __r)));
2633 template<
typename _LeftpadMapping>
2634 requires(__mdspan::__is_left_padded_mapping<_LeftpadMapping>
2635 && _LeftpadMapping::extents_type::rank() == _S_rank)
2636 friend constexpr bool
2637 operator==(
const mapping& __self,
const _LeftpadMapping& __other)
2639 {
return __self._M_storage._M_equal(__other); }
2642#if __glibcxx_submdspan
2643 template<
typename... _Slices>
2644 requires (extents_type::rank() ==
sizeof...(_Slices))
2645 friend constexpr auto
2646 submdspan_mapping(
const mapping& __mapping, _Slices... __slices)
2647 {
return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
2651 template<
size_t _PaddingValue>
2652 template<
typename _Extents>
2653 class layout_right_padded<_PaddingValue>::mapping {
2655 static constexpr size_t padding_value = _PaddingValue;
2656 using extents_type = _Extents;
2657 using index_type =
typename extents_type::index_type;
2658 using size_type =
typename extents_type::size_type;
2659 using rank_type =
typename extents_type::rank_type;
2660 using layout_type = layout_right_padded<_PaddingValue>;
2663 static constexpr size_t _S_rank = extents_type::rank();
2664 using _PaddedStorage = __mdspan::_PaddedStorage<_PaddingValue,
2665 _Extents, __mdspan::_RightPaddedLayoutTraits<_S_rank>>;
2666 [[no_unique_address]] _PaddedStorage _M_storage;
2668 consteval friend size_t
2669 __mdspan::__get_static_stride<mapping>();
2671 constexpr index_type
2672 _M_extent(
size_t __r)
const noexcept
2673 {
return _M_storage._M_extents.extent(__r); }
2675 constexpr index_type
2676 _M_padstride() const noexcept
2677 {
return _M_storage._M_stride.extent(0); }
2685 mapping(
const mapping&)
noexcept =
default;
2688 mapping(
const extents_type& __exts)
2689 : _M_storage(__exts)
2692 template<__mdspan::__val
id_index_type<index_type> _OIndexType>
2694 mapping(
const extents_type& __exts, _OIndexType __pad)
2695 : _M_storage(__exts,
2696 __mdspan::__index_type_cast<index_type>(std::move(__pad)))
2699 template<
typename _OExtents>
2700 requires is_constructible_v<extents_type, _OExtents>
2701 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
2702 mapping(
const layout_right::mapping<_OExtents>& __other)
2703 : _M_storage(__other)
2706 template<
typename _OExtents>
2707 requires is_constructible_v<_OExtents, extents_type>
2708 constexpr explicit(!(_OExtents::rank() == 0
2709 && is_convertible_v<_OExtents, extents_type>))
2710 mapping(
const typename layout_stride::mapping<_OExtents>& __other)
2711 : _M_storage(__other)
2712 { __glibcxx_assert(*
this == __other); }
2714 template<
typename _RightPaddedMapping>
2715 requires __mdspan::__is_right_padded_mapping<_RightPaddedMapping>
2716 && is_constructible_v<extents_type,
2717 typename _RightPaddedMapping::extents_type>
2719 !is_convertible_v<
typename _RightPaddedMapping::extents_type,
2721 || _S_rank > 1 && (padding_value != dynamic_extent
2722 || _RightPaddedMapping::padding_value == dynamic_extent))
2723 mapping(
const _RightPaddedMapping& __other)
2724 : _M_storage(layout_right{}, __other)
2727 template<
typename _LeftPaddedMapping>
2728 requires (__mdspan::__is_left_padded_mapping<_LeftPaddedMapping>
2729 || __mdspan::__mapping_of<layout_left, _LeftPaddedMapping>)
2731 && is_constructible_v<extents_type,
2732 typename _LeftPaddedMapping::extents_type>
2733 constexpr explicit(!is_convertible_v<
2734 typename _LeftPaddedMapping::extents_type, extents_type>)
2735 mapping(
const _LeftPaddedMapping& __other) noexcept
2736 : _M_storage(layout_left{}, __other)
2739 constexpr mapping& operator=(
const mapping&)
noexcept =
default;
2741 constexpr const extents_type&
2742 extents() const noexcept {
return _M_storage._M_extents; }
2744 constexpr array<index_type, _S_rank>
2745 strides() const noexcept
2747 array<index_type, _S_rank> __ret;
2748 if constexpr (_S_rank > 0)
2749 __ret[_S_rank - 1] = 1;
2750 if constexpr (_S_rank > 1)
2751 __ret[_S_rank - 2] = _M_padstride();
2752 if constexpr (_S_rank > 2)
2753 for(
size_t __i = _S_rank - 2; __i > 0; --__i)
2754 __ret[__i - 1] = __ret[__i] * _M_extent(__i);
2758 constexpr index_type
2759 required_span_size() const noexcept
2760 {
return _M_storage._M_required_span_size(); }
2764 template<__mdspan::__val
id_index_type<index_type>... _Indices>
2765 requires (
sizeof...(_Indices) == _S_rank)
2766 constexpr index_type
2767 operator()(_Indices... __indices)
const noexcept
2769 return __mdspan::__linear_index_rightpad(
2770 extents(), _M_storage._M_stride,
2771 static_cast<index_type
>(
std::move(__indices))...);
2774 static constexpr bool
2775 is_always_exhaustive() noexcept
2776 {
return _PaddedStorage::_M_is_always_exhaustive(); }
2779 is_exhaustive() noexcept
2780 {
return _M_storage._M_is_exhaustive(); }
2782 static constexpr bool
2783 is_always_unique() noexcept {
return true; }
2785 static constexpr bool
2786 is_unique() noexcept {
return true; }
2788 static constexpr bool
2789 is_always_strided() noexcept {
return true; }
2791 static constexpr bool
2792 is_strided() noexcept {
return true; }
2794 constexpr index_type
2795 stride(rank_type __r)
const noexcept
2797 __glibcxx_assert(__r < _S_rank);
2798 if constexpr (_S_rank <= 1)
2800 else if (__r == _S_rank - 1)
2802 else if (__r == _S_rank - 2)
2803 return _M_padstride();
2805 return static_cast<index_type
>(
2806 static_cast<size_t>(_M_padstride()) *
2807 static_cast<size_t>(__mdspan::__fwd_prod(
2808 extents(), __r + 1, _S_rank - 1)));
2811 template<
typename _RightPaddedMapping>
2812 requires(__mdspan::__is_right_padded_mapping<_RightPaddedMapping>
2813 && _RightPaddedMapping::extents_type::rank() == _S_rank)
2814 friend constexpr bool
2815 operator==(
const mapping& __self,
const _RightPaddedMapping& __other)
2817 {
return __self._M_storage._M_equal(__other); }
2819#if __glibcxx_submdspan
2821 template<
typename... _Slices>
2822 requires (extents_type::rank() ==
sizeof...(_Slices))
2823 friend constexpr auto
2824 submdspan_mapping(
const mapping& __mapping, _Slices... __slices)
2825 {
return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
2830 template<
typename _ElementType>
2831 struct default_accessor
2833 static_assert(!is_array_v<_ElementType>,
2834 "ElementType must not be an array type");
2835 static_assert(!is_abstract_v<_ElementType>,
2836 "ElementType must not be an abstract class type");
2838 using offset_policy = default_accessor;
2839 using element_type = _ElementType;
2840 using reference = element_type&;
2841 using data_handle_type = element_type*;
2844 default_accessor() noexcept = default;
2846 template<typename _OElementType>
2847 requires is_convertible_v<_OElementType(*)[], element_type(*)[]>
2849 default_accessor(default_accessor<_OElementType>) noexcept
2853 access(data_handle_type __p,
size_t __i)
const noexcept
2854 {
return __p[__i]; }
2856 constexpr data_handle_type
2857 offset(data_handle_type __p,
size_t __i)
const noexcept
2858 {
return __p + __i; }
2861#ifdef __glibcxx_aligned_accessor
2862 template<
typename _ElementType,
size_t _ByteAlignment>
2863 struct aligned_accessor
2865 static_assert(has_single_bit(_ByteAlignment),
2866 "ByteAlignment must be a power of two");
2867 static_assert(_ByteAlignment >=
alignof(_ElementType));
2869 using offset_policy = default_accessor<_ElementType>;
2870 using element_type = _ElementType;
2871 using reference = element_type&;
2872 using data_handle_type = element_type*;
2874 static constexpr size_t byte_alignment = _ByteAlignment;
2877 aligned_accessor() noexcept = default;
2879 template<typename _OElementType,
size_t _OByteAlignment>
2880 requires (_OByteAlignment >= byte_alignment)
2881 && is_convertible_v<_OElementType(*)[], element_type(*)[]>
2883 aligned_accessor(aligned_accessor<_OElementType, _OByteAlignment>)
2887 template<
typename _OElementType>
2888 requires is_convertible_v<_OElementType(*)[], element_type(*)[]>
2890 aligned_accessor(default_accessor<_OElementType>)
noexcept
2893 template<
typename _OElementType>
2894 requires is_convertible_v<element_type(*)[], _OElementType(*)[]>
2896 operator default_accessor<_OElementType>() const noexcept
2900 access(data_handle_type __p,
size_t __i)
const noexcept
2903 constexpr typename offset_policy::data_handle_type
2904 offset(data_handle_type __p,
size_t __i)
const noexcept
2909 template<
typename _ElementType,
typename _Extents,
2910 typename _LayoutPolicy = layout_right,
2911 typename _AccessorPolicy = default_accessor<_ElementType>>
2914 static_assert(!is_array_v<_ElementType>,
2915 "ElementType must not be an array type");
2916 static_assert(!is_abstract_v<_ElementType>,
2917 "ElementType must not be an abstract class type");
2918 static_assert(__mdspan::__is_extents<_Extents>,
2919 "Extents must be a specialization of std::extents");
2920 static_assert(is_same_v<_ElementType,
2921 typename _AccessorPolicy::element_type>);
2924 using extents_type = _Extents;
2925 using layout_type = _LayoutPolicy;
2926 using accessor_type = _AccessorPolicy;
2927 using mapping_type =
typename layout_type::template mapping<extents_type>;
2928 using element_type = _ElementType;
2929 using value_type = remove_cv_t<element_type>;
2930 using index_type =
typename extents_type::index_type;
2931 using size_type =
typename extents_type::size_type;
2932 using rank_type =
typename extents_type::rank_type;
2933 using data_handle_type =
typename accessor_type::data_handle_type;
2934 using reference =
typename accessor_type::reference;
2936 static constexpr rank_type
2937 rank() noexcept {
return extents_type::rank(); }
2939 static constexpr rank_type
2940 rank_dynamic() noexcept {
return extents_type::rank_dynamic(); }
2942 static constexpr size_t
2943 static_extent(rank_type __r)
noexcept
2944 {
return extents_type::static_extent(__r); }
2946 constexpr index_type
2947 extent(rank_type __r)
const noexcept {
return extents().extent(__r); }
2951 requires (rank_dynamic() > 0)
2952 && is_default_constructible_v<data_handle_type>
2953 && is_default_constructible_v<mapping_type>
2954 && is_default_constructible_v<accessor_type> =
default;
2957 mdspan(
const mdspan& __other) =
default;
2960 mdspan(mdspan&& __other) =
default;
2962 template<__mdspan::__val
id_index_type<index_type>... _OIndexTypes>
2963 requires (
sizeof...(_OIndexTypes) == rank()
2964 ||
sizeof...(_OIndexTypes) == rank_dynamic())
2965 && is_constructible_v<mapping_type, extents_type>
2966 && is_default_constructible_v<accessor_type>
2968 mdspan(data_handle_type __handle, _OIndexTypes... __exts)
2970 _M_mapping(_Extents(
static_cast<index_type
>(
std::move(__exts))...)),
2974 template<
typename _OIndexType,
size_t _Nm>
2975 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
2976 && (_Nm == rank() || _Nm == rank_dynamic())
2977 && is_constructible_v<mapping_type, extents_type>
2978 && is_default_constructible_v<accessor_type>
2979 constexpr explicit(_Nm != rank_dynamic())
2980 mdspan(data_handle_type __handle, span<_OIndexType, _Nm> __exts)
2981 : _M_accessor(), _M_mapping(extents_type(__exts)),
2982 _M_handle(std::move(__handle))
2985 template<
typename _OIndexType,
size_t _Nm>
2986 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
2987 && (_Nm == rank() || _Nm == rank_dynamic())
2988 && is_constructible_v<mapping_type, extents_type>
2989 && is_default_constructible_v<accessor_type>
2990 constexpr explicit(_Nm != rank_dynamic())
2991 mdspan(data_handle_type __handle,
const array<_OIndexType, _Nm>& __exts)
2992 : _M_accessor(), _M_mapping(extents_type(__exts)),
2993 _M_handle(std::move(__handle))
2997 mdspan(data_handle_type __handle,
const extents_type& __exts)
2998 requires is_constructible_v<mapping_type, const extents_type&>
2999 && is_default_constructible_v<accessor_type>
3000 : _M_accessor(), _M_mapping(__exts), _M_handle(
std::move(__handle))
3004 mdspan(data_handle_type __handle,
const mapping_type& __mapping)
3005 requires is_default_constructible_v<accessor_type>
3006 : _M_accessor(), _M_mapping(__mapping), _M_handle(
std::move(__handle))
3010 mdspan(data_handle_type __handle,
const mapping_type& __mapping,
3011 const accessor_type& __accessor)
3012 : _M_accessor(__accessor), _M_mapping(__mapping),
3013 _M_handle(std::move(__handle))
3016 template<
typename _OElementType,
typename _OExtents,
typename _OLayout,
3017 typename _OAccessor>
3018 requires is_constructible_v<mapping_type,
3019 const typename _OLayout::template mapping<_OExtents>&>
3020 && is_constructible_v<accessor_type, const _OAccessor&>
3021 constexpr explicit(!is_convertible_v<
3022 const typename _OLayout::template mapping<_OExtents>&, mapping_type>
3023 || !is_convertible_v<const _OAccessor&, accessor_type>)
3024 mdspan(
const mdspan<_OElementType, _OExtents, _OLayout, _OAccessor>&
3026 : _M_accessor(__other.accessor()), _M_mapping(__other.mapping()),
3027 _M_handle(__other.data_handle())
3029 static_assert(is_constructible_v<data_handle_type,
3030 const typename _OAccessor::data_handle_type&>);
3031 static_assert(is_constructible_v<extents_type, _OExtents>);
3035 operator=(
const mdspan& __other) =
default;
3038 operator=(mdspan&& __other) =
default;
3040 template<__mdspan::__val
id_index_type<index_type>... _OIndexTypes>
3041 requires (
sizeof...(_OIndexTypes) == rank())
3043 operator[](_OIndexTypes... __indices)
const
3045 if constexpr (rank() == 0)
3046 return _M_accessor.access(_M_handle, _M_mapping());
3047 else if constexpr (!(is_same_v<_OIndexTypes, index_type> && ...))
3049 __mdspan::__index_type_cast<index_type>(
std::move(__indices))...);
3052 auto __is_multi_index = [&]<
size_t... _Counts>(
index_sequence<_Counts...>)
3053 {
return ((__indices < extents().extent(_Counts)) && ...); };
3055 __glibcxx_assert(__is_multi_index(make_index_sequence<rank()>()));
3056 return _M_accessor.access(_M_handle, _M_mapping(__indices...));
3060 template<
typename _OIndexType>
3061 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3063 operator[](span<_OIndexType, rank()> __indices)
const
3069 __mdspan::__index_type_cast<index_type>(as_const(__indices[_Counts]))...);
3071 return __call(make_index_sequence<rank()>());
3074 template<
typename _OIndexType>
3075 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3077 operator[](
const array<_OIndexType, rank()>& __indices)
const
3078 {
return operator[](span<
const _OIndexType, rank()>(__indices)); }
3080#if __cplusplus > 202302L
3081 template<__mdspan::__val
id_index_type<index_type>... _OIndexTypes>
3082 requires (
sizeof...(_OIndexTypes) == rank())
3084 at(_OIndexTypes... __indices)
const
3086 if constexpr (rank() == 0)
3087 return _M_accessor.access(_M_handle, _M_mapping());
3088 else if constexpr (!(is_integral_v<_OIndexTypes> && ...))
3089 return at(__index_int_t<_OIndexTypes>(
std::move(__indices))...);
3092 auto __check_bound = [&]<
typename _OIntType>(
size_t __dim, _OIntType __index)
3094 if constexpr (is_signed_v<_OIntType>)
3096 std::__throw_out_of_range_fmt(
3097 __N(
"mdspan::at: %zuth index is negative"), __dim);
3099 const auto __ext = extents().extent(__dim);
3100 if (std::cmp_greater_equal(__index, __ext))
3101 std::__throw_out_of_range_fmt(
3102 __N(
"mdspan::at: %zuth index (which is %zu)"
3103 " >= extent(%zu) (which is %zu)"),
3104 __dim,
size_t(__index), __dim,
size_t(__ext));
3106 auto __check_bounds = [&]<
size_t... _Counts>(
index_sequence<_Counts...>)
3107 { (__check_bound(_Counts, __indices), ...); };
3109 __check_bounds(make_index_sequence<rank()>());
3110 auto __index = _M_mapping(
static_cast<index_type
>(__indices)...);
3111 return _M_accessor.access(_M_handle, __index);
3115 template<
typename _OIndexType>
3116 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3118 at(span<_OIndexType, rank()> __indices)
const
3124 __index_int_t<_OIndexType>(as_const(__indices[_Counts]))...);
3126 return __call(make_index_sequence<rank()>());
3129 template<
typename _OIndexType>
3130 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3132 at(
const array<_OIndexType, rank()>& __indices)
const
3133 {
return at(span<
const _OIndexType, rank()>(__indices)); }
3137 size() const noexcept
3139 __glibcxx_assert(cmp_less_equal(_M_mapping.required_span_size(),
3142 return size_type(__mdspan::__size(extents()));
3147 empty() const noexcept
3148 {
return __mdspan::__empty(extents()); }
3150 friend constexpr void
3151 swap(mdspan& __x, mdspan& __y)
noexcept
3154 swap(__x._M_mapping, __y._M_mapping);
3155 swap(__x._M_accessor, __y._M_accessor);
3156 swap(__x._M_handle, __y._M_handle);
3159 constexpr const extents_type&
3160 extents() const noexcept {
return _M_mapping.extents(); }
3162 constexpr const data_handle_type&
3163 data_handle() const noexcept {
return _M_handle; }
3165 constexpr const mapping_type&
3166 mapping() const noexcept {
return _M_mapping; }
3168 constexpr const accessor_type&
3169 accessor() const noexcept {
return _M_accessor; }
3173 static constexpr bool
3174 is_always_unique() noexcept(noexcept(mapping_type::is_always_unique()))
3175 {
return mapping_type::is_always_unique(); }
3177 static constexpr bool
3178 is_always_exhaustive()
3179 noexcept(noexcept(mapping_type::is_always_exhaustive()))
3180 {
return mapping_type::is_always_exhaustive(); }
3182 static constexpr bool
3184 noexcept(noexcept(mapping_type::is_always_strided()))
3185 {
return mapping_type::is_always_strided(); }
3188 is_unique() const noexcept(noexcept(_M_mapping.is_unique()))
3189 {
return _M_mapping.is_unique(); }
3192 is_exhaustive() const noexcept(noexcept(_M_mapping.is_exhaustive()))
3193 {
return _M_mapping.is_exhaustive(); }
3196 is_strided() const noexcept(noexcept(_M_mapping.is_strided()))
3197 {
return _M_mapping.is_strided(); }
3199 constexpr index_type
3200 stride(rank_type __r)
const {
return _M_mapping.stride(__r); }
3203 template<
typename _OIndexType>
3204 using __index_int_t = std::__conditional_t<
3205 is_integral_v<_OIndexType>, _OIndexType, index_type>;
3207 [[no_unique_address]] accessor_type _M_accessor = accessor_type();
3208 [[no_unique_address]] mapping_type _M_mapping = mapping_type();
3209 [[no_unique_address]] data_handle_type _M_handle = data_handle_type();
3212 template<
typename _CArray>
3213 requires is_array_v<_CArray> && (rank_v<_CArray> == 1)
3215 -> mdspan<remove_all_extents_t<_CArray>,
3216 extents<size_t, extent_v<_CArray, 0>>>;
3218 template<
typename _Po
inter>
3219 requires is_pointer_v<remove_reference_t<_Pointer>>
3221 -> mdspan<remove_pointer_t<remove_reference_t<_Pointer>>, extents<size_t>>;
3223 template<
typename _ElementType,
typename... _Integrals>
3224 requires (is_convertible_v<_Integrals, size_t> && ...)
3225 && (
sizeof...(_Integrals) > 0)
3226 explicit mdspan(_ElementType*, _Integrals...)
3227 -> mdspan<_ElementType,
3228 extents<size_t, __detail::__maybe_static_ext<_Integrals>...>>;
3230 template<
typename _ElementType,
typename _OIndexType,
size_t _Nm>
3231 mdspan(_ElementType*, span<_OIndexType, _Nm>)
3232 -> mdspan<_ElementType, dextents<size_t, _Nm>>;
3234 template<
typename _ElementType,
typename _OIndexType,
size_t _Nm>
3235 mdspan(_ElementType*,
const array<_OIndexType, _Nm>&)
3236 -> mdspan<_ElementType, dextents<size_t, _Nm>>;
3238 template<
typename _ElementType,
typename _IndexType,
size_t... _ExtentsPack>
3239 mdspan(_ElementType*,
const extents<_IndexType, _ExtentsPack...>&)
3240 -> mdspan<_ElementType, extents<_IndexType, _ExtentsPack...>>;
3242 template<
typename _ElementType,
typename _MappingType>
3243 mdspan(_ElementType*,
const _MappingType&)
3244 -> mdspan<_ElementType,
typename _MappingType::extents_type,
3245 typename _MappingType::layout_type>;
3247 template<
typename _MappingType,
typename _AccessorType>
3248 mdspan(
const typename _AccessorType::data_handle_type&,
const _MappingType&,
3249 const _AccessorType&)
3250 -> mdspan<
typename _AccessorType::element_type,
3251 typename _MappingType::extents_type,
3252 typename _MappingType::layout_type, _AccessorType>;
3254#if __glibcxx_submdspan
3257 template<
typename _IndexType,
typename _Slice>
3259 __canonical_index(_Slice&& __slice)
3261 if constexpr (__detail::__integral_constant_like<_Slice>)
3263 static_assert(__is_representable_integer<_IndexType>(_Slice::value));
3264 static_assert(_Slice::value >= 0);
3265 return std::cw<_IndexType(_Slice::value)>;
3268 return __mdspan::__index_type_cast<_IndexType>(
std::move(__slice));
3271 template<
typename _IndexType,
typename _Slice>
3273 __slice_cast(_Slice&& __slice)
3275 using _SliceType = remove_cvref_t<_Slice>;
3276 if constexpr (is_convertible_v<_SliceType, full_extent_t>)
3277 return static_cast<full_extent_t
>(
std::move(__slice));
3278 else if constexpr (is_convertible_v<_SliceType, _IndexType>)
3279 return __mdspan::__canonical_index<_IndexType>(
std::move(__slice));
3280 else if constexpr (__is_strided_slice<_SliceType>)
3283 = __mdspan::__canonical_index<_IndexType>(
std::move(__slice.extent));
3285 = __mdspan::__canonical_index<_IndexType>(
std::move(__slice.offset));
3286 if constexpr (is_same_v<
decltype(__extent),
3287 constant_wrapper<_IndexType(0)>>)
3288 return strided_slice{
3291 .stride = cw<_IndexType(1)>
3294 return strided_slice{
3298 = __mdspan::__canonical_index<_IndexType>(
std::move(__slice.stride))
3303 auto [__sbegin, __send] =
std::move(__slice);
3305 = __mdspan::__canonical_index<_IndexType>(
std::move(__sbegin));
3307 = __mdspan::__canonical_index<_IndexType>(
std::move(__send));
3308 return strided_slice{
3310 .extent = __mdspan::__canonical_index<_IndexType>(__end - __offset),
3311 .stride = cw<_IndexType(1)>
3316 template<
typename _IndexType,
size_t _Extent,
typename _OIndexType>
3318 __check_valid_index(
const extents<_IndexType, _Extent>& __ext,
3319 const _OIndexType& __idx)
3321 if constexpr (__is_constant_wrapper<_OIndexType>
3322 && _Extent != dynamic_extent)
3324 static_assert(_OIndexType::value >= 0);
3325 static_assert(std::cmp_less_equal(_OIndexType::value, _Extent));
3328 __glibcxx_assert(__idx <= __ext.extent(0));
3331 template<
typename _IndexType,
size_t _Extent,
typename _Slice>
3333 __check_valid_slice(
const extents<_IndexType, _Extent>& __ext,
3334 const _Slice& __slice)
3336 if constexpr (__is_strided_slice<_Slice>)
3342 __mdspan::__check_valid_index(__ext, __slice.offset);
3343 __mdspan::__check_valid_index(__ext, __slice.extent);
3345 if constexpr (__is_constant_wrapper<typename _Slice::extent_type>
3346 && __is_constant_wrapper<typename _Slice::stride_type>)
3347 static_assert(_Slice::stride_type::value > 0);
3349 __glibcxx_assert(__slice.extent == 0 || __slice.stride > 0);
3351 if constexpr (__is_constant_wrapper<typename _Slice::offset_type>
3352 && __is_constant_wrapper<typename _Slice::extent_type>
3353 && _Extent != dynamic_extent)
3354 static_assert(std::cmp_greater_equal(
3355 _Extent - _Slice::offset_type::value,
3356 _Slice::extent_type::value));
3358 __glibcxx_assert(__ext.extent(0) - __slice.offset
3361 else if constexpr (__is_constant_wrapper<_Slice>
3362 && _Extent != dynamic_extent)
3363 static_assert(std::cmp_less(_Slice::value, _Extent));
3364 else if constexpr (convertible_to<_Slice, _IndexType>)
3365 __glibcxx_assert(__slice < __ext.extent(0));
3368 template<
typename _Extents,
typename... _Slices>
3370 __check_valid_slices(
const _Extents& __exts,
const _Slices&... __slices)
3372 constexpr auto __rank = _Extents::rank();
3375 ((__mdspan::__check_valid_slice(__extract_extent<_Is>(__exts),
3376 __slices...[_Is])),...);
3378 __impl(make_index_sequence<__rank>());
3381 template<
typename _Slice>
3382 using __full_extent_t = std::full_extent_t;
3385 void submdspan_mapping() =
delete;
3387 template<
typename _Mapping,
typename... _Slices>
3388 concept __sliceable_mapping =
requires(
const _Mapping __m, _Slices... __slices)
3390 { submdspan_mapping(__m, __slices...) } -> __submdspan_mapping_result;
3393 template<
typename _Mapping,
typename... _Slices>
3395 __submapping(
const _Mapping& __mapping, _Slices... __slices)
3397 __mdspan::__check_valid_slices(__mapping.extents(), __slices...);
3398 return submdspan_mapping(__mapping, __slices...);
3402 template<
typename _IndexType,
size_t... _Extents,
typename... _RawSlices>
3403 requires (
sizeof...(_RawSlices) ==
sizeof...(_Extents))
3405 subextents(
const extents<_IndexType, _Extents...>& __exts,
3406 _RawSlices... __raw_slices)
3408 auto __impl = [&__exts](
auto... __slices)
3410 __mdspan::__check_valid_slices(__exts, __slices...);
3411 return __mdspan::__subextents(__exts, __slices...);
3413 return __impl(__mdspan::__slice_cast<_IndexType>(__raw_slices)...);
3416 template<
typename _IndexType,
size_t... _Extents,
typename... _RawSlices>
3417 requires (
sizeof...(_Extents) ==
sizeof...(_RawSlices))
3419 canonical_slices(
const extents<_IndexType, _Extents...>& __exts,
3420 _RawSlices... __raw_slices)
3422 auto __impl = [&__exts](
auto... __slices)
3424 __mdspan::__check_valid_slices(__exts, __slices...);
3427 return __impl(__mdspan::__slice_cast<_IndexType>(__raw_slices)...);
3430 template<
typename _ElementType,
typename _Extents,
typename _Layout,
3431 typename _Accessor,
typename... _RawSlices>
3432 requires (
sizeof...(_RawSlices) == _Extents::rank()
3433 && __mdspan::__sliceable_mapping<typename _Layout::template mapping<_Extents>,
3434 __mdspan::__full_extent_t<_RawSlices>...>)
3437 const mdspan<_ElementType, _Extents, _Layout, _Accessor>& __md,
3438 _RawSlices... __raw_slices)
3440 using _IndexType =
typename _Extents::index_type;
3441 auto [__mapping, __offset] = __mdspan::__submapping(
3442 __md.mapping(), __mdspan::__slice_cast<_IndexType>(__raw_slices)...);
3444 __md.accessor().offset(__md.data_handle(), __offset),
3446 typename _Accessor::offset_policy(__md.accessor()));
3450_GLIBCXX_END_NAMESPACE_VERSION
constexpr _Tp * assume_aligned(_Tp *__ptr) noexcept
Inform the compiler that a pointer is aligned.
constexpr tuple< typename __decay_and_strip< _Elements >::__type... > make_tuple(_Elements &&... __args)
Create a tuple containing copies of the arguments.
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
ISO C++ entities toplevel namespace is std.
make_integer_sequence< size_t, _Num > make_index_sequence
Alias template make_index_sequence.
integer_sequence< size_t, _Idx... > index_sequence
Alias template index_sequence.
__numeric_traits_integer< _Tp > __int_traits
Convenience alias for __numeric_traits<integer-type>.