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 _OIndexTypeRef>
85 __index_type_cast(_OIndexTypeRef&& __other)
89 using _OIndexType = std::remove_cvref_t<_OIndexTypeRef>;
90 if constexpr (std::is_integral_v<_OIndexType>)
92 constexpr _IndexType __index_type_max
93 = __gnu_cxx::__int_traits<_IndexType>::__max;
94 constexpr _OIndexType __oindex_type_max
95 = __gnu_cxx::__int_traits<_OIndexType>::__max;
97 if constexpr (__index_type_max < __oindex_type_max)
98 __glibcxx_assert(cmp_less_equal(__other, __index_type_max));
100 if constexpr (std::is_signed_v<_OIndexType>)
101 __glibcxx_assert(__other >= 0);
102 return static_cast<_IndexType
>(__other);
109 if constexpr (std::is_signed_v<_IndexType>)
110 __glibcxx_assert(__ret >= 0);
115 template<array _Extents>
119 static constexpr size_t _S_rank = _Extents.size();
127 static constexpr size_t
128 _S_dynamic_index(
size_t __r)
noexcept
129 {
return _S_dynamic_index_data[__r]; }
131 static constexpr auto _S_dynamic_index_data = []
consteval
133 array<size_t, _S_rank+1> __ret;
135 for (
size_t __i = 0; __i < _S_rank; ++__i)
138 __dyn += (_Extents[__i] == dynamic_extent);
140 __ret[_S_rank] = __dyn;
144 static constexpr size_t _S_rank_dynamic = _S_dynamic_index(_S_rank);
148 static constexpr size_t
149 _S_dynamic_index_inv(
size_t __r)
noexcept
150 {
return _S_dynamic_index_inv_data[__r]; }
152 static constexpr auto _S_dynamic_index_inv_data = []
consteval
154 array<size_t, _S_rank_dynamic> __ret;
155 for (
size_t __i = 0, __r = 0; __i < _S_rank; ++__i)
156 if (_Extents[__i] == dynamic_extent)
161 static constexpr size_t
162 _S_static_extent(
size_t __r)
noexcept
163 {
return _Extents[__r]; }
166 template<array _Extents>
167 requires (__all_dynamic<_Extents>())
168 class _StaticExtents<_Extents>
171 static constexpr size_t _S_rank = _Extents.size();
173 static constexpr size_t
174 _S_dynamic_index(
size_t __r)
noexcept
177 static constexpr size_t _S_rank_dynamic = _S_rank;
179 static constexpr size_t
180 _S_dynamic_index_inv(
size_t __k)
noexcept
183 static constexpr size_t
184 _S_static_extent(
size_t)
noexcept
185 {
return dynamic_extent; }
188 template<
typename _IndexType, array _Extents>
189 class _ExtentsStorage :
public _StaticExtents<_Extents>
192 using _Base = _StaticExtents<_Extents>;
195 using _Base::_S_rank;
196 using _Base::_S_rank_dynamic;
197 using _Base::_S_dynamic_index;
198 using _Base::_S_dynamic_index_inv;
199 using _Base::_S_static_extent;
201 static constexpr bool
202 _S_is_dynamic(
size_t __r)
noexcept
204 if constexpr (__all_static(_Extents))
206 else if constexpr (__all_dynamic(_Extents))
209 return _Extents[__r] == dynamic_extent;
212 template<
typename _OIndexType>
213 static constexpr _IndexType
214 _S_int_cast(
const _OIndexType& __other)
noexcept
215 {
return _IndexType(__other); }
218 _M_extent(
size_t __r)
const noexcept
220 if (_S_is_dynamic(__r))
221 return _M_dyn_exts[_S_dynamic_index(__r)];
223 return _S_static_extent(__r);
226 template<
size_t _OtherRank,
typename _GetOtherExtent>
227 static constexpr bool
228 _S_is_compatible_extents(_GetOtherExtent __get_extent)
noexcept
230 if constexpr (_OtherRank == _S_rank)
231 for (
size_t __i = 0; __i < _S_rank; ++__i)
232 if (!_S_is_dynamic(__i)
233 && !cmp_equal(_Extents[__i], _S_int_cast(__get_extent(__i))))
238 template<
size_t _OtherRank,
typename _GetOtherExtent>
240 _M_init_dynamic_extents(_GetOtherExtent __get_extent)
noexcept
242 __glibcxx_assert(_S_is_compatible_extents<_OtherRank>(__get_extent));
243 for (
size_t __i = 0; __i < _S_rank_dynamic; ++__i)
246 if constexpr (_OtherRank != _S_rank_dynamic)
247 __di = _S_dynamic_index_inv(__i);
248 _M_dyn_exts[__i] = _S_int_cast(__get_extent(__di));
253 _ExtentsStorage() noexcept = default;
255 template<typename _OIndexType, array _OExtents>
257 _ExtentsStorage(const _ExtentsStorage<_OIndexType, _OExtents>&
260 _M_init_dynamic_extents<_S_rank>([&__other](
size_t __i)
261 {
return __other._M_extent(__i); });
264 template<
typename _OIndexType,
size_t _Nm>
266 _ExtentsStorage(span<const _OIndexType, _Nm> __exts)
noexcept
268 _M_init_dynamic_extents<_Nm>(
269 [&__exts](
size_t __i) ->
const _OIndexType&
270 {
return __exts[__i]; });
273 static constexpr const array<size_t, _S_rank>&
274 _S_static_extents() noexcept
277 constexpr span<const _IndexType>
278 _M_dynamic_extents(
size_t __begin,
size_t __end)
const noexcept
279 requires (_Extents.size() > 0)
281 return {_M_dyn_exts + _S_dynamic_index(__begin),
282 _S_dynamic_index(__end) - _S_dynamic_index(__begin)};
286 using _Storage = __array_traits<_IndexType, _S_rank_dynamic>::_Type;
287 [[no_unique_address]] _Storage _M_dyn_exts{};
290 template<
typename _OIndexType,
typename _SIndexType>
291 concept __valid_index_type =
292 is_convertible_v<_OIndexType, _SIndexType> &&
293 is_nothrow_constructible_v<_SIndexType, _OIndexType>;
295 template<
size_t _Extent,
typename _IndexType>
297 __valid_static_extent = _Extent == dynamic_extent
298 || _Extent <= __gnu_cxx::__int_traits<_IndexType>::__max;
300 template<
typename _Extents>
301 constexpr const array<size_t, _Extents::rank()>&
302 __static_extents() noexcept
303 {
return _Extents::_Storage::_S_static_extents(); }
305 template<
typename _Extents>
306 constexpr span<const size_t>
307 __static_extents(
size_t __begin,
size_t __end)
noexcept
309 const auto& __sta_exts = __static_extents<_Extents>();
310 return span<const size_t>(__sta_exts.data() + __begin, __end - __begin);
314 template<array _Extents>
315 constexpr auto __fwd_partial_prods = []
consteval
317 constexpr size_t __rank = _Extents.size();
318 std::array<size_t, __rank> __ret;
320 for (
size_t __r = 0; __r < __rank; ++__r)
323 if (
size_t __ext = _Extents[__r]; __ext != dynamic_extent)
330 template<array _Extents>
331 constexpr auto __rev_partial_prods = []
consteval
333 constexpr size_t __rank = _Extents.size();
334 std::array<size_t, __rank> __ret;
336 for (
size_t __r = __rank; __r > 0; --__r)
338 __ret[__r - 1] = __prod;
339 if (
size_t __ext = _Extents[__r - 1]; __ext != dynamic_extent)
345 template<
typename _Extents>
346 constexpr span<const typename _Extents::index_type>
347 __dynamic_extents(
const _Extents& __exts,
size_t __begin = 0,
348 size_t __end = _Extents::rank()) noexcept
349 {
return __exts._M_exts._M_dynamic_extents(__begin, __end); }
352#if __glibcxx_submdspan
355 explicit full_extent_t() =
default;
358 inline constexpr full_extent_t full_extent{};
360 template<
typename _OffsetType,
typename _ExtentType,
typename _Str
ideType>
363 static_assert(__is_signed_or_unsigned_integer<_OffsetType>::value
364 || __detail::__integral_constant_like<_OffsetType>);
365 static_assert(__is_signed_or_unsigned_integer<_ExtentType>::value
366 || __detail::__integral_constant_like<_ExtentType>);
367 static_assert(__is_signed_or_unsigned_integer<_StrideType>::value
368 || __detail::__integral_constant_like<_StrideType>);
370 using offset_type = _OffsetType;
371 using extent_type = _ExtentType;
372 using stride_type = _StrideType;
374 [[no_unique_address]] offset_type offset{};
375 [[no_unique_address]] extent_type extent{};
376 [[no_unique_address]] stride_type stride{};
379 template<
typename _FirstType,
typename _LastType,
typename _Str
ideType = constant_wrapper<1zu>>
382 static_assert(__is_signed_or_unsigned_integer<_FirstType>::value
383 || __detail::__integral_constant_like<_FirstType>);
384 static_assert(__is_signed_or_unsigned_integer<_LastType>::value
385 || __detail::__integral_constant_like<_LastType>);
386 static_assert(__is_signed_or_unsigned_integer<_StrideType>::value
387 || __detail::__integral_constant_like<_StrideType>);
389 [[no_unique_address]] _FirstType first{};
390 [[no_unique_address]] _LastType last{};
391 [[no_unique_address]] _StrideType stride{};
394 template<
typename _Mapping>
395 struct submdspan_mapping_result
397 [[no_unique_address]] _Mapping mapping = _Mapping();
401 template<
typename _Tp>
402 constexpr bool __is_submdspan_mapping_result =
false;
404 template<
typename _Mapping>
405 constexpr bool __is_submdspan_mapping_result<submdspan_mapping_result<_Mapping>> =
true;
407 template<
typename _Mapping>
408 concept __submdspan_mapping_result = __is_submdspan_mapping_result<_Mapping>;
412 template<
typename _IndexType,
size_t... _Extents>
415 static_assert(__is_signed_or_unsigned_integer<_IndexType>::value,
416 "IndexType must be a signed or unsigned integer type");
418 (__mdspan::__valid_static_extent<_Extents, _IndexType> && ...),
419 "Extents must either be dynamic or representable as IndexType");
421 using _Storage = __mdspan::_ExtentsStorage<
422 _IndexType, array<size_t,
sizeof...(_Extents)>{_Extents...}>;
423 [[no_unique_address]] _Storage _M_exts;
426 using index_type = _IndexType;
428 using rank_type = size_t;
430 static constexpr rank_type
431 rank() noexcept {
return _Storage::_S_rank; }
433 static constexpr rank_type
434 rank_dynamic() noexcept {
return _Storage::_S_rank_dynamic; }
436 static constexpr size_t
437 static_extent(rank_type __r)
noexcept
439 __glibcxx_assert(__r < rank());
440 if constexpr (rank() == 0)
443 return _Storage::_S_static_extent(__r);
447 extent(rank_type __r)
const noexcept
449 __glibcxx_assert(__r < rank());
450 if constexpr (rank() == 0)
453 return _M_exts._M_extent(__r);
457 extents() noexcept = default;
460 static consteval
bool
461 _S_is_less_dynamic(
size_t __ext,
size_t __oext)
462 {
return (__ext != dynamic_extent) && (__oext == dynamic_extent); }
464 template<
typename _OIndexType,
size_t... _OExtents>
465 static consteval bool
468 return (_S_is_less_dynamic(_Extents, _OExtents) || ...)
469 || (__gnu_cxx::__int_traits<index_type>::__max
470 < __gnu_cxx::__int_traits<_OIndexType>::__max);
473 template<
size_t... _OExtents>
474 static consteval bool
475 _S_is_compatible_extents()
477 if constexpr (
sizeof...(_OExtents) != rank())
480 return ((_OExtents == dynamic_extent || _Extents == dynamic_extent
481 || _OExtents == _Extents) && ...);
485 template<
typename _OIndexType,
size_t... _OExtents>
486 requires (_S_is_compatible_extents<_OExtents...>())
487 constexpr explicit(_S_ctor_explicit<_OIndexType, _OExtents...>())
488 extents(
const extents<_OIndexType, _OExtents...>& __other) noexcept
489 : _M_exts(__other._M_exts)
492 template<__mdspan::__val
id_index_type<index_type>... _OIndexTypes>
493 requires (
sizeof...(_OIndexTypes) == rank()
494 ||
sizeof...(_OIndexTypes) == rank_dynamic())
495 constexpr explicit extents(_OIndexTypes... __exts) noexcept
496 : _M_exts(span<
const _IndexType,
sizeof...(_OIndexTypes)>(
497 initializer_list{
static_cast<_IndexType
>(
std::move(__exts))...}))
500 template<
typename _OIndexType,
size_t _Nm>
501 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
502 && (_Nm == rank() || _Nm == rank_dynamic())
503 constexpr explicit(_Nm != rank_dynamic())
504 extents(span<_OIndexType, _Nm> __exts) noexcept
505 : _M_exts(span<const _OIndexType, _Nm>(__exts))
508 template<
typename _OIndexType,
size_t _Nm>
509 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
510 && (_Nm == rank() || _Nm == rank_dynamic())
511 constexpr explicit(_Nm != rank_dynamic())
512 extents(
const array<_OIndexType, _Nm>& __exts) noexcept
513 : _M_exts(span<const _OIndexType, _Nm>(__exts))
516 template<
typename _OIndexType,
size_t... _OExtents>
517 friend constexpr bool
518 operator==(
const extents& __self,
519 const extents<_OIndexType, _OExtents...>& __other)
noexcept
521 if constexpr (!_S_is_compatible_extents<_OExtents...>())
525 auto __impl = [&__self, &__other]<
size_t... _Counts>(
527 {
return (cmp_equal(__self.extent(_Counts),
528 __other.extent(_Counts)) && ...); };
534 friend constexpr const array<size_t, rank()>&
535 __mdspan::__static_extents<extents>() noexcept;
537 friend constexpr span<const index_type>
538 __mdspan::__dynamic_extents<extents>(const extents&,
size_t,
size_t)
541 template<typename _OIndexType,
size_t... _OExtents>
542 friend class extents;
547 template<
typename _Tp,
size_t _Nm>
549 __contains_zero(span<_Tp, _Nm> __exts)
noexcept
551 for (
size_t __i = 0; __i < __exts.size(); ++__i)
552 if (__exts[__i] == 0)
557 template<
typename _Tp,
size_t _Nm>
559 __contains_zero(
const array<_Tp, _Nm>& __exts)
noexcept
560 {
return __contains_zero(span<const _Tp>(__exts)); }
562 template<
typename _Extents>
564 __empty(
const _Extents& __exts)
noexcept
566 if constexpr (__contains_zero(__static_extents<_Extents>()))
568 else if constexpr (_Extents::rank_dynamic() > 0)
569 return __contains_zero(__dynamic_extents(__exts));
574 template<
typename _Extents>
575 constexpr typename _Extents::index_type
576 __extents_prod(
const _Extents& __exts,
size_t __sta_prod,
size_t __begin,
577 size_t __end)
noexcept
582 size_t __ret = __sta_prod;
583 if constexpr (_Extents::rank_dynamic() > 0)
584 for (
auto __factor : __dynamic_extents(__exts, __begin, __end))
585 __ret *= size_t(__factor);
586 return static_cast<typename _Extents::index_type
>(__ret);
590 template<
typename _Extents>
591 constexpr typename _Extents::index_type
592 __fwd_prod(
const _Extents& __exts,
size_t __begin,
size_t __end)
noexcept
594 size_t __sta_prod = [__begin, __end] {
595 span<const size_t> __sta_exts
596 = __static_extents<_Extents>(__begin, __end);
598 for(
auto __ext : __sta_exts)
599 if (__ext != dynamic_extent)
603 return __extents_prod(__exts, __sta_prod, __begin, __end);
606 template<
typename _Extents>
607 constexpr typename _Extents::index_type
608 __fwd_prod(
const _Extents& __exts,
size_t __r)
noexcept
610 constexpr size_t __rank = _Extents::rank();
611 constexpr auto& __sta_exts = __static_extents<_Extents>();
612 if constexpr (__rank == 1)
614 else if constexpr (__rank == 2)
615 return __r == 0 ? 1 : __exts.extent(0);
616 else if constexpr (__all_dynamic(std::span(__sta_exts).first(__rank-1)))
617 return __extents_prod(__exts, 1, 0, __r);
620 size_t __sta_prod = __fwd_partial_prods<__sta_exts>[__r];
621 return __extents_prod(__exts, __sta_prod, 0, __r);
625 template<
typename _IndexType,
size_t _Nm>
627 __fwd_prod(span<const _IndexType, _Nm> __values)
629 _IndexType __ret = 1;
630 for(
auto __value : __values)
636 template<
typename _Extents>
637 constexpr typename _Extents::index_type
638 __rev_prod(
const _Extents& __exts,
size_t __r)
noexcept
640 constexpr size_t __rank = _Extents::rank();
641 constexpr auto& __sta_exts = __static_extents<_Extents>();
642 if constexpr (__rank == 1)
644 else if constexpr (__rank == 2)
645 return __r == 0 ? __exts.extent(1) : 1;
646 else if constexpr (__all_dynamic(std::span(__sta_exts).last(__rank-1)))
647 return __extents_prod(__exts, 1, __r + 1, __rank);
650 size_t __sta_prod = __rev_partial_prods<__sta_exts>[__r];
651 return __extents_prod(__exts, __sta_prod, __r + 1, __rank);
655 template<
typename _Extents>
656 constexpr typename _Extents::index_type
657 __size(
const _Extents& __exts)
noexcept
659 constexpr size_t __sta_prod = [] {
660 span<const size_t> __sta_exts = __static_extents<_Extents>();
662 for(
auto __ext : __sta_exts)
663 if (__ext != dynamic_extent)
667 return __extents_prod(__exts, __sta_prod, 0, _Extents::rank());
670 template<
typename _IndexType,
size_t... _Counts>
671 auto __build_dextents_type(integer_sequence<size_t, _Counts...>)
672 -> extents<_IndexType, ((void) _Counts, dynamic_extent)...>;
675 template<
typename _IndexType,
size_t _Rank>
676 using dextents =
decltype(__mdspan::__build_dextents_type<_IndexType>(
679#if __glibcxx_mdspan >= 202406L
680 template<
size_t _Rank,
typename _IndexType =
size_t>
681 using dims = dextents<_IndexType, _Rank>;
684 template<
typename... _Integrals>
685 requires (is_convertible_v<_Integrals, size_t> && ...)
686 explicit extents(_Integrals...) ->
687 extents<size_t, __detail::__maybe_static_ext<_Integrals>...>;
691 template<
typename _Extents>
697 template<
typename _Extents>
703 template<
typename _Extents>
707#ifdef __glibcxx_padded_layouts
708 template<
size_t _PaddingValue>
709 struct layout_left_padded
711 template<
typename _Extents>
715 template<
size_t _PaddingValue>
716 struct layout_right_padded
718 template<
typename _Extents>
725 template<
typename _Tp>
726 constexpr bool __is_extents =
false;
728 template<
typename _IndexType,
size_t... _Extents>
729 constexpr bool __is_extents<extents<_IndexType, _Extents...>> =
true;
731 template<
typename _Extents,
typename... _Indices>
732 constexpr typename _Extents::index_type
733 __linear_index_left(
const _Extents& __exts, _Indices... __indices)
736 using _IndexType =
typename _Extents::index_type;
737 _IndexType __res = 0;
738 if constexpr (
sizeof...(__indices) > 0)
740 _IndexType __mult = 1;
741 auto __update = [&, __pos = 0u](_IndexType __idx)
mutable
743 _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx, __exts.extent(__pos)));
744 __res += __idx * __mult;
745 __mult *= __exts.extent(__pos);
748 (__update(__indices), ...);
753 template<
typename _IndexType>
755 __static_quotient(std::span<const size_t> __sta_exts,
756 _IndexType __nom = __gnu_cxx::__int_traits<_IndexType>::__max)
758 for (
auto __factor : __sta_exts)
760 if (__factor != dynamic_extent)
761 __nom /= _IndexType(__factor);
768 template<
typename _Extents,
769 typename _IndexType =
typename _Extents::index_type>
770 requires __is_extents<_Extents>
772 __static_quotient(_IndexType __nom
773 = __gnu_cxx::__int_traits<_IndexType>::__max)
775 std::span<const size_t> __sta_exts = __static_extents<_Extents>();
776 return __static_quotient<_IndexType>(__sta_exts, __nom);
779 template<
typename _Extents>
781 __is_representable_extents(
const _Extents& __exts)
noexcept
783 using _IndexType = _Extents::index_type;
785 if constexpr (__contains_zero(__static_extents<_Extents>()))
789 constexpr auto __sta_quo = __static_quotient<_Extents>();
790 if constexpr (_Extents::rank_dynamic() == 0)
791 return __sta_quo != 0;
794 auto __dyn_exts = __dynamic_extents(__exts);
795 if (__contains_zero(__dyn_exts))
798 if constexpr (__sta_quo == 0)
802 auto __dyn_quo = _IndexType(__sta_quo);
803 for (
auto __factor : __dyn_exts)
805 __dyn_quo /= __factor;
815 template<
typename _Extents,
typename _IndexType>
816 concept __representable_size = _Extents::rank_dynamic() != 0
817 || __contains_zero(__static_extents<_Extents>())
818 || (__static_quotient<_Extents, _IndexType>() != 0);
820 template<
typename _Layout,
typename _Mapping>
821 concept __mapping_of =
822 is_same_v<
typename _Layout::template mapping<
823 typename _Mapping::extents_type>,
826 template<
template<
size_t>
typename _Layout,
typename _Mapping>
827 concept __padded_mapping_of = __mapping_of<
828 _Layout<_Mapping::padding_value>, _Mapping>;
830#ifdef __glibcxx_padded_layouts
831 template<
typename _Mapping>
832 constexpr bool __is_left_padded_mapping = __padded_mapping_of<
833 layout_left_padded, _Mapping>;
835 template<
typename _Mapping>
836 constexpr bool __is_right_padded_mapping = __padded_mapping_of<
837 layout_right_padded, _Mapping>;
839 template<
typename _Mapping>
840 constexpr bool __is_padded_mapping = __is_left_padded_mapping<_Mapping>
841 || __is_right_padded_mapping<_Mapping>;
844 template<
typename _PaddedMapping>
846 __get_static_stride()
847 {
return _PaddedMapping::_PaddedStorage::_S_static_stride; }
849 template<
typename _Mapping>
850 concept __standardized_mapping = __mapping_of<layout_left, _Mapping>
851 || __mapping_of<layout_right, _Mapping>
852 || __mapping_of<layout_stride, _Mapping>
853#ifdef __glibcxx_padded_layouts
854 || __is_left_padded_mapping<_Mapping>
855 || __is_right_padded_mapping<_Mapping>
860 class __internal_ctor
863 template<
typename _Mapping>
864 constexpr typename _Mapping::index_type
865 __offset(
const _Mapping& __m)
noexcept
867 using _IndexType =
typename _Mapping::index_type;
868 constexpr auto __rank = _Mapping::extents_type::rank();
870 if constexpr (__standardized_mapping<_Mapping>)
872 else if (__empty(__m.extents()))
876 auto __impl = [&__m]<
size_t... _Counts>(
index_sequence<_Counts...>)
877 {
return __m(((
void) _Counts, _IndexType(0))...); };
878 return __impl(make_index_sequence<__rank>());
882#ifdef __glibcxx_submdspan
883 template<
typename _Tp>
884 constexpr bool __is_extent_slice =
false;
886 template<
typename _OffsetType,
typename _ExtentType,
typename _Str
ideType>
887 constexpr bool __is_extent_slice<extent_slice<_OffsetType,
888 _ExtentType, _StrideType>> =
true;
890 template<
typename _Tp>
891 constexpr bool __is_range_slice =
false;
893 template<
typename _FirstType,
typename _LastType,
typename _Str
ideType>
894 constexpr bool __is_range_slice<range_slice<_FirstType,
895 _LastType, _StrideType>> =
true;
897 template<
typename _IndexType,
typename _OIndexType>
899 __is_representable_integer(_OIndexType __value)
901 constexpr auto __min = __gnu_cxx::__int_traits<_IndexType>::__min;
902 constexpr auto __max = __gnu_cxx::__int_traits<_IndexType>::__max;
903 return std::cmp_less_equal(__min, __value)
904 && std::cmp_less_equal(__value, __max);
907 template<
typename _Tp>
908 constexpr bool __is_constant_wrapper =
false;
910 template<_CwFixedValue _Xv,
typename _Tp>
911 constexpr bool __is_constant_wrapper<constant_wrapper<_Xv, _Tp>>
914 template<
size_t _Index,
typename _Extents>
916 __extract_extent(
const _Extents& __exts)
918 using _IndexType =
typename _Extents::index_type;
919 return extents<_IndexType, _Extents::static_extent(_Index)>{
920 __exts.extent(_Index)};
923 template<
typename _Slice,
typename _IndexType>
924 concept __acceptable_slice_type = same_as<_Slice, full_extent_t>
925 || same_as<_Slice, _IndexType> || __is_constant_wrapper<_Slice>
926 || __is_extent_slice<_Slice>;
928 template<
typename _IndexType,
typename... _Slices>
932 return (
static_cast<size_t>(!convertible_to<_Slices, _IndexType>)
936 template<
typename _IndexType,
typename... _Slices>
940 constexpr auto __rank =
sizeof...(_Slices);
941 constexpr auto __sub_rank = __subrank<_IndexType, _Slices...>();
942 auto __map = std::array<size_t, __sub_rank>{};
943 auto __is_int_like = std::array<bool, __rank>{
944 convertible_to<_Slices, _IndexType>...};
947 for (
size_t __k = 0; __k < __rank; ++__k)
948 if (!__is_int_like[__k])
953 template<
typename _Slice>
955 __slice_begin(_Slice __slice)
957 if constexpr (same_as<_Slice, full_extent_t>)
959 else if constexpr (__is_extent_slice<_Slice>)
960 return __slice.offset;
965 template<
typename _Mapping,
typename... _Slices>
967 __suboffset(
const _Mapping& __mapping,
const _Slices&... __slices)
969 using _IndexType =
typename _Mapping::index_type;
970 auto __any_past_the_end = [&]<
size_t... _Is>(
index_sequence<_Is...>)
972 auto __is_past_the_end = [](
const auto& __slice,
const auto& __ext)
974 using _Slice = remove_cvref_t<
decltype(__slice)>;
975 if constexpr (is_convertible_v<_Slice, _IndexType>)
977 else if constexpr (same_as<_Slice, full_extent_t>
978 && __ext.static_extent(0) != 0
979 && __ext.static_extent(0) != dynamic_extent)
982 return __mdspan::__slice_begin(__slice) == __ext.extent(0);
985 const auto& __exts = __mapping.extents();
986 return ((__is_past_the_end(__slices...[_Is],
987 __mdspan::__extract_extent<_Is>(__exts))) || ...);
990 if constexpr ((same_as<_Slices, full_extent_t> && ...))
991 return __mdspan::__offset(__mapping);
994 return __mapping.required_span_size();
995 return __mapping(__mdspan::__slice_begin(__slices)...);
998 template<
typename _IndexType,
size_t _Extent,
typename _Slice>
1000 __static_slice_extent()
1002 if constexpr (same_as<_Slice, full_extent_t>)
1004 else if constexpr (same_as<_Slice, constant_wrapper<_IndexType(0)>>)
1006 else if constexpr (__is_constant_wrapper<typename _Slice::extent_type>)
1007 return _Slice::extent_type::value;
1009 return dynamic_extent;
1012 template<
size_t _K,
typename _Extents,
typename _Slice>
1013 constexpr typename _Extents::index_type
1014 __dynamic_slice_extent(
const _Extents& __exts, _Slice __slice)
1016 if constexpr (__is_extent_slice<_Slice>)
1017 return __slice.extent;
1019 return __exts.extent(_K);
1022 template<
typename _IndexType,
size_t... _Extents,
typename... _Slices>
1023 requires (
sizeof...(_Slices) ==
sizeof...(_Extents))
1025 __subextents(
const extents<_IndexType, _Extents...>& __exts,
1026 _Slices... __slices)
1028 constexpr auto __inv_map = __mdspan::__inv_map_rank<_IndexType, _Slices...>();
1031 using _SubExts = extents<_IndexType,
1032 __mdspan::__static_slice_extent<_IndexType,
1033 _Extents...[__inv_map[_Indices]],
1034 _Slices...[__inv_map[_Indices]]>()...>;
1035 if constexpr (_SubExts::rank_dynamic() == 0)
1039 using _StaticSubExtents = __mdspan::_StaticExtents<
1040 __mdspan::__static_extents<_SubExts>()>;
1043 constexpr auto __slice_idx = [__inv_map](
size_t __i)
consteval
1045 return __inv_map[_StaticSubExtents::_S_dynamic_index_inv(__i)];
1048 return _SubExts{__mdspan::__dynamic_slice_extent<__slice_idx(_Is)>(
1049 __exts, __slices...[__slice_idx(_Is)])...};
1051 constexpr auto __dyn_subrank = _SubExts::rank_dynamic();
1059 enum class _LayoutSide
1066 template<
typename _Mapping>
1067 consteval _LayoutSide
1070 if constexpr (__is_left_padded_mapping<_Mapping>
1071 || __mapping_of<layout_left, _Mapping>)
1072 return _LayoutSide::__left;
1073 if constexpr (__is_right_padded_mapping<_Mapping>
1074 || __mapping_of<layout_right, _Mapping>)
1075 return _LayoutSide::__right;
1077 return _LayoutSide::__unknown;
1080 template<_LayoutS
ide _S
ide,
size_t _Rank>
1081 struct _StridesTrait
1083 static constexpr const _LayoutSide _S_side = _Side;
1085 static constexpr size_t
1086 _S_idx(
size_t __k)
noexcept
1088 if constexpr (_Side == _LayoutSide::__left)
1091 return _Rank - 1 - __k;
1096 template<
typename _Mapping>
1097 static constexpr typename _Mapping::index_type
1098 _S_padded_extent(
const _Mapping& __mapping,
size_t __k)
1101 return __mapping.stride(_S_idx(1));
1103 return __mapping.extents().extent(_S_idx(__k));
1106 template<
typename _IndexType,
typename... _Slices>
1107 static consteval auto
1110 static_assert(_Side != _LayoutSide::__unknown);
1113 return __mdspan::__inv_map_rank<_IndexType, _Slices...[_S_idx(_Is)]...>();
1119 template<
typename _SubExts,
typename _Mapping,
typename... _Slices>
1121 __substrides_generic(
const _Mapping& __mapping,
const _Slices&... __slices)
1123 using _IndexType =
typename _Mapping::index_type;
1124 if constexpr (_SubExts::rank() == 0)
1125 return array<_IndexType, _SubExts::rank()>{};
1128 auto __stride = [&__mapping](
size_t __k,
auto __slice) -> _IndexType
1130 if constexpr (__is_extent_slice<
decltype(__slice)>)
1131 if (__slice.extent > 1)
1132 return __mapping.stride(__k) * __slice.stride;
1133 return __mapping.stride(__k);
1138 constexpr auto __inv_map
1139 = __mdspan::__inv_map_rank<_IndexType, _Slices...>();
1140 return array<_IndexType, _SubExts::rank()>{
1141 __stride(__inv_map[_Is], __slices...[__inv_map[_Is]])...};
1147 template<
typename _SubExts,
typename _Mapping,
typename... _Slices>
1149 __substrides_standardized(
const _Mapping& __mapping,
1150 const _Slices&... __slices)
1152 using _IndexType =
typename _Mapping::index_type;
1153 using _Trait = _StridesTrait<__mapping_side<_Mapping>(),
1154 _Mapping::extents_type::rank()>;
1155 using _SubTrait = _StridesTrait<__mapping_side<_Mapping>(), _SubExts::rank()>;
1157 constexpr size_t __sub_rank = _SubExts::rank();
1159 std::array<_IndexType, __sub_rank> __ret;
1160 if constexpr (__sub_rank > 0)
1162 constexpr auto __inv_map
1163 = _Trait::template _S_inv_map<_IndexType, _Slices...>();
1167 size_t __stride = 1;
1168 auto __body = [&](
size_t __k,
auto __slice)
1170 for (
size_t __i = __i0; __i < __inv_map[__k]; ++__i)
1171 __stride *= _Trait::_S_padded_extent(__mapping, __i);
1173 size_t __krev = _SubTrait::_S_idx(__k);
1174 if constexpr (__is_extent_slice<
decltype(__slice)>)
1176 if (__slice.extent > 1)
1177 __ret[__krev] = __stride * __slice.stride;
1179 __ret[__krev] = __stride;
1182 __ret[__krev] = __stride;
1184 __i0 = __inv_map[__k];
1187 ((__body(_Ks, __slices...[_Trait::_S_idx(__inv_map[_Ks])])),...);
1195 template<
typename _SubExts,
typename _Mapping,
typename... _Slices>
1197 __substrides(
const _Mapping& __mapping,
const _Slices&... __slices)
1199 if constexpr (__mdspan::__mapping_side<_Mapping>() == _LayoutSide::__unknown)
1200 return __mdspan::__substrides_generic<_SubExts>(__mapping, __slices...);
1202 return __mdspan::__substrides_standardized<_SubExts>(__mapping, __slices...);
1205 template<
typename _Slice>
1206 concept __is_unit_stride_slice = (__mdspan::__is_extent_slice<_Slice>
1207 && __mdspan::__is_constant_wrapper<typename _Slice::stride_type>
1208 && _Slice::stride_type::value == 1)
1209 || std::same_as<_Slice, full_extent_t>;
1215 enum class _SliceKind
1218 __unit_stride_slice,
1223 template<
typename _Slice>
1224 consteval _SliceKind
1227 if constexpr (std::same_as<_Slice, full_extent_t>)
1228 return _SliceKind::__full;
1229 else if constexpr (__mdspan::__is_extent_slice<_Slice>)
1231 if constexpr (__mdspan::__is_unit_stride_slice<_Slice>)
1232 return _SliceKind::__unit_stride_slice;
1234 return _SliceKind::__extent_slice;
1237 return _SliceKind::__collapsing;
1240 template<
typename... _Slices>
1241 consteval array<_SliceKind,
sizeof...(_Slices)>
1242 __make_slice_kind_array()
1244 return array<_SliceKind,
sizeof...(_Slices)>{
1245 __mdspan::__make_slice_kind<_Slices>()...};
1251 __is_block(span<const _SliceKind> __slice_kinds,
size_t __block_size)
1253 if (__block_size == 0)
1256 if (__block_size > __slice_kinds.size())
1259 for (
size_t __i = 0; __i < __block_size - 1; ++__i)
1260 if (__slice_kinds[__i] != _SliceKind::__full)
1263 auto __last = __slice_kinds[__block_size - 1];
1264 return __last == _SliceKind::__full
1265 || __last == _SliceKind::__unit_stride_slice;
1270 static consteval size_t
1271 __padded_block_begin_generic(span<const _SliceKind> __slice_kinds,
1274 if (__slice_kinds[0] != _SliceKind::__full
1275 && __slice_kinds[0] != _SliceKind::__unit_stride_slice)
1276 return dynamic_extent;
1277 else if (__slice_kinds.size() == 1)
1278 return dynamic_extent;
1282 while(__u < __slice_kinds.size()
1283 && __slice_kinds[__u] == _SliceKind::__collapsing)
1286 if (__mdspan::__is_block(__slice_kinds.subspan(__u), __sub_rank -1))
1288 return dynamic_extent;
1292 template<_LayoutS
ide _S
ide,
size_t _Nm>
1293 static consteval size_t
1294 __padded_block_begin(span<const _SliceKind, _Nm> __slice_kinds,
size_t __sub_rank)
1296 if constexpr (_Side == _LayoutSide::__left)
1297 return __mdspan::__padded_block_begin_generic(__slice_kinds, __sub_rank);
1300 std::array<_SliceKind, _Nm> __rev_slices;
1301 for(
size_t __i = 0; __i < _Nm; ++__i)
1302 __rev_slices[__i] = __slice_kinds[_Nm - 1 - __i];
1303 auto __rev_slice_kinds = span<const _SliceKind>(__rev_slices);
1305 auto __u = __mdspan::__padded_block_begin_generic(__rev_slice_kinds,
1307 return __u == dynamic_extent ? dynamic_extent : _Nm - 1 - __u;
1311 template<_LayoutS
ide _S
ide,
bool _Padded>
1312 struct _SubMdspanMapping;
1315 struct _SubMdspanMapping<_LayoutSide::__left, false>
1317 using _Layout = layout_left;
1318 template<
size_t _Pad>
using _PaddedLayout = layout_left_padded<_Pad>;
1320 template<
typename _Mapping,
size_t _Us>
1321 static consteval size_t
1324 using _Extents =
typename _Mapping::extents_type;
1325 constexpr auto __sta_exts = __mdspan::__static_extents<_Extents>(0, _Us);
1326 if constexpr (!__mdspan::__all_static(__sta_exts))
1327 return dynamic_extent;
1329 return __mdspan::__fwd_prod(__sta_exts);
1332 template<
size_t _Nm>
1333 static consteval bool
1334 _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
size_t __sub_rank)
1335 {
return __mdspan::__is_block(__slice_kinds, __sub_rank); }
1339 struct _SubMdspanMapping<_LayoutSide::__left, true>
1341 using _Layout = layout_left;
1342 template<
size_t _Pad>
using _PaddedLayout = layout_left_padded<_Pad>;
1344 template<
typename _Mapping,
size_t _Us>
1345 static consteval size_t
1348 using _Extents =
typename _Mapping::extents_type;
1349 constexpr auto __sta_exts
1350 = __mdspan::__static_extents<_Extents>(1, _Us);
1351 constexpr auto __sta_padstride
1352 = __mdspan::__get_static_stride<_Mapping>();
1353 if constexpr (__sta_padstride == dynamic_extent
1354 || !__mdspan::__all_static(__sta_exts))
1355 return dynamic_extent;
1357 return __sta_padstride * __mdspan::__fwd_prod(__sta_exts);
1360 template<
size_t _Nm>
1361 static consteval bool
1362 _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
1365 if (__sub_rank == 1)
1366 return __slice_kinds[0] == _SliceKind::__unit_stride_slice
1367 || __slice_kinds[0] == _SliceKind::__full;
1374 struct _SubMdspanMapping<_LayoutSide::__right, false>
1376 using _Layout = layout_right;
1377 template<
size_t _Pad>
using _PaddedLayout = layout_right_padded<_Pad>;
1379 template<
typename _Mapping,
size_t _Us>
1380 static consteval size_t
1383 using _Extents =
typename _Mapping::extents_type;
1384 constexpr auto __rank = _Extents::rank();
1385 constexpr auto __sta_exts
1386 = __mdspan::__static_extents<_Extents>(_Us + 1, __rank);
1387 if constexpr (!__mdspan::__all_static(__sta_exts))
1388 return dynamic_extent;
1390 return __fwd_prod(__sta_exts);
1393 template<
size_t _Nm>
1394 static consteval bool
1395 _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
1398 auto __rev_slice_kinds = array<_SliceKind, _Nm>{};
1399 for(
size_t __i = 0; __i < _Nm; ++__i)
1400 __rev_slice_kinds[__i] = __slice_kinds[_Nm - 1 - __i];
1401 return __mdspan::__is_block(span(__rev_slice_kinds), __sub_rank);
1406 struct _SubMdspanMapping<_LayoutSide::__right, true>
1408 using _Layout = layout_right;
1409 template<
size_t _Pad>
using _PaddedLayout = layout_right_padded<_Pad>;
1411 template<
typename _Mapping,
size_t _Us>
1412 static consteval size_t
1415 using _Extents =
typename _Mapping::extents_type;
1416 constexpr auto __rank = _Extents::rank();
1417 constexpr auto __sta_exts
1418 = __mdspan::__static_extents<_Extents>(_Us + 1, __rank - 1);
1419 constexpr auto __sta_padstride
1420 = __mdspan::__get_static_stride<_Mapping>();
1421 if constexpr (__sta_padstride == dynamic_extent
1422 || !__mdspan::__all_static(__sta_exts))
1423 return dynamic_extent;
1425 return __sta_padstride * __mdspan::__fwd_prod(__sta_exts);
1428 template<
size_t _Nm>
1429 static consteval bool
1430 _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
1433 if (__sub_rank == 1)
1434 return __slice_kinds[_Nm - 1] == _SliceKind::__unit_stride_slice
1435 || __slice_kinds[_Nm - 1] == _SliceKind::__full;
1442 template<
typename _Mapping>
1444 __submdspan_mapping_impl(
const _Mapping& __mapping)
1445 {
return submdspan_mapping_result{__mapping, 0}; }
1447 template<
typename _Mapping,
typename... _Slices>
1448 requires (
sizeof...(_Slices) > 0)
1450 __submdspan_mapping_impl(
const _Mapping& __mapping, _Slices... __slices)
1452 using _IndexType =
typename _Mapping::index_type;
1453 static_assert((__acceptable_slice_type<_Slices, _IndexType> && ...));
1455 constexpr auto __side = __mdspan::__mapping_side<_Mapping>();
1456 constexpr auto __rank =
sizeof...(_Slices);
1457 using _Trait = _SubMdspanMapping<__side, __is_padded_mapping<_Mapping>>;
1458 using _SliceView = span<const _SliceKind, __rank>;
1460 constexpr auto __slice_kinds = __mdspan::__make_slice_kind_array<_Slices...>();
1461 auto __offset = __mdspan::__suboffset(__mapping, __slices...);
1462 auto __sub_exts = __mdspan::__subextents(__mapping.extents(), __slices...);
1463 using _SubExts =
decltype(__sub_exts);
1464 constexpr auto __sub_rank = _SubExts::rank();
1465 if constexpr (__sub_rank == 0)
1466 return submdspan_mapping_result{
1467 typename _Trait::_Layout::mapping(__sub_exts), __offset};
1468 else if constexpr (_Trait::_S_is_unpadded_submdspan(
1469 _SliceView(__slice_kinds), __sub_rank))
1470 return submdspan_mapping_result{
1471 typename _Trait::_Layout::mapping(__sub_exts), __offset};
1473 constexpr auto __u = __padded_block_begin<__side>(
1474 _SliceView(__slice_kinds), __sub_rank);
1475 __u != dynamic_extent)
1477 constexpr auto __pad = _Trait::template _S_pad<_Mapping, __u>();
1478 using _Layout =
typename _Trait::template _PaddedLayout<__pad>;
1479 return submdspan_mapping_result{
1480 typename _Layout::mapping(__sub_exts, __mapping.stride(__u)),
1486 = __mdspan::__substrides<_SubExts>(__mapping, __slices...);
1487 return submdspan_mapping_result{
1488 layout_stride::mapping(__sub_exts, __sub_strides), __offset};
1494 template<
typename _Extents>
1495 class layout_left::mapping
1498 using extents_type = _Extents;
1499 using index_type =
typename extents_type::index_type;
1500 using size_type =
typename extents_type::size_type;
1501 using rank_type =
typename extents_type::rank_type;
1502 using layout_type = layout_left;
1504 static_assert(__mdspan::__representable_size<extents_type, index_type>,
1505 "The size of extents_type must be representable as index_type");
1508 mapping() noexcept = default;
1511 mapping(const mapping&) noexcept = default;
1514 mapping(const extents_type& __extents) noexcept
1515 : _M_extents(__extents)
1516 { __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); }
1518 template<
typename _OExtents>
1519 requires is_constructible_v<extents_type, _OExtents>
1520 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
1521 mapping(
const mapping<_OExtents>& __other) noexcept
1522 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1525 template<
typename _OExtents>
1526 requires (extents_type::rank() <= 1)
1527 && is_constructible_v<extents_type, _OExtents>
1528 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
1529 mapping(
const layout_right::mapping<_OExtents>& __other) noexcept
1530 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1534 template<
typename _OExtents>
1535 requires is_constructible_v<extents_type, _OExtents>
1536 constexpr explicit(!(extents_type::rank() == 0
1537 && is_convertible_v<_OExtents, extents_type>))
1538 mapping(
const layout_stride::mapping<_OExtents>& __other) noexcept
1539 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1540 { __glibcxx_assert(*
this == __other); }
1542#if __glibcxx_padded_layouts
1543 template<
typename _LeftpadMapping>
1544 requires __mdspan::__is_left_padded_mapping<_LeftpadMapping>
1545 && is_constructible_v<extents_type,
1546 typename _LeftpadMapping::extents_type>
1548 explicit(!is_convertible_v<
typename _LeftpadMapping::extents_type,
1550 mapping(
const _LeftpadMapping& __other) noexcept
1551 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1553 constexpr size_t __ostride_sta
1554 = __mdspan::__get_static_stride<_LeftpadMapping>();
1556 if constexpr (extents_type::rank() > 1)
1558 if constexpr (extents_type::static_extent(0) != dynamic_extent
1559 && __ostride_sta != dynamic_extent)
1560 static_assert(extents_type::static_extent(0) == __ostride_sta);
1562 __glibcxx_assert(__other.stride(1)
1563 == __other.extents().extent(0));
1569 operator=(
const mapping&)
noexcept =
default;
1571 constexpr const extents_type&
1572 extents() const noexcept {
return _M_extents; }
1574 constexpr index_type
1575 required_span_size() const noexcept
1576 {
return __mdspan::__size(_M_extents); }
1580 template<__mdspan::__val
id_index_type<index_type>... _Indices>
1581 requires (
sizeof...(_Indices) == extents_type::rank())
1582 constexpr index_type
1583 operator()(_Indices... __indices)
const noexcept
1585 return __mdspan::__linear_index_left(_M_extents,
1586 static_cast<index_type
>(
std::move(__indices))...);
1589 static constexpr bool
1590 is_always_unique() noexcept {
return true; }
1592 static constexpr bool
1593 is_always_exhaustive() noexcept {
return true; }
1595 static constexpr bool
1596 is_always_strided() noexcept {
return true; }
1598 static constexpr bool
1599 is_unique() noexcept {
return true; }
1601 static constexpr bool
1602 is_exhaustive() noexcept {
return true; }
1604 static constexpr bool
1605 is_strided() noexcept {
return true; }
1607 constexpr index_type
1608 stride(rank_type __i)
const noexcept
1609 requires (extents_type::rank() > 0)
1611 __glibcxx_assert(__i < extents_type::rank());
1612 return __mdspan::__fwd_prod(_M_extents, __i);
1615 template<
typename _OExtents>
1616 requires (extents_type::rank() == _OExtents::rank())
1617 friend constexpr bool
1618 operator==(
const mapping& __self,
const mapping<_OExtents>& __other)
1620 {
return __self.extents() == __other.extents(); }
1623 template<
typename _OExtents>
1625 mapping(
const _OExtents& __oexts, __mdspan::__internal_ctor) noexcept
1626 : _M_extents(__oexts)
1628 static_assert(__mdspan::__representable_size<_OExtents, index_type>,
1629 "The size of OtherExtents must be representable as index_type");
1630 __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents));
1633#if __glibcxx_submdspan
1634 template<
typename... _Slices>
1635 requires (extents_type::rank() ==
sizeof...(_Slices))
1636 friend constexpr auto
1637 submdspan_mapping(
const mapping& __mapping, _Slices... __slices)
1638 {
return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
1641 [[no_unique_address]] extents_type _M_extents{};
1646 template<
typename _Extents,
typename... _Indices>
1647 constexpr typename _Extents::index_type
1648 __linear_index_right(
const _Extents& __exts, _Indices... __indices)
1651 using _IndexType =
typename _Extents::index_type;
1652 array<_IndexType,
sizeof...(__indices)> __ind_arr{__indices...};
1653 _IndexType __res = 0;
1654 if constexpr (
sizeof...(__indices) > 0)
1656 _IndexType __mult = 1;
1657 auto __update = [&, __pos = __exts.rank()](_IndexType)
mutable
1660 _GLIBCXX_DEBUG_ASSERT(cmp_less(__ind_arr[__pos],
1661 __exts.extent(__pos)));
1662 __res += __ind_arr[__pos] * __mult;
1663 __mult *= __exts.extent(__pos);
1665 (__update(__indices), ...);
1671 template<
typename _Extents>
1672 class layout_right::mapping
1675 using extents_type = _Extents;
1676 using index_type =
typename extents_type::index_type;
1677 using size_type =
typename extents_type::size_type;
1678 using rank_type =
typename extents_type::rank_type;
1679 using layout_type = layout_right;
1681 static_assert(__mdspan::__representable_size<extents_type, index_type>,
1682 "The size of extents_type must be representable as index_type");
1685 mapping() noexcept = default;
1688 mapping(const mapping&) noexcept = default;
1691 mapping(const extents_type& __extents) noexcept
1692 : _M_extents(__extents)
1693 { __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); }
1695 template<
typename _OExtents>
1696 requires is_constructible_v<extents_type, _OExtents>
1697 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
1698 mapping(
const mapping<_OExtents>& __other) noexcept
1699 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1702 template<
typename _OExtents>
1703 requires (extents_type::rank() <= 1)
1704 && is_constructible_v<extents_type, _OExtents>
1705 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
1706 mapping(
const layout_left::mapping<_OExtents>& __other) noexcept
1707 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1710 template<
typename _OExtents>
1711 requires is_constructible_v<extents_type, _OExtents>
1712 constexpr explicit(!(extents_type::rank() == 0
1713 && is_convertible_v<_OExtents, extents_type>))
1714 mapping(
const layout_stride::mapping<_OExtents>& __other) noexcept
1715 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1716 { __glibcxx_assert(*
this == __other); }
1718#if __glibcxx_padded_layouts
1719 template<
typename _RightPaddedMapping>
1720 requires __mdspan::__is_right_padded_mapping<_RightPaddedMapping>
1721 && is_constructible_v<extents_type,
1722 typename _RightPaddedMapping::extents_type>
1724 explicit(!is_convertible_v<
typename _RightPaddedMapping::extents_type,
1726 mapping(
const _RightPaddedMapping& __other) noexcept
1727 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1729 constexpr size_t __rank = extents_type::rank();
1730 constexpr size_t __ostride_sta
1731 = __mdspan::__get_static_stride<_RightPaddedMapping>();
1733 if constexpr (__rank > 1)
1735 if constexpr (extents_type::static_extent(__rank - 1) != dynamic_extent
1736 && __ostride_sta != dynamic_extent)
1737 static_assert(extents_type::static_extent(__rank - 1)
1740 __glibcxx_assert(__other.stride(__rank - 2)
1741 == __other.extents().extent(__rank - 1));
1747 operator=(
const mapping&)
noexcept =
default;
1749 constexpr const extents_type&
1750 extents() const noexcept {
return _M_extents; }
1752 constexpr index_type
1753 required_span_size() const noexcept
1754 {
return __mdspan::__size(_M_extents); }
1758 template<__mdspan::__val
id_index_type<index_type>... _Indices>
1759 requires (
sizeof...(_Indices) == extents_type::rank())
1760 constexpr index_type
1761 operator()(_Indices... __indices)
const noexcept
1763 return __mdspan::__linear_index_right(
1764 _M_extents,
static_cast<index_type
>(
std::move(__indices))...);
1767 static constexpr bool
1768 is_always_unique() noexcept
1771 static constexpr bool
1772 is_always_exhaustive() noexcept
1775 static constexpr bool
1776 is_always_strided() noexcept
1779 static constexpr bool
1780 is_unique() noexcept
1783 static constexpr bool
1784 is_exhaustive() noexcept
1787 static constexpr bool
1788 is_strided() noexcept
1791 constexpr index_type
1792 stride(rank_type __i)
const noexcept
1793 requires (extents_type::rank() > 0)
1795 __glibcxx_assert(__i < extents_type::rank());
1796 return __mdspan::__rev_prod(_M_extents, __i);
1799 template<
typename _OExtents>
1800 requires (extents_type::rank() == _OExtents::rank())
1801 friend constexpr bool
1802 operator==(
const mapping& __self,
const mapping<_OExtents>& __other)
1804 {
return __self.extents() == __other.extents(); }
1807 template<
typename _OExtents>
1809 mapping(
const _OExtents& __oexts, __mdspan::__internal_ctor) noexcept
1810 : _M_extents(__oexts)
1812 static_assert(__mdspan::__representable_size<_OExtents, index_type>,
1813 "The size of OtherExtents must be representable as index_type");
1814 __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents));
1817#if __glibcxx_submdspan
1818 template<
typename... _Slices>
1819 requires (extents_type::rank() ==
sizeof...(_Slices))
1820 friend constexpr auto
1821 submdspan_mapping(
const mapping& __mapping, _Slices... __slices)
1822 {
return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
1825 [[no_unique_address]] extents_type _M_extents{};
1830 template<
typename _Mp>
1831 concept __mapping_alike =
requires
1833 requires __is_extents<typename _Mp::extents_type>;
1834 { _Mp::is_always_strided() } -> same_as<bool>;
1835 { _Mp::is_always_exhaustive() } -> same_as<bool>;
1836 { _Mp::is_always_unique() } -> same_as<bool>;
1837 bool_constant<_Mp::is_always_strided()>::value;
1838 bool_constant<_Mp::is_always_exhaustive()>::value;
1839 bool_constant<_Mp::is_always_unique()>::value;
1842 template<
typename _Mapping,
typename... _Indices>
1843 constexpr typename _Mapping::index_type
1844 __linear_index_strides(
const _Mapping& __m, _Indices... __indices)
1847 using _IndexType =
typename _Mapping::index_type;
1848 _IndexType __res = 0;
1849 if constexpr (
sizeof...(__indices) > 0)
1851 auto __update = [&, __pos = 0u](_IndexType __idx)
mutable
1853 _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx,
1854 __m.extents().extent(__pos)));
1855 __res += __idx * __m.stride(__pos++);
1857 (__update(__indices), ...);
1863 template<
typename _Extents>
1864 class layout_stride::mapping
1867 using extents_type = _Extents;
1868 using index_type =
typename extents_type::index_type;
1869 using size_type =
typename extents_type::size_type;
1870 using rank_type =
typename extents_type::rank_type;
1871 using layout_type = layout_stride;
1873 static_assert(__mdspan::__representable_size<extents_type, index_type>,
1874 "The size of extents_type must be representable as index_type");
1881 size_t __stride = 1;
1882 for (
size_t __i = extents_type::rank(); __i > 0; --__i)
1884 _M_strides[__i - 1] = index_type(__stride);
1885 __stride *= size_t(_M_extents.extent(__i - 1));
1890 mapping(
const mapping&)
noexcept =
default;
1892 template<
typename _OIndexType>
1893 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
1895 mapping(
const extents_type& __exts,
1896 span<_OIndexType, extents_type::rank()> __strides) noexcept
1897 : _M_extents(__exts)
1899 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
1900 _M_strides[__i] = index_type(as_const(__strides[__i]));
1903 template<
typename _OIndexType>
1904 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
1906 mapping(
const extents_type& __exts,
1907 const array<_OIndexType, extents_type::rank()>& __strides)
1910 span<
const _OIndexType, extents_type::rank()>(__strides))
1913 template<__mdspan::__mapping_alike _Str
idedMapping>
1914 requires (is_constructible_v<extents_type,
1915 typename _StridedMapping::extents_type>
1916 && _StridedMapping::is_always_unique()
1917 && _StridedMapping::is_always_strided())
1918 constexpr explicit(!(
1919 is_convertible_v<typename _StridedMapping::extents_type, extents_type>
1920 && __mdspan::__standardized_mapping<_StridedMapping>))
1921 mapping(
const _StridedMapping& __other) noexcept
1922 : _M_extents(__other.extents())
1924 using _OIndexType = _StridedMapping::index_type;
1925 using _OExtents = _StridedMapping::extents_type;
1927 __glibcxx_assert(__mdspan::__offset(__other) == 0);
1928 static_assert(__mdspan::__representable_size<_OExtents, index_type>,
1929 "The size of StridedMapping::extents_type must be representable as"
1931 if constexpr (cmp_greater(__gnu_cxx::__int_traits<_OIndexType>::__max,
1932 __gnu_cxx::__int_traits<index_type>::__max))
1933 __glibcxx_assert(!cmp_less(
1934 __gnu_cxx::__int_traits<index_type>::__max,
1935 __other.required_span_size())
1936 &&
"other.required_span_size() must be representable"
1938 if constexpr (extents_type::rank() > 0)
1939 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
1940 _M_strides[__i] = index_type(__other.stride(__i));
1944 operator=(
const mapping&)
noexcept =
default;
1946 constexpr const extents_type&
1947 extents() const noexcept {
return _M_extents; }
1949 constexpr array<index_type, extents_type::rank()>
1950 strides() const noexcept
1952 array<index_type, extents_type::rank()> __ret;
1953 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
1954 __ret[__i] = _M_strides[__i];
1958 constexpr index_type
1959 required_span_size() const noexcept
1961 if (__mdspan::__empty(_M_extents))
1964 index_type __ret = 1;
1965 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
1966 __ret += (_M_extents.extent(__i) - 1) * _M_strides[__i];
1972 template<__mdspan::__val
id_index_type<index_type>... _Indices>
1973 requires (
sizeof...(_Indices) == extents_type::rank())
1974 constexpr index_type
1975 operator()(_Indices... __indices)
const noexcept
1977 return __mdspan::__linear_index_strides(*
this,
1978 static_cast<index_type
>(
std::move(__indices))...);
1981 static constexpr bool
1982 is_always_unique() noexcept {
return true; }
1986 static constexpr bool
1987 is_always_exhaustive() noexcept
1989 return (_Extents::rank() == 0) || __mdspan::__contains_zero(
1990 __mdspan::__static_extents<extents_type>());
1993 static constexpr bool
1994 is_always_strided() noexcept {
return true; }
1996 static constexpr bool
1997 is_unique() noexcept {
return true; }
2002 is_exhaustive() const noexcept
2004 if constexpr (!is_always_exhaustive())
2006 auto __size = __mdspan::__size(_M_extents);
2008 return __size == required_span_size();
2013 static constexpr bool
2014 is_strided() noexcept {
return true; }
2016 constexpr index_type
2017 stride(rank_type __r)
const noexcept {
return _M_strides[__r]; }
2019 template<__mdspan::__mapping_alike _OMapping>
2020 requires ((extents_type::rank() == _OMapping::extents_type::rank())
2021 && _OMapping::is_always_strided())
2022 friend constexpr bool
2023 operator==(
const mapping& __self,
const _OMapping& __other)
noexcept
2025 if (__self.extents() != __other.extents())
2027 if constexpr (extents_type::rank() > 0)
2028 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
2029 if (!cmp_equal(__self.stride(__i), __other.stride(__i)))
2031 return __mdspan::__offset(__other) == 0;
2035#if __glibcxx_submdspan
2036 template<
typename... _Slices>
2037 requires (extents_type::rank() ==
sizeof...(_Slices))
2038 friend constexpr auto
2039 submdspan_mapping(
const mapping& __mapping, _Slices... __slices)
2041 if constexpr (
sizeof...(_Slices) == 0)
2042 return submdspan_mapping_result{__mapping, 0};
2045 auto __offset = __mdspan::__suboffset(__mapping, __slices...);
2046 auto __sub_exts = __mdspan::__subextents(__mapping.extents(), __slices...);
2048 = __mdspan::__substrides<decltype(__sub_exts)>(__mapping, __slices...);
2049 return submdspan_mapping_result{
2050 layout_stride::mapping(__sub_exts, __sub_strides), __offset};
2055 using _Strides =
typename __array_traits<index_type,
2056 extents_type::rank()>::_Type;
2057 [[no_unique_address]] extents_type _M_extents;
2058 [[no_unique_address]] _Strides _M_strides;
2061#ifdef __glibcxx_padded_layouts
2065 __least_multiple(
size_t __x,
size_t __y)
2069 return (__y / __x + (__y % __x != 0)) * __x ;
2072 template<
typename _IndexType>
2074 __is_representable_least_multiple(
size_t __x,
size_t __y)
2076 constexpr auto __y_max = __gnu_cxx::__int_traits<_IndexType>::__max;
2077 if(std::cmp_greater(__y, __y_max))
2083 auto __max_delta = __y_max -
static_cast<_IndexType
>(__y);
2084 auto __y_mod_x = __y % __x;
2085 auto __delta = (__y_mod_x == 0) ?
size_t(0) : (__x - __y_mod_x);
2086 return std::cmp_less_equal(__delta, __max_delta);
2089 template<
typename _Extents,
size_t _PaddingValue,
typename _LayoutTraits,
2090 size_t _Rank = _Extents::rank()>
2091 concept __valid_static_stride = (_Extents::rank() <= 1)
2092 || (_PaddingValue == dynamic_extent)
2093 || (_Extents::static_extent(_LayoutTraits::_S_ext_idx) == dynamic_extent)
2094 || (__is_representable_least_multiple<size_t>(
2095 _PaddingValue, _Extents::static_extent(_LayoutTraits::_S_ext_idx)));
2097 template<
size_t _PaddedStride,
typename _Extents,
2098 typename _LayoutTraits>
2100 __is_representable_padded_size()
2102 using _IndexType =
typename _Extents::index_type;
2103 auto __sta_exts = __static_extents<_Extents>(
2104 _LayoutTraits::_S_unpad_begin, _LayoutTraits::_S_unpad_end);
2105 size_t __max = __gnu_cxx::__int_traits<_IndexType>::__max;
2106 return __static_quotient(__sta_exts, __max / _PaddedStride) != 0;
2109 template<
typename _Extents,
size_t _PaddedStride,
typename _LayoutTraits,
2110 size_t _Rank = _Extents::rank()>
2111 concept __valid_padded_size = (_Rank <= 1)
2112 || (_PaddedStride == dynamic_extent)
2113 || (!__all_static(__static_extents<_Extents>()))
2114 || (__contains_zero(__static_extents<_Extents>()))
2115 || (__is_representable_padded_size<_PaddedStride, _Extents,
2118 template<
typename _Extents,
typename _Stride,
typename... _Indices>
2119 constexpr typename _Extents::index_type
2120 __linear_index_leftpad(
const _Extents& __exts, _Stride __stride,
2121 _Indices... __indices)
2124 using _IndexType =
typename _Extents::index_type;
2125 _IndexType __res = 0;
2126 if constexpr (
sizeof...(__indices) > 0)
2128 _IndexType __mult = 1;
2130 auto __update_rest = [&, __pos = 1u](_IndexType __idx)
mutable
2132 __res += __idx * __mult;
2133 __mult *= __exts.extent(__pos);
2137 auto __update = [&](_IndexType __idx,
auto... __rest)
2140 __mult = __stride.extent(0);
2141 (__update_rest(__rest), ...);
2143 __update(__indices...);
2148 template<
typename _Extents,
typename _Stride,
typename... _Indices>
2149 constexpr typename _Extents::index_type
2150 __linear_index_rightpad(
const _Extents& __exts, _Stride __stride,
2151 _Indices... __indices)
2154 using _IndexType =
typename _Extents::index_type;
2155 _IndexType __res = 0;
2156 if constexpr (
sizeof...(__indices) > 0)
2158 _IndexType __mult = 1;
2159 array<_IndexType,
sizeof...(__indices)> __ind_arr{__indices...};
2161 auto __update_rest = [&, __pos = __exts.rank()-1](_IndexType)
mutable
2164 __res += __ind_arr[__pos] * __mult;
2165 __mult *= __exts.extent(__pos);
2168 auto __update = [&](_IndexType,
auto... __rest)
2170 __res += __ind_arr[__exts.rank() - 1];
2171 __mult = __stride.extent(0);
2172 (__update_rest(__rest), ...);
2174 __update(__indices...);
2179 template<
size_t _Rank>
2180 struct _LeftPaddedLayoutTraits
2182 using _LayoutSame = layout_left;
2183 using _LayoutOther = layout_right;
2185 constexpr static const size_t _S_ext_idx = 0;
2186 constexpr static const size_t _S_stride_idx = 1;
2187 constexpr static const size_t _S_unpad_begin = 1;
2188 constexpr static const size_t _S_unpad_end = _Rank;
2190 template<
typename _IndexType,
size_t _StaticStride,
size_t..._Extents>
2191 constexpr static auto
2192 _S_make_padded_extent(
2193 extents<_IndexType, _StaticStride> __stride,
2194 const extents<_IndexType, _Extents...>& __exts)
2196 auto __impl = [&]<
size_t... _Is>(integer_sequence<size_t, _Is...>)
2198 return extents<_IndexType, _StaticStride,
2199 (_Extents...[_Is + 1])...>{
2200 __stride.extent(0), __exts.extent(_Is + 1)...};
2202 return __impl(make_index_sequence<
sizeof...(_Extents) - 1>());
2206 template<
size_t _Rank>
2207 struct _RightPaddedLayoutTraits
2209 using _LayoutSame = layout_right;
2210 using _LayoutOther = layout_left;
2212 constexpr static size_t _S_ext_idx = _Rank - 1;
2213 constexpr static size_t _S_stride_idx = _Rank - 2;
2214 constexpr static size_t _S_unpad_begin = 0;
2215 constexpr static size_t _S_unpad_end = _Rank - 1;
2217 template<
typename _IndexType,
size_t _StaticStride,
size_t..._Extents>
2218 constexpr static auto
2219 _S_make_padded_extent(
2220 extents<_IndexType, _StaticStride> __stride,
2221 const extents<_IndexType, _Extents...>& __exts)
2223 auto __impl = [&]<
size_t... _Is>(integer_sequence<size_t, _Is...>)
2225 return extents<_IndexType, (_Extents...[_Is])..., _StaticStride>{
2226 __exts.extent(_Is)..., __stride.extent(0)};
2228 return __impl(make_index_sequence<
sizeof...(_Extents) - 1>());
2232 template<
size_t _PaddingValue,
typename _Extents,
typename _LayoutTraits>
2233 class _PaddedStorage
2235 using _LayoutSame =
typename _LayoutTraits::_LayoutSame;
2238 using _IndexType =
typename _Extents::index_type;
2239 constexpr static size_t _S_rank = _Extents::rank();
2243 static_assert((_PaddingValue == dynamic_extent)
2244 || (cmp_less_equal(_PaddingValue,
2245 __gnu_cxx::__int_traits<_IndexType>::__max)),
2246 "padding_value must be representable as index_type");
2248 static_assert(__representable_size<_Extents, _IndexType>,
2249 "The size of extents_type must be representable as index_type");
2251 static_assert(__valid_static_stride<_Extents, _PaddingValue,
2253 "The padded stride must be representable as size_t");
2255 static constexpr size_t _S_static_stride = []
consteval
2257 constexpr size_t __rank = _Extents::rank();
2258 if constexpr (__rank <= 1)
2262 constexpr size_t __ext_idx = _LayoutTraits::_S_ext_idx;
2263 constexpr size_t __sta_ext = _Extents::static_extent(__ext_idx);
2264 if constexpr (__sta_ext == 0)
2266 else if constexpr (_PaddingValue == dynamic_extent
2267 || __sta_ext == dynamic_extent)
2268 return dynamic_extent;
2270 return __least_multiple(_PaddingValue, __sta_ext);
2274 static_assert(_S_static_stride == dynamic_extent
2275 || cmp_less_equal(_S_static_stride,
2276 __gnu_cxx::__int_traits<_IndexType>::__max),
2277 "Padded stride must be representable as index_type");
2279 static_assert(__valid_padded_size<_Extents, _S_static_stride,
2283 _PaddedStorage() noexcept
2285 if constexpr (_S_rank > 1)
2286 if constexpr (_S_static_stride == dynamic_extent
2287 && _S_static_padextent() != dynamic_extent)
2288 _M_stride = _Stride{_S_static_padextent()};
2292 _PaddedStorage(
const _Extents& __exts)
2293 : _M_extents(__exts)
2295 if constexpr (!__all_static(__static_extents<_Extents>()))
2296 __glibcxx_assert(__is_representable_extents(_M_extents));
2298 if constexpr (_S_rank > 1)
2300 _IndexType __stride;
2301 if constexpr (_PaddingValue == dynamic_extent)
2302 __stride = _M_padextent();
2303 else if constexpr (_S_static_padextent() != dynamic_extent)
2308 __is_representable_least_multiple<_IndexType>(
2309 _PaddingValue, _M_padextent()));
2311 __stride =
static_cast<_IndexType
>(
2312 __least_multiple(_PaddingValue, _M_padextent()));
2314 __glibcxx_assert(__is_representable_extents(
2315 _LayoutTraits::_S_make_padded_extent(
2316 std::dextents<_IndexType, 1>{__stride},
2319 _M_stride = _Stride{__stride};
2324 _PaddedStorage(
const _Extents& __exts, _IndexType __pad)
2325 : _M_extents(__exts)
2327 if constexpr (_PaddingValue != dynamic_extent)
2328 __glibcxx_assert(cmp_equal(_PaddingValue, __pad));
2329 if constexpr (_S_rank > 1 && _S_static_stride == dynamic_extent)
2332 __is_representable_least_multiple<_IndexType>(
2333 __pad, _M_padextent()));
2335 _M_stride = _Stride{
static_cast<_IndexType
>(
2336 __least_multiple(__pad, _M_padextent()))};
2338 __glibcxx_assert(__is_representable_extents(
2339 _LayoutTraits::_S_make_padded_extent(
2340 _M_stride, _M_extents)));
2344 template<
typename _OExtents>
2347 const typename _LayoutSame::template mapping<_OExtents>& __other)
2348 : _PaddedStorage(_Extents(__other.extents()))
2350 constexpr size_t __stride_idx = _LayoutTraits::_S_stride_idx;
2351 constexpr size_t __ext_idx = _LayoutTraits::_S_ext_idx;
2352 if constexpr (_S_rank > 1 && _PaddingValue != dynamic_extent)
2354 static_assert(_S_static_stride == dynamic_extent
2355 || _OExtents::static_extent(__ext_idx) == dynamic_extent
2356 || _S_static_stride == _OExtents::static_extent(__ext_idx),
2357 "The padded stride must be compatible with other");
2359 if constexpr (_S_static_stride == dynamic_extent
2360 || _OExtents::static_extent(__stride_idx) == dynamic_extent)
2361 __glibcxx_assert(std::cmp_equal(_M_padstride(),
2366 template<
typename _OExtents>
2368 _PaddedStorage(
const typename layout_stride::mapping<_OExtents>&
2370 : _M_extents(__other.extents())
2372 __glibcxx_assert(cmp_less_equal(__other.required_span_size(),
2376 constexpr size_t __stride_idx = _LayoutTraits::_S_stride_idx;
2377 if constexpr (_S_rank > 1)
2379 if constexpr (_PaddingValue != dynamic_extent)
2380 __glibcxx_assert(cmp_equal(__other.stride(__stride_idx),
2381 _M_calc_padstride())
2382 &&
"The padded stride must be compatible with other");
2383 if constexpr (_S_static_stride == dynamic_extent)
2384 _M_stride = _Stride{__other.stride(__stride_idx)};
2388 template<
typename _SamePaddedMapping>
2390 _PaddedStorage(_LayoutTraits::_LayoutSame,
2391 const _SamePaddedMapping& __other)
2392 : _M_extents(__other.extents())
2394 if constexpr (_S_rank > 1)
2396 static_assert(_PaddingValue == dynamic_extent
2397 || _SamePaddedMapping::padding_value == dynamic_extent
2398 || _PaddingValue == _SamePaddedMapping::padding_value,
2399 "If neither PaddingValue is dynamic_extent, then they must "
2402 constexpr size_t __stride_idx = _LayoutTraits::_S_stride_idx;
2403 if constexpr (_PaddingValue != dynamic_extent)
2404 __glibcxx_assert(cmp_equal(__other.stride(__stride_idx),
2405 _M_calc_padstride())
2406 &&
"The padded stride must be compatible with other");
2407 if constexpr (_S_static_stride == dynamic_extent)
2408 _M_stride = _Stride{__other.stride(__stride_idx)};
2410 __glibcxx_assert(cmp_less_equal(__other.required_span_size(),
2411 __gnu_cxx::__int_traits<_IndexType>::__max));
2414 template<
typename _OtherPaddedMapping>
2416 _PaddedStorage(_LayoutTraits::_LayoutOther,
2417 const _OtherPaddedMapping& __other) noexcept
2418 : _M_extents(__other.extents())
2420 __glibcxx_assert(cmp_less_equal(__other.required_span_size(),
2421 __gnu_cxx::__int_traits<_IndexType>::__max));
2424 static constexpr bool
2425 _M_is_always_exhaustive() noexcept
2427 if constexpr (_S_rank <= 1)
2430 return _S_static_padextent() != dynamic_extent
2431 && _S_static_stride != dynamic_extent
2432 && _S_static_padextent() == _S_static_stride;
2436 _M_is_exhaustive() const noexcept
2438 if constexpr (_M_is_always_exhaustive())
2441 return cmp_equal(_M_padextent(), _M_padstride());
2444 constexpr static size_t
2445 _S_static_padextent() noexcept
2446 {
return _Extents::static_extent(_LayoutTraits::_S_ext_idx); }
2448 constexpr _IndexType
2449 _M_padextent() const noexcept
2450 {
return _M_extents.extent(_LayoutTraits::_S_ext_idx); }
2452 constexpr _IndexType
2453 _M_calc_padstride() const noexcept
2455 if constexpr (_S_static_stride != dynamic_extent)
2456 return _S_static_stride;
2457 else if constexpr (_PaddingValue != dynamic_extent)
2458 return __least_multiple(_PaddingValue, _M_padextent());
2460 return _M_padextent();
2463 constexpr _IndexType
2464 _M_padstride() const noexcept
2465 {
return _M_stride.extent(0); }
2467 constexpr _IndexType
2468 _M_required_span_size() const noexcept
2470 if constexpr (_S_rank == 0)
2472 else if (__mdspan::__empty(_M_extents))
2476 size_t __stride =
static_cast<size_t>(_M_padstride());
2477 size_t __prod_rest = __mdspan::__fwd_prod(_M_extents,
2478 _LayoutTraits::_S_unpad_begin, _LayoutTraits::_S_unpad_end);
2479 size_t __delta = _M_padstride() - _M_padextent();
2480 return static_cast<_IndexType
>(__stride * __prod_rest - __delta);
2484 template<
typename _SamePaddedMapping>
2486 _M_equal(
const _SamePaddedMapping& __other)
const noexcept
2488 return _M_extents == __other.extents()
2490 || cmp_equal(_M_stride.extent(0),
2491 __other.stride(_LayoutTraits::_S_stride_idx)));
2494 using _Stride = std::extents<_IndexType, _S_static_stride>;
2495 [[no_unique_address]] _Stride _M_stride;
2496 [[no_unique_address]] _Extents _M_extents;
2500 template<
size_t _PaddingValue>
2501 template<
typename _Extents>
2502 class layout_left_padded<_PaddingValue>::mapping
2505 static constexpr size_t padding_value = _PaddingValue;
2507 using extents_type = _Extents;
2508 using index_type =
typename extents_type::index_type;
2509 using size_type =
typename extents_type::size_type;
2510 using rank_type =
typename extents_type::rank_type;
2511 using layout_type = layout_left_padded<padding_value>;
2514 static constexpr size_t _S_rank = extents_type::rank();
2515 using _PaddedStorage = __mdspan::_PaddedStorage<_PaddingValue,
2516 _Extents, __mdspan::_LeftPaddedLayoutTraits<_S_rank>>;
2517 [[no_unique_address]] _PaddedStorage _M_storage;
2519 consteval friend size_t
2520 __mdspan::__get_static_stride<mapping>();
2522 constexpr index_type
2523 _M_extent(
size_t __r)
const noexcept
2524 {
return _M_storage._M_extents.extent(__r); }
2526 constexpr index_type
2527 _M_padstride() const noexcept
2528 {
return _M_storage._M_stride.extent(0); }
2536 mapping(
const mapping&)
noexcept =
default;
2539 mapping(
const extents_type& __exts)
2540 : _M_storage(__exts)
2543 template<__mdspan::__val
id_index_type<index_type> _OIndexType>
2545 mapping(
const extents_type& __exts, _OIndexType __pad)
2546 : _M_storage(__exts,
2547 __mdspan::__index_type_cast<index_type>(std::move(__pad)))
2550 template<
typename _OExtents>
2551 requires is_constructible_v<extents_type, _OExtents>
2552 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
2553 mapping(
const layout_left::mapping<_OExtents>& __other)
2554 : _M_storage(__other)
2557 template<
typename _OExtents>
2558 requires is_constructible_v<_OExtents, extents_type>
2559 constexpr explicit(!(_OExtents::rank() == 0
2560 && is_convertible_v<_OExtents, extents_type>))
2561 mapping(
const typename layout_stride::mapping<_OExtents>& __other)
2562 : _M_storage(__other)
2563 { __glibcxx_assert(*
this == __other); }
2565 template<
typename _LeftPaddedMapping>
2566 requires __mdspan::__is_left_padded_mapping<_LeftPaddedMapping>
2567 && is_constructible_v<extents_type,
2568 typename _LeftPaddedMapping::extents_type>
2570 !is_convertible_v<
typename _LeftPaddedMapping::extents_type,
2572 || _S_rank > 1 && (padding_value != dynamic_extent
2573 || _LeftPaddedMapping::padding_value == dynamic_extent))
2574 mapping(
const _LeftPaddedMapping& __other)
2575 : _M_storage(layout_left{}, __other)
2578 template<
typename _RightPaddedMapping>
2579 requires (__mdspan::__is_right_padded_mapping<_RightPaddedMapping>
2580 || __mdspan::__mapping_of<layout_right, _RightPaddedMapping>)
2582 && is_constructible_v<extents_type,
2583 typename _RightPaddedMapping::extents_type>
2584 constexpr explicit(!is_convertible_v<
2585 typename _RightPaddedMapping::extents_type, extents_type>)
2586 mapping(
const _RightPaddedMapping& __other) noexcept
2587 : _M_storage(layout_right{}, __other)
2591 operator=(
const mapping&)
noexcept =
default;
2593 constexpr const extents_type&
2594 extents() const noexcept {
return _M_storage._M_extents; }
2596 constexpr array<index_type, _S_rank>
2597 strides() const noexcept
2599 array<index_type, _S_rank> __ret;
2600 if constexpr (_S_rank > 0)
2602 if constexpr (_S_rank > 1)
2603 __ret[1] = _M_padstride();
2604 if constexpr (_S_rank > 2)
2605 for(
size_t __i = 2; __i < _S_rank; ++__i)
2606 __ret[__i] = __ret[__i - 1] * _M_extent(__i - 1);
2610 constexpr index_type
2611 required_span_size() const noexcept
2612 {
return _M_storage._M_required_span_size(); }
2616 template<__mdspan::__val
id_index_type<index_type>... _Indices>
2617 requires (
sizeof...(_Indices) == _S_rank)
2618 constexpr index_type
2619 operator()(_Indices... __indices)
const noexcept
2621 return __mdspan::__linear_index_leftpad(
2622 extents(), _M_storage._M_stride,
2623 static_cast<index_type
>(
std::move(__indices))...);
2626 static constexpr bool
2627 is_always_exhaustive() noexcept
2628 {
return _PaddedStorage::_M_is_always_exhaustive(); }
2631 is_exhaustive() noexcept
2632 {
return _M_storage._M_is_exhaustive(); }
2634 static constexpr bool
2635 is_always_unique() noexcept {
return true; }
2637 static constexpr bool
2638 is_unique() noexcept {
return true; }
2640 static constexpr bool
2641 is_always_strided() noexcept {
return true; }
2643 static constexpr bool
2644 is_strided() noexcept {
return true; }
2646 constexpr index_type
2647 stride(rank_type __r)
const noexcept
2649 __glibcxx_assert(__r < _S_rank);
2653 return static_cast<index_type
>(
2654 static_cast<size_t>(_M_padstride()) *
2655 static_cast<size_t>(__mdspan::__fwd_prod(extents(), 1, __r)));
2658 template<
typename _LeftpadMapping>
2659 requires(__mdspan::__is_left_padded_mapping<_LeftpadMapping>
2660 && _LeftpadMapping::extents_type::rank() == _S_rank)
2661 friend constexpr bool
2662 operator==(
const mapping& __self,
const _LeftpadMapping& __other)
2664 {
return __self._M_storage._M_equal(__other); }
2667#if __glibcxx_submdspan
2668 template<
typename... _Slices>
2669 requires (extents_type::rank() ==
sizeof...(_Slices))
2670 friend constexpr auto
2671 submdspan_mapping(
const mapping& __mapping, _Slices... __slices)
2672 {
return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
2676 template<
size_t _PaddingValue>
2677 template<
typename _Extents>
2678 class layout_right_padded<_PaddingValue>::mapping {
2680 static constexpr size_t padding_value = _PaddingValue;
2681 using extents_type = _Extents;
2682 using index_type =
typename extents_type::index_type;
2683 using size_type =
typename extents_type::size_type;
2684 using rank_type =
typename extents_type::rank_type;
2685 using layout_type = layout_right_padded<_PaddingValue>;
2688 static constexpr size_t _S_rank = extents_type::rank();
2689 using _PaddedStorage = __mdspan::_PaddedStorage<_PaddingValue,
2690 _Extents, __mdspan::_RightPaddedLayoutTraits<_S_rank>>;
2691 [[no_unique_address]] _PaddedStorage _M_storage;
2693 consteval friend size_t
2694 __mdspan::__get_static_stride<mapping>();
2696 constexpr index_type
2697 _M_extent(
size_t __r)
const noexcept
2698 {
return _M_storage._M_extents.extent(__r); }
2700 constexpr index_type
2701 _M_padstride() const noexcept
2702 {
return _M_storage._M_stride.extent(0); }
2710 mapping(
const mapping&)
noexcept =
default;
2713 mapping(
const extents_type& __exts)
2714 : _M_storage(__exts)
2717 template<__mdspan::__val
id_index_type<index_type> _OIndexType>
2719 mapping(
const extents_type& __exts, _OIndexType __pad)
2720 : _M_storage(__exts,
2721 __mdspan::__index_type_cast<index_type>(std::move(__pad)))
2724 template<
typename _OExtents>
2725 requires is_constructible_v<extents_type, _OExtents>
2726 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
2727 mapping(
const layout_right::mapping<_OExtents>& __other)
2728 : _M_storage(__other)
2731 template<
typename _OExtents>
2732 requires is_constructible_v<_OExtents, extents_type>
2733 constexpr explicit(!(_OExtents::rank() == 0
2734 && is_convertible_v<_OExtents, extents_type>))
2735 mapping(
const typename layout_stride::mapping<_OExtents>& __other)
2736 : _M_storage(__other)
2737 { __glibcxx_assert(*
this == __other); }
2739 template<
typename _RightPaddedMapping>
2740 requires __mdspan::__is_right_padded_mapping<_RightPaddedMapping>
2741 && is_constructible_v<extents_type,
2742 typename _RightPaddedMapping::extents_type>
2744 !is_convertible_v<
typename _RightPaddedMapping::extents_type,
2746 || _S_rank > 1 && (padding_value != dynamic_extent
2747 || _RightPaddedMapping::padding_value == dynamic_extent))
2748 mapping(
const _RightPaddedMapping& __other)
2749 : _M_storage(layout_right{}, __other)
2752 template<
typename _LeftPaddedMapping>
2753 requires (__mdspan::__is_left_padded_mapping<_LeftPaddedMapping>
2754 || __mdspan::__mapping_of<layout_left, _LeftPaddedMapping>)
2756 && is_constructible_v<extents_type,
2757 typename _LeftPaddedMapping::extents_type>
2758 constexpr explicit(!is_convertible_v<
2759 typename _LeftPaddedMapping::extents_type, extents_type>)
2760 mapping(
const _LeftPaddedMapping& __other) noexcept
2761 : _M_storage(layout_left{}, __other)
2764 constexpr mapping& operator=(
const mapping&)
noexcept =
default;
2766 constexpr const extents_type&
2767 extents() const noexcept {
return _M_storage._M_extents; }
2769 constexpr array<index_type, _S_rank>
2770 strides() const noexcept
2772 array<index_type, _S_rank> __ret;
2773 if constexpr (_S_rank > 0)
2774 __ret[_S_rank - 1] = 1;
2775 if constexpr (_S_rank > 1)
2776 __ret[_S_rank - 2] = _M_padstride();
2777 if constexpr (_S_rank > 2)
2778 for(
size_t __i = _S_rank - 2; __i > 0; --__i)
2779 __ret[__i - 1] = __ret[__i] * _M_extent(__i);
2783 constexpr index_type
2784 required_span_size() const noexcept
2785 {
return _M_storage._M_required_span_size(); }
2789 template<__mdspan::__val
id_index_type<index_type>... _Indices>
2790 requires (
sizeof...(_Indices) == _S_rank)
2791 constexpr index_type
2792 operator()(_Indices... __indices)
const noexcept
2794 return __mdspan::__linear_index_rightpad(
2795 extents(), _M_storage._M_stride,
2796 static_cast<index_type
>(
std::move(__indices))...);
2799 static constexpr bool
2800 is_always_exhaustive() noexcept
2801 {
return _PaddedStorage::_M_is_always_exhaustive(); }
2804 is_exhaustive() noexcept
2805 {
return _M_storage._M_is_exhaustive(); }
2807 static constexpr bool
2808 is_always_unique() noexcept {
return true; }
2810 static constexpr bool
2811 is_unique() noexcept {
return true; }
2813 static constexpr bool
2814 is_always_strided() noexcept {
return true; }
2816 static constexpr bool
2817 is_strided() noexcept {
return true; }
2819 constexpr index_type
2820 stride(rank_type __r)
const noexcept
2822 __glibcxx_assert(__r < _S_rank);
2823 if constexpr (_S_rank <= 1)
2825 else if (__r == _S_rank - 1)
2827 else if (__r == _S_rank - 2)
2828 return _M_padstride();
2830 return static_cast<index_type
>(
2831 static_cast<size_t>(_M_padstride()) *
2832 static_cast<size_t>(__mdspan::__fwd_prod(
2833 extents(), __r + 1, _S_rank - 1)));
2836 template<
typename _RightPaddedMapping>
2837 requires(__mdspan::__is_right_padded_mapping<_RightPaddedMapping>
2838 && _RightPaddedMapping::extents_type::rank() == _S_rank)
2839 friend constexpr bool
2840 operator==(
const mapping& __self,
const _RightPaddedMapping& __other)
2842 {
return __self._M_storage._M_equal(__other); }
2844#if __glibcxx_submdspan
2846 template<
typename... _Slices>
2847 requires (extents_type::rank() ==
sizeof...(_Slices))
2848 friend constexpr auto
2849 submdspan_mapping(
const mapping& __mapping, _Slices... __slices)
2850 {
return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
2855 template<
typename _ElementType>
2856 struct default_accessor
2858 static_assert(!is_array_v<_ElementType>,
2859 "ElementType must not be an array type");
2860 static_assert(!is_abstract_v<_ElementType>,
2861 "ElementType must not be an abstract class type");
2863 using offset_policy = default_accessor;
2864 using element_type = _ElementType;
2865 using reference = element_type&;
2866 using data_handle_type = element_type*;
2869 default_accessor() noexcept = default;
2871 template<typename _OElementType>
2872 requires is_convertible_v<_OElementType(*)[], element_type(*)[]>
2874 default_accessor(default_accessor<_OElementType>) noexcept
2878 access(data_handle_type __p,
size_t __i)
const noexcept
2879 {
return __p[__i]; }
2881 constexpr data_handle_type
2882 offset(data_handle_type __p,
size_t __i)
const noexcept
2883 {
return __p + __i; }
2886#ifdef __glibcxx_aligned_accessor
2887 template<
typename _ElementType,
size_t _ByteAlignment>
2888 struct aligned_accessor
2890 static_assert(has_single_bit(_ByteAlignment),
2891 "ByteAlignment must be a power of two");
2892 static_assert(_ByteAlignment >=
alignof(_ElementType));
2894 using offset_policy = default_accessor<_ElementType>;
2895 using element_type = _ElementType;
2896 using reference = element_type&;
2897 using data_handle_type = element_type*;
2899 static constexpr size_t byte_alignment = _ByteAlignment;
2902 aligned_accessor() noexcept = default;
2904 template<typename _OElementType,
size_t _OByteAlignment>
2905 requires (_OByteAlignment >= byte_alignment)
2906 && is_convertible_v<_OElementType(*)[], element_type(*)[]>
2908 aligned_accessor(aligned_accessor<_OElementType, _OByteAlignment>)
2912 template<
typename _OElementType>
2913 requires is_convertible_v<_OElementType(*)[], element_type(*)[]>
2915 aligned_accessor(default_accessor<_OElementType>)
noexcept
2918 template<
typename _OElementType>
2919 requires is_convertible_v<element_type(*)[], _OElementType(*)[]>
2921 operator default_accessor<_OElementType>() const noexcept
2925 access(data_handle_type __p,
size_t __i)
const noexcept
2928 constexpr typename offset_policy::data_handle_type
2929 offset(data_handle_type __p,
size_t __i)
const noexcept
2934 template<
typename _ElementType,
typename _Extents,
2935 typename _LayoutPolicy = layout_right,
2936 typename _AccessorPolicy = default_accessor<_ElementType>>
2939 static_assert(!is_array_v<_ElementType>,
2940 "ElementType must not be an array type");
2941 static_assert(!is_abstract_v<_ElementType>,
2942 "ElementType must not be an abstract class type");
2943 static_assert(__mdspan::__is_extents<_Extents>,
2944 "Extents must be a specialization of std::extents");
2945 static_assert(is_same_v<_ElementType,
2946 typename _AccessorPolicy::element_type>);
2949 using extents_type = _Extents;
2950 using layout_type = _LayoutPolicy;
2951 using accessor_type = _AccessorPolicy;
2952 using mapping_type =
typename layout_type::template mapping<extents_type>;
2953 using element_type = _ElementType;
2954 using value_type = remove_cv_t<element_type>;
2955 using index_type =
typename extents_type::index_type;
2956 using size_type =
typename extents_type::size_type;
2957 using rank_type =
typename extents_type::rank_type;
2958 using data_handle_type =
typename accessor_type::data_handle_type;
2959 using reference =
typename accessor_type::reference;
2961 static constexpr rank_type
2962 rank() noexcept {
return extents_type::rank(); }
2964 static constexpr rank_type
2965 rank_dynamic() noexcept {
return extents_type::rank_dynamic(); }
2967 static constexpr size_t
2968 static_extent(rank_type __r)
noexcept
2969 {
return extents_type::static_extent(__r); }
2971 constexpr index_type
2972 extent(rank_type __r)
const noexcept {
return extents().extent(__r); }
2976 requires (rank_dynamic() > 0)
2977 && is_default_constructible_v<data_handle_type>
2978 && is_default_constructible_v<mapping_type>
2979 && is_default_constructible_v<accessor_type> =
default;
2982 mdspan(
const mdspan& __other) =
default;
2985 mdspan(mdspan&& __other) =
default;
2987 template<__mdspan::__val
id_index_type<index_type>... _OIndexTypes>
2988 requires (
sizeof...(_OIndexTypes) == rank()
2989 ||
sizeof...(_OIndexTypes) == rank_dynamic())
2990 && is_constructible_v<mapping_type, extents_type>
2991 && is_default_constructible_v<accessor_type>
2993 mdspan(data_handle_type __handle, _OIndexTypes... __exts)
2995 _M_mapping(_Extents(
static_cast<index_type
>(
std::move(__exts))...)),
2999 template<
typename _OIndexType,
size_t _Nm>
3000 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3001 && (_Nm == rank() || _Nm == rank_dynamic())
3002 && is_constructible_v<mapping_type, extents_type>
3003 && is_default_constructible_v<accessor_type>
3004 constexpr explicit(_Nm != rank_dynamic())
3005 mdspan(data_handle_type __handle, span<_OIndexType, _Nm> __exts)
3006 : _M_accessor(), _M_mapping(extents_type(__exts)),
3007 _M_handle(std::move(__handle))
3010 template<
typename _OIndexType,
size_t _Nm>
3011 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3012 && (_Nm == rank() || _Nm == rank_dynamic())
3013 && is_constructible_v<mapping_type, extents_type>
3014 && is_default_constructible_v<accessor_type>
3015 constexpr explicit(_Nm != rank_dynamic())
3016 mdspan(data_handle_type __handle,
const array<_OIndexType, _Nm>& __exts)
3017 : _M_accessor(), _M_mapping(extents_type(__exts)),
3018 _M_handle(std::move(__handle))
3022 mdspan(data_handle_type __handle,
const extents_type& __exts)
3023 requires is_constructible_v<mapping_type, const extents_type&>
3024 && is_default_constructible_v<accessor_type>
3025 : _M_accessor(), _M_mapping(__exts), _M_handle(
std::move(__handle))
3029 mdspan(data_handle_type __handle,
const mapping_type& __mapping)
3030 requires is_default_constructible_v<accessor_type>
3031 : _M_accessor(), _M_mapping(__mapping), _M_handle(
std::move(__handle))
3035 mdspan(data_handle_type __handle,
const mapping_type& __mapping,
3036 const accessor_type& __accessor)
3037 : _M_accessor(__accessor), _M_mapping(__mapping),
3038 _M_handle(std::move(__handle))
3041 template<
typename _OElementType,
typename _OExtents,
typename _OLayout,
3042 typename _OAccessor>
3043 requires is_constructible_v<mapping_type,
3044 const typename _OLayout::template mapping<_OExtents>&>
3045 && is_constructible_v<accessor_type, const _OAccessor&>
3046 constexpr explicit(!is_convertible_v<
3047 const typename _OLayout::template mapping<_OExtents>&, mapping_type>
3048 || !is_convertible_v<const _OAccessor&, accessor_type>)
3049 mdspan(
const mdspan<_OElementType, _OExtents, _OLayout, _OAccessor>&
3051 : _M_accessor(__other.accessor()), _M_mapping(__other.mapping()),
3052 _M_handle(__other.data_handle())
3054 static_assert(is_constructible_v<data_handle_type,
3055 const typename _OAccessor::data_handle_type&>);
3056 static_assert(is_constructible_v<extents_type, _OExtents>);
3060 operator=(
const mdspan& __other) =
default;
3063 operator=(mdspan&& __other) =
default;
3065 template<__mdspan::__val
id_index_type<index_type>... _OIndexTypes>
3066 requires (
sizeof...(_OIndexTypes) == rank())
3068 operator[](_OIndexTypes... __indices)
const
3070 if constexpr (rank() == 0)
3071 return _M_accessor.access(_M_handle, _M_mapping());
3072 else if constexpr (!(is_same_v<_OIndexTypes, index_type> && ...))
3074 __mdspan::__index_type_cast<index_type>(
std::move(__indices))...);
3077 auto __is_multi_index = [&]<
size_t... _Counts>(
index_sequence<_Counts...>)
3078 {
return ((__indices < extents().extent(_Counts)) && ...); };
3080 __glibcxx_assert(__is_multi_index(make_index_sequence<rank()>()));
3081 return _M_accessor.access(_M_handle, _M_mapping(__indices...));
3085 template<
typename _OIndexType>
3086 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3088 operator[](span<_OIndexType, rank()> __indices)
const
3094 __mdspan::__index_type_cast<index_type>(as_const(__indices[_Counts]))...);
3096 return __call(make_index_sequence<rank()>());
3099 template<
typename _OIndexType>
3100 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3102 operator[](
const array<_OIndexType, rank()>& __indices)
const
3103 {
return operator[](span<
const _OIndexType, rank()>(__indices)); }
3105#if __cplusplus > 202302L
3106 template<__mdspan::__val
id_index_type<index_type>... _OIndexTypes>
3107 requires (
sizeof...(_OIndexTypes) == rank())
3109 at(_OIndexTypes... __indices)
const
3111 if constexpr (rank() == 0)
3112 return _M_accessor.access(_M_handle, _M_mapping());
3113 else if constexpr (!(is_integral_v<_OIndexTypes> && ...))
3114 return at(__index_int_t<_OIndexTypes>(
std::move(__indices))...);
3117 auto __check_bound = [&]<
typename _OIntType>(
size_t __dim, _OIntType __index)
3119 if constexpr (is_signed_v<_OIntType>)
3121 std::__throw_out_of_range_fmt(
3122 __N(
"mdspan::at: %zuth index is negative"), __dim);
3124 const auto __ext = extents().extent(__dim);
3125 if (std::cmp_greater_equal(__index, __ext))
3126 std::__throw_out_of_range_fmt(
3127 __N(
"mdspan::at: %zuth index (which is %zu)"
3128 " >= extent(%zu) (which is %zu)"),
3129 __dim,
size_t(__index), __dim,
size_t(__ext));
3131 auto __check_bounds = [&]<
size_t... _Counts>(
index_sequence<_Counts...>)
3132 { (__check_bound(_Counts, __indices), ...); };
3134 __check_bounds(make_index_sequence<rank()>());
3135 auto __index = _M_mapping(
static_cast<index_type
>(__indices)...);
3136 return _M_accessor.access(_M_handle, __index);
3140 template<
typename _OIndexType>
3141 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3143 at(span<_OIndexType, rank()> __indices)
const
3149 __index_int_t<_OIndexType>(as_const(__indices[_Counts]))...);
3151 return __call(make_index_sequence<rank()>());
3154 template<
typename _OIndexType>
3155 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3157 at(
const array<_OIndexType, rank()>& __indices)
const
3158 {
return at(span<
const _OIndexType, rank()>(__indices)); }
3162 size() const noexcept
3164 __glibcxx_assert(cmp_less_equal(_M_mapping.required_span_size(),
3167 return size_type(__mdspan::__size(extents()));
3172 empty() const noexcept
3173 {
return __mdspan::__empty(extents()); }
3175 friend constexpr void
3176 swap(mdspan& __x, mdspan& __y)
noexcept
3179 swap(__x._M_mapping, __y._M_mapping);
3180 swap(__x._M_accessor, __y._M_accessor);
3181 swap(__x._M_handle, __y._M_handle);
3184 constexpr const extents_type&
3185 extents() const noexcept {
return _M_mapping.extents(); }
3187 constexpr const data_handle_type&
3188 data_handle() const noexcept {
return _M_handle; }
3190 constexpr const mapping_type&
3191 mapping() const noexcept {
return _M_mapping; }
3193 constexpr const accessor_type&
3194 accessor() const noexcept {
return _M_accessor; }
3198 static constexpr bool
3199 is_always_unique() noexcept(noexcept(mapping_type::is_always_unique()))
3200 {
return mapping_type::is_always_unique(); }
3202 static constexpr bool
3203 is_always_exhaustive()
3204 noexcept(noexcept(mapping_type::is_always_exhaustive()))
3205 {
return mapping_type::is_always_exhaustive(); }
3207 static constexpr bool
3209 noexcept(noexcept(mapping_type::is_always_strided()))
3210 {
return mapping_type::is_always_strided(); }
3213 is_unique() const noexcept(noexcept(_M_mapping.is_unique()))
3214 {
return _M_mapping.is_unique(); }
3217 is_exhaustive() const noexcept(noexcept(_M_mapping.is_exhaustive()))
3218 {
return _M_mapping.is_exhaustive(); }
3221 is_strided() const noexcept(noexcept(_M_mapping.is_strided()))
3222 {
return _M_mapping.is_strided(); }
3224 constexpr index_type
3225 stride(rank_type __r)
const {
return _M_mapping.stride(__r); }
3228 template<
typename _OIndexType>
3229 using __index_int_t = std::__conditional_t<
3230 is_integral_v<_OIndexType>, _OIndexType, index_type>;
3232 [[no_unique_address]] accessor_type _M_accessor = accessor_type();
3233 [[no_unique_address]] mapping_type _M_mapping = mapping_type();
3234 [[no_unique_address]] data_handle_type _M_handle = data_handle_type();
3237 template<
typename _CArray>
3238 requires is_array_v<_CArray> && (rank_v<_CArray> == 1)
3240 -> mdspan<remove_all_extents_t<_CArray>,
3241 extents<size_t, extent_v<_CArray, 0>>>;
3243 template<
typename _Po
inter>
3244 requires is_pointer_v<remove_reference_t<_Pointer>>
3246 -> mdspan<remove_pointer_t<remove_reference_t<_Pointer>>, extents<size_t>>;
3248 template<
typename _ElementType,
typename... _Integrals>
3249 requires (is_convertible_v<_Integrals, size_t> && ...)
3250 && (
sizeof...(_Integrals) > 0)
3251 explicit mdspan(_ElementType*, _Integrals...)
3252 -> mdspan<_ElementType,
3253 extents<size_t, __detail::__maybe_static_ext<_Integrals>...>>;
3255 template<
typename _ElementType,
typename _OIndexType,
size_t _Nm>
3256 mdspan(_ElementType*, span<_OIndexType, _Nm>)
3257 -> mdspan<_ElementType, dextents<size_t, _Nm>>;
3259 template<
typename _ElementType,
typename _OIndexType,
size_t _Nm>
3260 mdspan(_ElementType*,
const array<_OIndexType, _Nm>&)
3261 -> mdspan<_ElementType, dextents<size_t, _Nm>>;
3263 template<
typename _ElementType,
typename _IndexType,
size_t... _ExtentsPack>
3264 mdspan(_ElementType*,
const extents<_IndexType, _ExtentsPack...>&)
3265 -> mdspan<_ElementType, extents<_IndexType, _ExtentsPack...>>;
3267 template<
typename _ElementType,
typename _MappingType>
3268 mdspan(_ElementType*,
const _MappingType&)
3269 -> mdspan<_ElementType,
typename _MappingType::extents_type,
3270 typename _MappingType::layout_type>;
3274 template<
typename _MappingType,
typename _AccessorType>
3275 mdspan(
typename _AccessorType::data_handle_type,
const _MappingType&,
3276 const _AccessorType&)
3277 -> mdspan<
typename _AccessorType::element_type,
3278 typename _MappingType::extents_type,
3279 typename _MappingType::layout_type, _AccessorType>;
3281#if __glibcxx_submdspan
3284 template<
typename _IndexType,
typename _Slice>
3286 __canonical_index(_Slice&& __slice)
3288 if constexpr (__detail::__integral_constant_like<_Slice>)
3290 static_assert(__is_representable_integer<_IndexType>(_Slice::value));
3291 static_assert(_Slice::value >= 0);
3292 return std::cw<_IndexType(_Slice::value)>;
3295 return __mdspan::__index_type_cast<_IndexType>(
std::move(__slice));
3298 template<
typename _IndexType,
3299 typename _OffsetType,
typename _SpanType,
typename _StrideType>
3301 __canonical_range_slice(_OffsetType __offset, _SpanType __span,
3302 _StrideType __stride)
3304 if constexpr (is_same_v<_SpanType, constant_wrapper<_IndexType(0)>>
3305 || is_same_v<_StrideType, constant_wrapper<_IndexType(1)>>)
3306 return extent_slice{
3309 .stride = cw<_IndexType(1)>
3311 else if constexpr (__is_constant_wrapper<_StrideType>)
3313 static_assert(_StrideType::value > 0);
3314 if constexpr (__is_constant_wrapper<_SpanType>)
3315 return extent_slice{
3317 .extent = cw<_IndexType(1 + (_SpanType::value - 1) / _StrideType::value)>,
3321 return extent_slice{
3323 .extent = _IndexType(__span > 0 ? 1 + (__span - 1) / _StrideType::value : 0),
3327 else if (__span == 0 || __stride == 1)
3328 return extent_slice{
3330 .extent = _IndexType(__span),
3331 .stride = _IndexType(1)
3335 __glibcxx_assert(__stride > 0);
3336 return extent_slice{
3338 .extent = _IndexType(1 + (__span - 1) / __stride),
3344 template<
typename _IndexType,
typename _Slice>
3346 __slice_cast(_Slice&& __slice)
3348 using _SliceType = remove_cvref_t<_Slice>;
3349 if constexpr (is_convertible_v<_SliceType, full_extent_t>)
3350 return static_cast<full_extent_t
>(
std::move(__slice));
3351 else if constexpr (is_convertible_v<_SliceType, _IndexType>)
3352 return __mdspan::__canonical_index<_IndexType>(
std::move(__slice));
3353 else if constexpr (__is_extent_slice<_SliceType>)
3354 return extent_slice{
3355 .offset = __mdspan::__canonical_index<_IndexType>(
std::move(__slice.offset)),
3356 .extent = __mdspan::__canonical_index<_IndexType>(
std::move(__slice.extent)),
3357 .stride = __mdspan::__canonical_index<_IndexType>(
std::move(__slice.stride))
3359 else if constexpr (__is_range_slice<_SliceType>)
3362 = __mdspan::__canonical_index<_IndexType>(
std::move(__slice.first));
3364 = __mdspan::__canonical_index<_IndexType>(
std::move(__slice.last));
3365 return __mdspan::__canonical_range_slice<_IndexType>(
3367 __mdspan::__canonical_index<_IndexType>(__last - __first),
3368 __mdspan::__canonical_index<_IndexType>(
std::move(__slice.stride)));
3372 auto [__sbegin, __send] =
std::move(__slice);
3374 = __mdspan::__canonical_index<_IndexType>(
std::move(__sbegin));
3376 = __mdspan::__canonical_index<_IndexType>(
std::move(__send));
3378 = __mdspan::__canonical_index<_IndexType>(__cend - __cbegin);
3379 return __mdspan::__canonical_range_slice<_IndexType>(
3380 __cbegin, __cspan, cw<_IndexType(1)>);
3384 template<
typename _IndexType,
size_t _Extent,
typename _OIndexType>
3386 __check_inrange_index(
const extents<_IndexType, _Extent>& __ext,
3387 const _OIndexType& __idx)
3389 if constexpr (__is_constant_wrapper<_OIndexType>
3390 && _Extent != dynamic_extent)
3392 static_assert(_OIndexType::value >= 0);
3393 static_assert(std::cmp_less(_OIndexType::value, _Extent));
3396 __glibcxx_assert(__idx < __ext.extent(0));
3399 template<
typename _IndexType,
size_t _Extent,
typename _OIndexType>
3401 __check_valid_index(
const extents<_IndexType, _Extent>& __ext,
3402 const _OIndexType& __idx)
3404 if constexpr (__is_constant_wrapper<_OIndexType>
3405 && _Extent != dynamic_extent)
3407 static_assert(_OIndexType::value >= 0);
3408 static_assert(std::cmp_less_equal(_OIndexType::value, _Extent));
3411 __glibcxx_assert(__idx <= __ext.extent(0));
3414 template<
typename _IndexType,
size_t _Extent,
typename _Slice>
3416 __check_valid_slice(
const extents<_IndexType, _Extent>& __ext,
3417 const _Slice& __slice)
3419 if constexpr (__is_extent_slice<_Slice>)
3421 __mdspan::__check_valid_index(__ext, __slice.extent);
3426 if constexpr (is_same_v<
typename _Slice::extent_type,
3427 constant_wrapper<_IndexType(0)>>)
3428 __mdspan::__check_valid_index(__ext, __slice.offset);
3429 else if constexpr (is_same_v<
typename _Slice::extent_type,
3430 constant_wrapper<_IndexType(1)>>)
3431 __mdspan::__check_inrange_index(__ext, __slice.offset);
3432 else if constexpr (__is_constant_wrapper<typename _Slice::extent_type>)
3434 __mdspan::__check_inrange_index(__ext, __slice.offset);
3435 if constexpr (__is_constant_wrapper<typename _Slice::stride_type>)
3436 static_assert(_Slice::stride_type::value > 0);
3438 __glibcxx_assert(__slice.stride > 0);
3440 if constexpr (_Extent != dynamic_extent
3441 && __is_constant_wrapper<typename _Slice::offset_type>)
3442 static_assert(std::cmp_greater_equal(
3443 _Extent - _Slice::offset_type::value,
3444 _Slice::extent_type::value));
3445 if constexpr (_Extent != dynamic_extent
3446 && __is_constant_wrapper<typename _Slice::stride_type>)
3447 static_assert(std::cmp_greater(
3449 (_Slice::extent_type::value - 1) * _Slice::stride_type::value));
3451 if constexpr (_Extent != dynamic_extent
3452 && __is_constant_wrapper<typename _Slice::offset_type>
3453 && __is_constant_wrapper<typename _Slice::stride_type>)
3454 static_assert(std::cmp_greater(
3455 _Extent - _Slice::offset_type::value,
3456 (_Slice::extent_type::value - 1) * _Slice::stride_type::value));
3458 __glibcxx_assert(std::cmp_greater(
3459 __ext.extent(0) - __slice.offset,
3460 (_Slice::extent_type::value - 1) * __slice.stride));
3462 else if constexpr (is_same_v<
typename _Slice::stride_type,
3463 constant_wrapper<_IndexType(1)>>)
3465 __mdspan::__check_valid_index(__ext, __slice.offset);
3466 __glibcxx_assert(std::cmp_greater_equal(
3467 __ext.extent(0) - __slice.offset,
3470 else if (__slice.extent == 0)
3471 __mdspan::__check_valid_index(__ext, __slice.offset);
3474 __glibcxx_assert(__slice.offset < __ext.extent(0));
3475 __glibcxx_assert(__slice.extent == 1 || __slice.stride > 0);
3476 __glibcxx_assert(__slice.extent == 1 || std::cmp_greater(
3477 __ext.extent(0) - __slice.offset,
3478 (__slice.extent - 1) * __slice.stride));
3481 else if constexpr (!is_same_v<_Slice, full_extent_t>)
3482 __mdspan::__check_inrange_index(__ext, __slice);
3485 template<
typename _Extents,
typename... _Slices>
3487 __check_valid_slices(
const _Extents& __exts,
const _Slices&... __slices)
3489 constexpr auto __rank = _Extents::rank();
3492 ((__mdspan::__check_valid_slice(__extract_extent<_Is>(__exts),
3493 __slices...[_Is])),...);
3495 __impl(make_index_sequence<__rank>());
3498 template<
typename _Slice>
3499 using __full_extent_t = std::full_extent_t;
3502 void submdspan_mapping() =
delete;
3504 template<
typename _Mapping,
typename... _Slices>
3505 concept __sliceable_mapping =
requires(
const _Mapping __m, _Slices... __slices)
3507 { submdspan_mapping(__m, __slices...) } -> __submdspan_mapping_result;
3510 template<
typename _Mapping,
typename... _Slices>
3512 __submapping(
const _Mapping& __mapping, _Slices... __slices)
3514 __mdspan::__check_valid_slices(__mapping.extents(), __slices...);
3515 return submdspan_mapping(__mapping, __slices...);
3519 template<
typename _IndexType,
size_t... _Extents,
typename... _RawSlices>
3520 requires (
sizeof...(_RawSlices) ==
sizeof...(_Extents))
3522 subextents(
const extents<_IndexType, _Extents...>& __exts,
3523 _RawSlices... __raw_slices)
3525 auto __impl = [&__exts](
auto... __slices)
3527 __mdspan::__check_valid_slices(__exts, __slices...);
3528 return __mdspan::__subextents(__exts, __slices...);
3530 return __impl(__mdspan::__slice_cast<_IndexType>(__raw_slices)...);
3533 template<
typename _IndexType,
size_t... _Extents,
typename... _RawSlices>
3534 requires (
sizeof...(_Extents) ==
sizeof...(_RawSlices))
3536 canonical_slices(
const extents<_IndexType, _Extents...>& __exts,
3537 _RawSlices... __raw_slices)
3539 auto __impl = [&__exts](
auto... __slices)
3541 __mdspan::__check_valid_slices(__exts, __slices...);
3544 return __impl(__mdspan::__slice_cast<_IndexType>(__raw_slices)...);
3547 template<
typename _ElementType,
typename _Extents,
typename _Layout,
3548 typename _Accessor,
typename... _RawSlices>
3549 requires (
sizeof...(_RawSlices) == _Extents::rank()
3550 && __mdspan::__sliceable_mapping<typename _Layout::template mapping<_Extents>,
3551 __mdspan::__full_extent_t<_RawSlices>...>)
3554 const mdspan<_ElementType, _Extents, _Layout, _Accessor>& __md,
3555 _RawSlices... __raw_slices)
3557 using _IndexType =
typename _Extents::index_type;
3558 auto [__mapping, __offset] = __mdspan::__submapping(
3559 __md.mapping(), __mdspan::__slice_cast<_IndexType>(__raw_slices)...);
3561 __md.accessor().offset(__md.data_handle(), __offset),
3563 typename _Accessor::offset_policy(__md.accessor()));
3567_GLIBCXX_END_NAMESPACE_VERSION
constexpr _Tp * assume_aligned(_Tp *__ptr) noexcept
Inform the compiler that a pointer is aligned.
typename make_unsigned< _Tp >::type make_unsigned_t
Alias template for make_unsigned.
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.
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
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>.