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_hardened_mdspan
44#define __glibcxx_want_submdspan
47#if __glibcxx_aligned_accessor
51#if __glibcxx_submdspan
55#if __cplusplus > 202302L
59#ifdef __glibcxx_mdspan
61namespace std _GLIBCXX_VISIBILITY(default)
63_GLIBCXX_BEGIN_NAMESPACE_VERSION
67 __all_static(std::span<const size_t> __extents)
69 for(
auto __ext : __extents)
70 if (__ext == dynamic_extent)
76 __all_dynamic(std::span<const size_t> __extents)
78 for(
auto __ext : __extents)
79 if (__ext != dynamic_extent)
84 template<
typename _IndexType,
typename _OIndexTypeRef>
86 __index_type_cast(_OIndexTypeRef&& __other)
90 using _OIndexType = std::remove_cvref_t<_OIndexTypeRef>;
91 if constexpr (std::is_integral_v<_OIndexType>)
93 constexpr _IndexType __index_type_max
94 = __gnu_cxx::__int_traits<_IndexType>::__max;
95 constexpr _OIndexType __oindex_type_max
96 = __gnu_cxx::__int_traits<_OIndexType>::__max;
98 if constexpr (__index_type_max < __oindex_type_max)
99 __glibcxx_assert(cmp_less_equal(__other, __index_type_max));
101 if constexpr (std::is_signed_v<_OIndexType>)
102 __glibcxx_assert(__other >= 0);
103 return static_cast<_IndexType
>(__other);
110 if constexpr (std::is_signed_v<_IndexType>)
111 __glibcxx_assert(__ret >= 0);
116 template<array _Extents>
120 static constexpr size_t _S_rank = _Extents.size();
128 static constexpr size_t
129 _S_dynamic_index(
size_t __r)
noexcept
130 {
return _S_dynamic_index_data[__r]; }
132 static constexpr auto _S_dynamic_index_data = []
consteval
134 array<size_t, _S_rank+1> __ret;
136 for (
size_t __i = 0; __i < _S_rank; ++__i)
139 __dyn += (_Extents[__i] == dynamic_extent);
141 __ret[_S_rank] = __dyn;
145 static constexpr size_t _S_rank_dynamic = _S_dynamic_index(_S_rank);
149 static constexpr size_t
150 _S_dynamic_index_inv(
size_t __r)
noexcept
151 {
return _S_dynamic_index_inv_data[__r]; }
153 static constexpr auto _S_dynamic_index_inv_data = []
consteval
155 array<size_t, _S_rank_dynamic> __ret;
156 for (
size_t __i = 0, __r = 0; __i < _S_rank; ++__i)
157 if (_Extents[__i] == dynamic_extent)
162 static constexpr size_t
163 _S_static_extent(
size_t __r)
noexcept
164 {
return _Extents[__r]; }
167 template<array _Extents>
168 requires (__all_dynamic<_Extents>())
169 class _StaticExtents<_Extents>
172 static constexpr size_t _S_rank = _Extents.size();
174 static constexpr size_t
175 _S_dynamic_index(
size_t __r)
noexcept
178 static constexpr size_t _S_rank_dynamic = _S_rank;
180 static constexpr size_t
181 _S_dynamic_index_inv(
size_t __k)
noexcept
184 static constexpr size_t
185 _S_static_extent(
size_t)
noexcept
186 {
return dynamic_extent; }
189 template<
typename _IndexType, array _Extents>
190 class _ExtentsStorage :
public _StaticExtents<_Extents>
193 using _Base = _StaticExtents<_Extents>;
196 using _Base::_S_rank;
197 using _Base::_S_rank_dynamic;
198 using _Base::_S_dynamic_index;
199 using _Base::_S_dynamic_index_inv;
200 using _Base::_S_static_extent;
202 static constexpr bool
203 _S_is_dynamic(
size_t __r)
noexcept
205 if constexpr (__all_static(_Extents))
207 else if constexpr (__all_dynamic(_Extents))
210 return _Extents[__r] == dynamic_extent;
213 template<
typename _OIndexType>
214 static constexpr _IndexType
215 _S_int_cast(
const _OIndexType& __other)
noexcept
216 {
return _IndexType(__other); }
219 _M_extent(
size_t __r)
const noexcept
221 if (_S_is_dynamic(__r))
222 return _M_dyn_exts[_S_dynamic_index(__r)];
224 return _S_static_extent(__r);
227 template<
size_t _OtherRank,
typename _GetOtherExtent>
228 static constexpr bool
229 _S_is_compatible_extents(_GetOtherExtent __get_extent)
noexcept
231 if constexpr (_OtherRank == _S_rank)
232 for (
size_t __i = 0; __i < _S_rank; ++__i)
233 if (!_S_is_dynamic(__i)
234 && !cmp_equal(_Extents[__i], _S_int_cast(__get_extent(__i))))
239 template<
size_t _OtherRank,
typename _GetOtherExtent>
241 _M_init_dynamic_extents(_GetOtherExtent __get_extent)
noexcept
243 __glibcxx_assert(_S_is_compatible_extents<_OtherRank>(__get_extent));
244 for (
size_t __i = 0; __i < _S_rank_dynamic; ++__i)
247 if constexpr (_OtherRank != _S_rank_dynamic)
248 __di = _S_dynamic_index_inv(__i);
249 _M_dyn_exts[__i] = _S_int_cast(__get_extent(__di));
254 _ExtentsStorage() noexcept = default;
256 template<typename _OIndexType, array _OExtents>
258 _ExtentsStorage(const _ExtentsStorage<_OIndexType, _OExtents>&
261 _M_init_dynamic_extents<_S_rank>([&__other](
size_t __i)
262 {
return __other._M_extent(__i); });
265 template<
typename _OIndexType,
size_t _Nm>
267 _ExtentsStorage(span<const _OIndexType, _Nm> __exts)
noexcept
269 _M_init_dynamic_extents<_Nm>(
270 [&__exts](
size_t __i) ->
const _OIndexType&
271 {
return __exts[__i]; });
274 static constexpr const array<size_t, _S_rank>&
275 _S_static_extents() noexcept
278 constexpr span<const _IndexType>
279 _M_dynamic_extents(
size_t __begin,
size_t __end)
const noexcept
280 requires (_Extents.size() > 0)
282 return {_M_dyn_exts + _S_dynamic_index(__begin),
283 _S_dynamic_index(__end) - _S_dynamic_index(__begin)};
287 using _Storage = __array_traits<_IndexType, _S_rank_dynamic>::_Type;
288 [[no_unique_address]] _Storage _M_dyn_exts{};
291 template<
typename _OIndexType,
typename _SIndexType>
292 concept __valid_index_type =
293 is_convertible_v<_OIndexType, _SIndexType> &&
294 is_nothrow_constructible_v<_SIndexType, _OIndexType>;
296 template<
size_t _Extent,
typename _IndexType>
298 __valid_static_extent = _Extent == dynamic_extent
299 || _Extent <= __gnu_cxx::__int_traits<_IndexType>::__max;
301 template<
typename _Extents>
302 constexpr const array<size_t, _Extents::rank()>&
303 __static_extents() noexcept
304 {
return _Extents::_Storage::_S_static_extents(); }
306 template<
typename _Extents>
307 constexpr span<const size_t>
308 __static_extents(
size_t __begin,
size_t __end)
noexcept
310 const auto& __sta_exts = __static_extents<_Extents>();
311 return span<const size_t>(__sta_exts.data() + __begin, __end - __begin);
315 template<array _Extents>
316 constexpr auto __fwd_partial_prods = []
consteval
318 constexpr size_t __rank = _Extents.size();
319 std::array<size_t, __rank> __ret;
321 for (
size_t __r = 0; __r < __rank; ++__r)
324 if (
size_t __ext = _Extents[__r]; __ext != dynamic_extent)
331 template<array _Extents>
332 constexpr auto __rev_partial_prods = []
consteval
334 constexpr size_t __rank = _Extents.size();
335 std::array<size_t, __rank> __ret;
337 for (
size_t __r = __rank; __r > 0; --__r)
339 __ret[__r - 1] = __prod;
340 if (
size_t __ext = _Extents[__r - 1]; __ext != dynamic_extent)
346 template<
typename _Extents>
347 constexpr span<const typename _Extents::index_type>
348 __dynamic_extents(
const _Extents& __exts,
size_t __begin = 0,
349 size_t __end = _Extents::rank()) noexcept
350 {
return __exts._M_exts._M_dynamic_extents(__begin, __end); }
353#if __glibcxx_submdspan
356 explicit full_extent_t() =
default;
359 inline constexpr full_extent_t full_extent{};
361 template<
typename _OffsetType,
typename _ExtentType,
typename _Str
ideType>
364 static_assert(__is_signed_or_unsigned_integer<_OffsetType>::value
365 || __detail::__integral_constant_like<_OffsetType>);
366 static_assert(__is_signed_or_unsigned_integer<_ExtentType>::value
367 || __detail::__integral_constant_like<_ExtentType>);
368 static_assert(__is_signed_or_unsigned_integer<_StrideType>::value
369 || __detail::__integral_constant_like<_StrideType>);
371 using offset_type = _OffsetType;
372 using extent_type = _ExtentType;
373 using stride_type = _StrideType;
375 [[no_unique_address]] offset_type offset{};
376 [[no_unique_address]] extent_type extent{};
377 [[no_unique_address]] stride_type stride{};
380 template<
typename _FirstType,
typename _LastType,
typename _Str
ideType = constant_wrapper<1zu>>
383 static_assert(__is_signed_or_unsigned_integer<_FirstType>::value
384 || __detail::__integral_constant_like<_FirstType>);
385 static_assert(__is_signed_or_unsigned_integer<_LastType>::value
386 || __detail::__integral_constant_like<_LastType>);
387 static_assert(__is_signed_or_unsigned_integer<_StrideType>::value
388 || __detail::__integral_constant_like<_StrideType>);
390 [[no_unique_address]] _FirstType first{};
391 [[no_unique_address]] _LastType last{};
392 [[no_unique_address]] _StrideType stride{};
395 template<
typename _Mapping>
396 struct submdspan_mapping_result
398 [[no_unique_address]] _Mapping mapping = _Mapping();
402 template<
typename _Tp>
403 constexpr bool __is_submdspan_mapping_result =
false;
405 template<
typename _Mapping>
406 constexpr bool __is_submdspan_mapping_result<submdspan_mapping_result<_Mapping>> =
true;
408 template<
typename _Mapping>
409 concept __submdspan_mapping_result = __is_submdspan_mapping_result<_Mapping>;
413 template<
typename _IndexType,
size_t... _Extents>
416 static_assert(__is_signed_or_unsigned_integer<_IndexType>::value,
417 "IndexType must be a signed or unsigned integer type");
419 (__mdspan::__valid_static_extent<_Extents, _IndexType> && ...),
420 "Extents must either be dynamic or representable as IndexType");
422 using _Storage = __mdspan::_ExtentsStorage<
423 _IndexType, array<size_t,
sizeof...(_Extents)>{_Extents...}>;
424 [[no_unique_address]] _Storage _M_exts;
427 using index_type = _IndexType;
429 using rank_type = size_t;
431 static constexpr rank_type
432 rank() noexcept {
return _Storage::_S_rank; }
434 static constexpr rank_type
435 rank_dynamic() noexcept {
return _Storage::_S_rank_dynamic; }
437 static constexpr size_t
438 static_extent(rank_type __r)
noexcept
440 __glibcxx_assert(__r < rank());
441 if constexpr (rank() == 0)
444 return _Storage::_S_static_extent(__r);
448 extent(rank_type __r)
const noexcept
450 __glibcxx_assert(__r < rank());
451 if constexpr (rank() == 0)
454 return _M_exts._M_extent(__r);
458 extents() noexcept = default;
461 static consteval
bool
462 _S_is_less_dynamic(
size_t __ext,
size_t __oext)
463 {
return (__ext != dynamic_extent) && (__oext == dynamic_extent); }
465 template<
typename _OIndexType,
size_t... _OExtents>
466 static consteval bool
469 return (_S_is_less_dynamic(_Extents, _OExtents) || ...)
470 || (__gnu_cxx::__int_traits<index_type>::__max
471 < __gnu_cxx::__int_traits<_OIndexType>::__max);
474 template<
size_t... _OExtents>
475 static consteval bool
476 _S_is_compatible_extents()
478 if constexpr (
sizeof...(_OExtents) != rank())
481 return ((_OExtents == dynamic_extent || _Extents == dynamic_extent
482 || _OExtents == _Extents) && ...);
486 template<
typename _OIndexType,
size_t... _OExtents>
487 requires (_S_is_compatible_extents<_OExtents...>())
488 constexpr explicit(_S_ctor_explicit<_OIndexType, _OExtents...>())
489 extents(
const extents<_OIndexType, _OExtents...>& __other) noexcept
490 : _M_exts(__other._M_exts)
493 template<__mdspan::__val
id_index_type<index_type>... _OIndexTypes>
494 requires (
sizeof...(_OIndexTypes) == rank()
495 ||
sizeof...(_OIndexTypes) == rank_dynamic())
496 constexpr explicit extents(_OIndexTypes... __exts) noexcept
497 : _M_exts(span<
const _IndexType,
sizeof...(_OIndexTypes)>(
498 initializer_list{
static_cast<_IndexType
>(
std::move(__exts))...}))
501 template<
typename _OIndexType,
size_t _Nm>
502 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
503 && (_Nm == rank() || _Nm == rank_dynamic())
504 constexpr explicit(_Nm != rank_dynamic())
505 extents(span<_OIndexType, _Nm> __exts) noexcept
506 : _M_exts(span<const _OIndexType, _Nm>(__exts))
509 template<
typename _OIndexType,
size_t _Nm>
510 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
511 && (_Nm == rank() || _Nm == rank_dynamic())
512 constexpr explicit(_Nm != rank_dynamic())
513 extents(
const array<_OIndexType, _Nm>& __exts) noexcept
514 : _M_exts(span<const _OIndexType, _Nm>(__exts))
517 template<
typename _OIndexType,
size_t... _OExtents>
518 friend constexpr bool
519 operator==(
const extents& __self,
520 const extents<_OIndexType, _OExtents...>& __other)
noexcept
522 if constexpr (!_S_is_compatible_extents<_OExtents...>())
526 auto __impl = [&__self, &__other]<
size_t... _Counts>(
528 {
return (cmp_equal(__self.extent(_Counts),
529 __other.extent(_Counts)) && ...); };
535 friend constexpr const array<size_t, rank()>&
536 __mdspan::__static_extents<extents>() noexcept;
538 friend constexpr span<const index_type>
539 __mdspan::__dynamic_extents<extents>(const extents&,
size_t,
size_t)
542 template<typename _OIndexType,
size_t... _OExtents>
543 friend class extents;
548 template<
typename _Tp,
size_t _Nm>
550 __contains_zero(span<_Tp, _Nm> __exts)
noexcept
552 for (
size_t __i = 0; __i < __exts.size(); ++__i)
553 if (__exts[__i] == 0)
558 template<
typename _Tp,
size_t _Nm>
560 __contains_zero(
const array<_Tp, _Nm>& __exts)
noexcept
561 {
return __contains_zero(span<const _Tp>(__exts)); }
563 template<
typename _Extents>
565 __empty(
const _Extents& __exts)
noexcept
567 if constexpr (__contains_zero(__static_extents<_Extents>()))
569 else if constexpr (_Extents::rank_dynamic() > 0)
570 return __contains_zero(__dynamic_extents(__exts));
575 template<
typename _Extents>
576 constexpr typename _Extents::index_type
577 __extents_prod(
const _Extents& __exts,
size_t __sta_prod,
size_t __begin,
578 size_t __end)
noexcept
583 size_t __ret = __sta_prod;
584 if constexpr (_Extents::rank_dynamic() > 0)
585 for (
auto __factor : __dynamic_extents(__exts, __begin, __end))
586 __ret *= size_t(__factor);
587 return static_cast<typename _Extents::index_type
>(__ret);
591 template<
typename _Extents>
592 constexpr typename _Extents::index_type
593 __fwd_prod(
const _Extents& __exts,
size_t __begin,
size_t __end)
noexcept
595 size_t __sta_prod = [__begin, __end] {
596 span<const size_t> __sta_exts
597 = __static_extents<_Extents>(__begin, __end);
599 for(
auto __ext : __sta_exts)
600 if (__ext != dynamic_extent)
604 return __extents_prod(__exts, __sta_prod, __begin, __end);
607 template<
typename _Extents>
608 constexpr typename _Extents::index_type
609 __fwd_prod(
const _Extents& __exts,
size_t __r)
noexcept
611 constexpr size_t __rank = _Extents::rank();
612 constexpr auto& __sta_exts = __static_extents<_Extents>();
613 if constexpr (__rank == 1)
615 else if constexpr (__rank == 2)
616 return __r == 0 ? 1 : __exts.extent(0);
617 else if constexpr (__all_dynamic(std::span(__sta_exts).first(__rank-1)))
618 return __extents_prod(__exts, 1, 0, __r);
621 size_t __sta_prod = __fwd_partial_prods<__sta_exts>[__r];
622 return __extents_prod(__exts, __sta_prod, 0, __r);
626 template<
typename _IndexType,
size_t _Nm>
628 __fwd_prod(span<const _IndexType, _Nm> __values)
630 _IndexType __ret = 1;
631 for(
auto __value : __values)
637 template<
typename _Extents>
638 constexpr typename _Extents::index_type
639 __rev_prod(
const _Extents& __exts,
size_t __r)
noexcept
641 constexpr size_t __rank = _Extents::rank();
642 constexpr auto& __sta_exts = __static_extents<_Extents>();
643 if constexpr (__rank == 1)
645 else if constexpr (__rank == 2)
646 return __r == 0 ? __exts.extent(1) : 1;
647 else if constexpr (__all_dynamic(std::span(__sta_exts).last(__rank-1)))
648 return __extents_prod(__exts, 1, __r + 1, __rank);
651 size_t __sta_prod = __rev_partial_prods<__sta_exts>[__r];
652 return __extents_prod(__exts, __sta_prod, __r + 1, __rank);
656 template<
typename _Extents>
657 constexpr typename _Extents::index_type
658 __size(
const _Extents& __exts)
noexcept
660 constexpr size_t __sta_prod = [] {
661 span<const size_t> __sta_exts = __static_extents<_Extents>();
663 for(
auto __ext : __sta_exts)
664 if (__ext != dynamic_extent)
668 return __extents_prod(__exts, __sta_prod, 0, _Extents::rank());
671 template<
typename _IndexType,
size_t... _Counts>
672 auto __build_dextents_type(integer_sequence<size_t, _Counts...>)
673 -> extents<_IndexType, ((void) _Counts, dynamic_extent)...>;
676 template<
typename _IndexType,
size_t _Rank>
677 using dextents =
decltype(__mdspan::__build_dextents_type<_IndexType>(
680#if __glibcxx_mdspan >= 202406L
681 template<
size_t _Rank,
typename _IndexType =
size_t>
682 using dims = dextents<_IndexType, _Rank>;
685 template<
typename... _Integrals>
686 requires (is_convertible_v<_Integrals, size_t> && ...)
687 explicit extents(_Integrals...) ->
688 extents<size_t, __detail::__maybe_static_ext<_Integrals>...>;
692 template<
typename _Extents>
698 template<
typename _Extents>
704 template<
typename _Extents>
708#ifdef __glibcxx_padded_layouts
709 template<
size_t _PaddingValue>
710 struct layout_left_padded
712 template<
typename _Extents>
716 template<
size_t _PaddingValue>
717 struct layout_right_padded
719 template<
typename _Extents>
726 template<
typename _Tp>
727 constexpr bool __is_extents =
false;
729 template<
typename _IndexType,
size_t... _Extents>
730 constexpr bool __is_extents<extents<_IndexType, _Extents...>> =
true;
732 template<
typename _Extents,
typename... _Indices>
733 constexpr typename _Extents::index_type
734 __linear_index_left(
const _Extents& __exts, _Indices... __indices)
737 using _IndexType =
typename _Extents::index_type;
738 _IndexType __res = 0;
739 if constexpr (
sizeof...(__indices) > 0)
741 _IndexType __mult = 1;
742 auto __update = [&, __pos = 0u](_IndexType __idx)
mutable
744 _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx, __exts.extent(__pos)));
745 __res += __idx * __mult;
746 __mult *= __exts.extent(__pos);
749 (__update(__indices), ...);
754 template<
typename _IndexType>
756 __static_quotient(std::span<const size_t> __sta_exts,
757 _IndexType __nom = __gnu_cxx::__int_traits<_IndexType>::__max)
759 for (
auto __factor : __sta_exts)
761 if (__factor != dynamic_extent)
762 __nom /= _IndexType(__factor);
769 template<
typename _Extents,
770 typename _IndexType =
typename _Extents::index_type>
771 requires __is_extents<_Extents>
773 __static_quotient(_IndexType __nom
774 = __gnu_cxx::__int_traits<_IndexType>::__max)
776 std::span<const size_t> __sta_exts = __static_extents<_Extents>();
777 return __static_quotient<_IndexType>(__sta_exts, __nom);
780 template<
typename _Extents>
782 __is_representable_extents(
const _Extents& __exts)
noexcept
784 using _IndexType = _Extents::index_type;
786 if constexpr (__contains_zero(__static_extents<_Extents>()))
790 constexpr auto __sta_quo = __static_quotient<_Extents>();
791 if constexpr (_Extents::rank_dynamic() == 0)
792 return __sta_quo != 0;
795 auto __dyn_exts = __dynamic_extents(__exts);
796 if (__contains_zero(__dyn_exts))
799 if constexpr (__sta_quo == 0)
803 auto __dyn_quo = _IndexType(__sta_quo);
804 for (
auto __factor : __dyn_exts)
806 __dyn_quo /= __factor;
816 template<
typename _Extents,
typename _IndexType>
817 concept __representable_size = _Extents::rank_dynamic() != 0
818 || __contains_zero(__static_extents<_Extents>())
819 || (__static_quotient<_Extents, _IndexType>() != 0);
821 template<
typename _Layout,
typename _Mapping>
822 concept __mapping_of =
823 is_same_v<
typename _Layout::template mapping<
824 typename _Mapping::extents_type>,
827 template<
template<
size_t>
typename _Layout,
typename _Mapping>
828 concept __padded_mapping_of = __mapping_of<
829 _Layout<_Mapping::padding_value>, _Mapping>;
831#ifdef __glibcxx_padded_layouts
832 template<
typename _Mapping>
833 constexpr bool __is_left_padded_mapping = __padded_mapping_of<
834 layout_left_padded, _Mapping>;
836 template<
typename _Mapping>
837 constexpr bool __is_right_padded_mapping = __padded_mapping_of<
838 layout_right_padded, _Mapping>;
840 template<
typename _Mapping>
841 constexpr bool __is_padded_mapping = __is_left_padded_mapping<_Mapping>
842 || __is_right_padded_mapping<_Mapping>;
845 template<
typename _PaddedMapping>
847 __get_static_stride()
848 {
return _PaddedMapping::_PaddedStorage::_S_static_stride; }
850 template<
typename _Mapping>
851 concept __standardized_mapping = __mapping_of<layout_left, _Mapping>
852 || __mapping_of<layout_right, _Mapping>
853 || __mapping_of<layout_stride, _Mapping>
854#ifdef __glibcxx_padded_layouts
855 || __is_left_padded_mapping<_Mapping>
856 || __is_right_padded_mapping<_Mapping>
861 class __internal_ctor
864 template<
typename _Mapping>
865 constexpr typename _Mapping::index_type
866 __offset(
const _Mapping& __m)
noexcept
868 using _IndexType =
typename _Mapping::index_type;
869 constexpr auto __rank = _Mapping::extents_type::rank();
871 if constexpr (__standardized_mapping<_Mapping>)
873 else if (__empty(__m.extents()))
877 auto __impl = [&__m]<
size_t... _Counts>(
index_sequence<_Counts...>)
878 {
return __m(((
void) _Counts, _IndexType(0))...); };
879 return __impl(make_index_sequence<__rank>());
883#ifdef __glibcxx_submdspan
884 template<
typename _Tp>
885 constexpr bool __is_extent_slice =
false;
887 template<
typename _OffsetType,
typename _ExtentType,
typename _Str
ideType>
888 constexpr bool __is_extent_slice<extent_slice<_OffsetType,
889 _ExtentType, _StrideType>> =
true;
891 template<
typename _Tp>
892 constexpr bool __is_range_slice =
false;
894 template<
typename _FirstType,
typename _LastType,
typename _Str
ideType>
895 constexpr bool __is_range_slice<range_slice<_FirstType,
896 _LastType, _StrideType>> =
true;
898 template<
typename _IndexType,
typename _OIndexType>
900 __is_representable_integer(_OIndexType __value)
902 constexpr auto __min = __gnu_cxx::__int_traits<_IndexType>::__min;
903 constexpr auto __max = __gnu_cxx::__int_traits<_IndexType>::__max;
904 return std::cmp_less_equal(__min, __value)
905 && std::cmp_less_equal(__value, __max);
908 template<
size_t _Index,
typename _Extents>
910 __extract_extent(
const _Extents& __exts)
912 using _IndexType =
typename _Extents::index_type;
913 return extents<_IndexType, _Extents::static_extent(_Index)>{
914 __exts.extent(_Index)};
917 template<
typename _Slice,
typename _IndexType>
918 concept __acceptable_slice_type = same_as<_Slice, full_extent_t>
919 || same_as<_Slice, _IndexType> || __is_constant_wrapper_v<_Slice>
920 || __is_extent_slice<_Slice>;
922 template<
typename _IndexType,
typename... _Slices>
926 return (
static_cast<size_t>(!convertible_to<_Slices, _IndexType>)
930 template<
typename _IndexType,
typename... _Slices>
934 constexpr auto __rank =
sizeof...(_Slices);
935 constexpr auto __sub_rank = __subrank<_IndexType, _Slices...>();
936 auto __map = std::array<size_t, __sub_rank>{};
937 auto __is_int_like = std::array<bool, __rank>{
938 convertible_to<_Slices, _IndexType>...};
941 for (
size_t __k = 0; __k < __rank; ++__k)
942 if (!__is_int_like[__k])
947 template<
typename _Slice>
949 __slice_begin(_Slice __slice)
951 if constexpr (same_as<_Slice, full_extent_t>)
953 else if constexpr (__is_extent_slice<_Slice>)
954 return __slice.offset;
959 template<
typename _Mapping,
typename... _Slices>
961 __suboffset(
const _Mapping& __mapping,
const _Slices&... __slices)
963 using _IndexType =
typename _Mapping::index_type;
964 auto __any_past_the_end = [&]<
size_t... _Is>(
index_sequence<_Is...>)
966 auto __is_past_the_end = [](
const auto& __slice,
const auto& __ext)
968 using _Slice = remove_cvref_t<
decltype(__slice)>;
969 if constexpr (is_convertible_v<_Slice, _IndexType>)
971 else if constexpr (same_as<_Slice, full_extent_t>
972 && __ext.static_extent(0) != 0
973 && __ext.static_extent(0) != dynamic_extent)
976 return __mdspan::__slice_begin(__slice) == __ext.extent(0);
979 const auto& __exts = __mapping.extents();
980 return ((__is_past_the_end(__slices...[_Is],
981 __mdspan::__extract_extent<_Is>(__exts))) || ...);
984 if constexpr ((same_as<_Slices, full_extent_t> && ...))
985 return __mdspan::__offset(__mapping);
988 return __mapping.required_span_size();
989 return __mapping(__mdspan::__slice_begin(__slices)...);
992 template<
typename _IndexType,
size_t _Extent,
typename _Slice>
994 __static_slice_extent()
996 if constexpr (same_as<_Slice, full_extent_t>)
998 else if constexpr (same_as<_Slice, constant_wrapper<_IndexType(0)>>)
1000 else if constexpr (__is_constant_wrapper_v<typename _Slice::extent_type>)
1001 return _Slice::extent_type::value;
1003 return dynamic_extent;
1006 template<
size_t _K,
typename _Extents,
typename _Slice>
1007 constexpr typename _Extents::index_type
1008 __dynamic_slice_extent(
const _Extents& __exts, _Slice __slice)
1010 if constexpr (__is_extent_slice<_Slice>)
1011 return __slice.extent;
1013 return __exts.extent(_K);
1016 template<
typename _IndexType,
size_t... _Extents,
typename... _Slices>
1017 requires (
sizeof...(_Slices) ==
sizeof...(_Extents))
1019 __subextents(
const extents<_IndexType, _Extents...>& __exts,
1020 _Slices... __slices)
1022 constexpr auto __inv_map = __mdspan::__inv_map_rank<_IndexType, _Slices...>();
1025 using _SubExts = extents<_IndexType,
1026 __mdspan::__static_slice_extent<_IndexType,
1027 _Extents...[__inv_map[_Indices]],
1028 _Slices...[__inv_map[_Indices]]>()...>;
1029 if constexpr (_SubExts::rank_dynamic() == 0)
1033 using _StaticSubExtents = __mdspan::_StaticExtents<
1034 __mdspan::__static_extents<_SubExts>()>;
1037 constexpr auto __slice_idx = [__inv_map](
size_t __i)
consteval
1039 return __inv_map[_StaticSubExtents::_S_dynamic_index_inv(__i)];
1042 return _SubExts{__mdspan::__dynamic_slice_extent<__slice_idx(_Is)>(
1043 __exts, __slices...[__slice_idx(_Is)])...};
1045 constexpr auto __dyn_subrank = _SubExts::rank_dynamic();
1053 enum class _LayoutSide
1060 template<
typename _Mapping>
1061 consteval _LayoutSide
1064 if constexpr (__is_left_padded_mapping<_Mapping>
1065 || __mapping_of<layout_left, _Mapping>)
1066 return _LayoutSide::__left;
1067 if constexpr (__is_right_padded_mapping<_Mapping>
1068 || __mapping_of<layout_right, _Mapping>)
1069 return _LayoutSide::__right;
1071 return _LayoutSide::__unknown;
1074 template<_LayoutS
ide _S
ide,
size_t _Rank>
1075 struct _StridesTrait
1077 static constexpr const _LayoutSide _S_side = _Side;
1079 static constexpr size_t
1080 _S_idx(
size_t __k)
noexcept
1082 if constexpr (_Side == _LayoutSide::__left)
1085 return _Rank - 1 - __k;
1090 template<
typename _Mapping>
1091 static constexpr typename _Mapping::index_type
1092 _S_padded_extent(
const _Mapping& __mapping,
size_t __k)
1095 return __mapping.stride(_S_idx(1));
1097 return __mapping.extents().extent(_S_idx(__k));
1100 template<
typename _IndexType,
typename... _Slices>
1101 static consteval auto
1104 static_assert(_Side != _LayoutSide::__unknown);
1107 return __mdspan::__inv_map_rank<_IndexType, _Slices...[_S_idx(_Is)]...>();
1113 template<
typename _SubExts,
typename _Mapping,
typename... _Slices>
1115 __substrides_generic(
const _Mapping& __mapping,
const _Slices&... __slices)
1117 using _IndexType =
typename _Mapping::index_type;
1118 if constexpr (_SubExts::rank() == 0)
1119 return array<_IndexType, _SubExts::rank()>{};
1122 auto __stride = [&__mapping](
size_t __k,
auto __slice) -> _IndexType
1124 if constexpr (__is_extent_slice<
decltype(__slice)>)
1125 if (__slice.extent > 1)
1126 return __mapping.stride(__k) * __slice.stride;
1127 return __mapping.stride(__k);
1132 constexpr auto __inv_map
1133 = __mdspan::__inv_map_rank<_IndexType, _Slices...>();
1134 return array<_IndexType, _SubExts::rank()>{
1135 __stride(__inv_map[_Is], __slices...[__inv_map[_Is]])...};
1141 template<
typename _SubExts,
typename _Mapping,
typename... _Slices>
1143 __substrides_standardized(
const _Mapping& __mapping,
1144 const _Slices&... __slices)
1146 using _IndexType =
typename _Mapping::index_type;
1147 using _Trait = _StridesTrait<__mapping_side<_Mapping>(),
1148 _Mapping::extents_type::rank()>;
1149 using _SubTrait = _StridesTrait<__mapping_side<_Mapping>(), _SubExts::rank()>;
1151 constexpr size_t __sub_rank = _SubExts::rank();
1153 std::array<_IndexType, __sub_rank> __ret;
1154 if constexpr (__sub_rank > 0)
1156 constexpr auto __inv_map
1157 = _Trait::template _S_inv_map<_IndexType, _Slices...>();
1161 size_t __stride = 1;
1162 auto __body = [&](
size_t __k,
auto __slice)
1164 for (
size_t __i = __i0; __i < __inv_map[__k]; ++__i)
1165 __stride *= _Trait::_S_padded_extent(__mapping, __i);
1167 size_t __krev = _SubTrait::_S_idx(__k);
1168 if constexpr (__is_extent_slice<
decltype(__slice)>)
1170 if (__slice.extent > 1)
1171 __ret[__krev] = __stride * __slice.stride;
1173 __ret[__krev] = __stride;
1176 __ret[__krev] = __stride;
1178 __i0 = __inv_map[__k];
1181 ((__body(_Ks, __slices...[_Trait::_S_idx(__inv_map[_Ks])])),...);
1189 template<
typename _SubExts,
typename _Mapping,
typename... _Slices>
1191 __substrides(
const _Mapping& __mapping,
const _Slices&... __slices)
1193 if constexpr (__mdspan::__mapping_side<_Mapping>() == _LayoutSide::__unknown)
1194 return __mdspan::__substrides_generic<_SubExts>(__mapping, __slices...);
1196 return __mdspan::__substrides_standardized<_SubExts>(__mapping, __slices...);
1199 template<
typename _Slice>
1200 concept __is_unit_stride_slice = (__mdspan::__is_extent_slice<_Slice>
1201 && __is_constant_wrapper_v<typename _Slice::stride_type>
1202 && _Slice::stride_type::value == 1)
1203 || std::same_as<_Slice, full_extent_t>;
1209 enum class _SliceKind
1212 __unit_stride_slice,
1217 template<
typename _Slice>
1218 consteval _SliceKind
1221 if constexpr (std::same_as<_Slice, full_extent_t>)
1222 return _SliceKind::__full;
1223 else if constexpr (__mdspan::__is_extent_slice<_Slice>)
1225 if constexpr (__mdspan::__is_unit_stride_slice<_Slice>)
1226 return _SliceKind::__unit_stride_slice;
1228 return _SliceKind::__extent_slice;
1231 return _SliceKind::__collapsing;
1234 template<
typename... _Slices>
1235 consteval array<_SliceKind,
sizeof...(_Slices)>
1236 __make_slice_kind_array()
1238 return array<_SliceKind,
sizeof...(_Slices)>{
1239 __mdspan::__make_slice_kind<_Slices>()...};
1245 __is_block(span<const _SliceKind> __slice_kinds,
size_t __block_size)
1247 if (__block_size == 0)
1250 if (__block_size > __slice_kinds.size())
1253 for (
size_t __i = 0; __i < __block_size - 1; ++__i)
1254 if (__slice_kinds[__i] != _SliceKind::__full)
1257 auto __last = __slice_kinds[__block_size - 1];
1258 return __last == _SliceKind::__full
1259 || __last == _SliceKind::__unit_stride_slice;
1264 static consteval size_t
1265 __padded_block_begin_generic(span<const _SliceKind> __slice_kinds,
1268 if (__slice_kinds[0] != _SliceKind::__full
1269 && __slice_kinds[0] != _SliceKind::__unit_stride_slice)
1270 return dynamic_extent;
1271 else if (__slice_kinds.size() == 1)
1272 return dynamic_extent;
1276 while(__u < __slice_kinds.size()
1277 && __slice_kinds[__u] == _SliceKind::__collapsing)
1280 if (__mdspan::__is_block(__slice_kinds.subspan(__u), __sub_rank -1))
1282 return dynamic_extent;
1286 template<_LayoutS
ide _S
ide,
size_t _Nm>
1287 static consteval size_t
1288 __padded_block_begin(span<const _SliceKind, _Nm> __slice_kinds,
size_t __sub_rank)
1290 if constexpr (_Side == _LayoutSide::__left)
1291 return __mdspan::__padded_block_begin_generic(__slice_kinds, __sub_rank);
1294 std::array<_SliceKind, _Nm> __rev_slices;
1295 for(
size_t __i = 0; __i < _Nm; ++__i)
1296 __rev_slices[__i] = __slice_kinds[_Nm - 1 - __i];
1297 auto __rev_slice_kinds = span<const _SliceKind>(__rev_slices);
1299 auto __u = __mdspan::__padded_block_begin_generic(__rev_slice_kinds,
1301 return __u == dynamic_extent ? dynamic_extent : _Nm - 1 - __u;
1305 template<_LayoutS
ide _S
ide,
bool _Padded>
1306 struct _SubMdspanMapping;
1309 struct _SubMdspanMapping<_LayoutSide::__left, false>
1311 using _Layout = layout_left;
1312 template<
size_t _Pad>
using _PaddedLayout = layout_left_padded<_Pad>;
1314 template<
typename _Mapping,
size_t _Us>
1315 static consteval size_t
1318 using _Extents =
typename _Mapping::extents_type;
1319 constexpr auto __sta_exts = __mdspan::__static_extents<_Extents>(0, _Us);
1320 if constexpr (!__mdspan::__all_static(__sta_exts))
1321 return dynamic_extent;
1323 return __mdspan::__fwd_prod(__sta_exts);
1326 template<
size_t _Nm>
1327 static consteval bool
1328 _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
size_t __sub_rank)
1329 {
return __mdspan::__is_block(__slice_kinds, __sub_rank); }
1333 struct _SubMdspanMapping<_LayoutSide::__left, true>
1335 using _Layout = layout_left;
1336 template<
size_t _Pad>
using _PaddedLayout = layout_left_padded<_Pad>;
1338 template<
typename _Mapping,
size_t _Us>
1339 static consteval size_t
1342 using _Extents =
typename _Mapping::extents_type;
1343 constexpr auto __sta_exts
1344 = __mdspan::__static_extents<_Extents>(1, _Us);
1345 constexpr auto __sta_padstride
1346 = __mdspan::__get_static_stride<_Mapping>();
1347 if constexpr (__sta_padstride == dynamic_extent
1348 || !__mdspan::__all_static(__sta_exts))
1349 return dynamic_extent;
1351 return __sta_padstride * __mdspan::__fwd_prod(__sta_exts);
1354 template<
size_t _Nm>
1355 static consteval bool
1356 _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
1359 if (__sub_rank == 1)
1360 return __slice_kinds[0] == _SliceKind::__unit_stride_slice
1361 || __slice_kinds[0] == _SliceKind::__full;
1368 struct _SubMdspanMapping<_LayoutSide::__right, false>
1370 using _Layout = layout_right;
1371 template<
size_t _Pad>
using _PaddedLayout = layout_right_padded<_Pad>;
1373 template<
typename _Mapping,
size_t _Us>
1374 static consteval size_t
1377 using _Extents =
typename _Mapping::extents_type;
1378 constexpr auto __rank = _Extents::rank();
1379 constexpr auto __sta_exts
1380 = __mdspan::__static_extents<_Extents>(_Us + 1, __rank);
1381 if constexpr (!__mdspan::__all_static(__sta_exts))
1382 return dynamic_extent;
1384 return __fwd_prod(__sta_exts);
1387 template<
size_t _Nm>
1388 static consteval bool
1389 _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
1392 auto __rev_slice_kinds = array<_SliceKind, _Nm>{};
1393 for(
size_t __i = 0; __i < _Nm; ++__i)
1394 __rev_slice_kinds[__i] = __slice_kinds[_Nm - 1 - __i];
1395 return __mdspan::__is_block(span(__rev_slice_kinds), __sub_rank);
1400 struct _SubMdspanMapping<_LayoutSide::__right, true>
1402 using _Layout = layout_right;
1403 template<
size_t _Pad>
using _PaddedLayout = layout_right_padded<_Pad>;
1405 template<
typename _Mapping,
size_t _Us>
1406 static consteval size_t
1409 using _Extents =
typename _Mapping::extents_type;
1410 constexpr auto __rank = _Extents::rank();
1411 constexpr auto __sta_exts
1412 = __mdspan::__static_extents<_Extents>(_Us + 1, __rank - 1);
1413 constexpr auto __sta_padstride
1414 = __mdspan::__get_static_stride<_Mapping>();
1415 if constexpr (__sta_padstride == dynamic_extent
1416 || !__mdspan::__all_static(__sta_exts))
1417 return dynamic_extent;
1419 return __sta_padstride * __mdspan::__fwd_prod(__sta_exts);
1422 template<
size_t _Nm>
1423 static consteval bool
1424 _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
1427 if (__sub_rank == 1)
1428 return __slice_kinds[_Nm - 1] == _SliceKind::__unit_stride_slice
1429 || __slice_kinds[_Nm - 1] == _SliceKind::__full;
1436 template<
typename _Mapping>
1438 __submdspan_mapping_impl(
const _Mapping& __mapping)
1439 {
return submdspan_mapping_result{__mapping, 0}; }
1441 template<
typename _Mapping,
typename... _Slices>
1442 requires (
sizeof...(_Slices) > 0)
1444 __submdspan_mapping_impl(
const _Mapping& __mapping, _Slices... __slices)
1446 using _IndexType =
typename _Mapping::index_type;
1447 static_assert((__acceptable_slice_type<_Slices, _IndexType> && ...));
1449 constexpr auto __side = __mdspan::__mapping_side<_Mapping>();
1450 constexpr auto __rank =
sizeof...(_Slices);
1451 using _Trait = _SubMdspanMapping<__side, __is_padded_mapping<_Mapping>>;
1452 using _SliceView = span<const _SliceKind, __rank>;
1454 constexpr auto __slice_kinds = __mdspan::__make_slice_kind_array<_Slices...>();
1455 auto __offset = __mdspan::__suboffset(__mapping, __slices...);
1456 auto __sub_exts = __mdspan::__subextents(__mapping.extents(), __slices...);
1457 using _SubExts =
decltype(__sub_exts);
1458 constexpr auto __sub_rank = _SubExts::rank();
1459 if constexpr (__sub_rank == 0)
1460 return submdspan_mapping_result{
1461 typename _Trait::_Layout::mapping(__sub_exts), __offset};
1462 else if constexpr (_Trait::_S_is_unpadded_submdspan(
1463 _SliceView(__slice_kinds), __sub_rank))
1464 return submdspan_mapping_result{
1465 typename _Trait::_Layout::mapping(__sub_exts), __offset};
1467 constexpr auto __u = __padded_block_begin<__side>(
1468 _SliceView(__slice_kinds), __sub_rank);
1469 __u != dynamic_extent)
1471 constexpr auto __pad = _Trait::template _S_pad<_Mapping, __u>();
1472 using _Layout =
typename _Trait::template _PaddedLayout<__pad>;
1473 return submdspan_mapping_result{
1474 typename _Layout::mapping(__sub_exts, __mapping.stride(__u)),
1480 = __mdspan::__substrides<_SubExts>(__mapping, __slices...);
1481 return submdspan_mapping_result{
1482 layout_stride::mapping(__sub_exts, __sub_strides), __offset};
1488 template<
typename _Extents>
1489 class layout_left::mapping
1492 using extents_type = _Extents;
1493 using index_type =
typename extents_type::index_type;
1494 using size_type =
typename extents_type::size_type;
1495 using rank_type =
typename extents_type::rank_type;
1496 using layout_type = layout_left;
1498 static_assert(__mdspan::__representable_size<extents_type, index_type>,
1499 "The size of extents_type must be representable as index_type");
1502 mapping() noexcept = default;
1505 mapping(const mapping&) noexcept = default;
1508 mapping(const extents_type& __extents) noexcept
1509 : _M_extents(__extents)
1510 { __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); }
1512 template<
typename _OExtents>
1513 requires is_constructible_v<extents_type, _OExtents>
1514 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
1515 mapping(
const mapping<_OExtents>& __other) noexcept
1516 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1519 template<
typename _OExtents>
1520 requires (extents_type::rank() <= 1)
1521 && is_constructible_v<extents_type, _OExtents>
1522 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
1523 mapping(
const layout_right::mapping<_OExtents>& __other) noexcept
1524 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1528 template<
typename _OExtents>
1529 requires is_constructible_v<extents_type, _OExtents>
1530 constexpr explicit(!(extents_type::rank() == 0
1531 && is_convertible_v<_OExtents, extents_type>))
1532 mapping(
const layout_stride::mapping<_OExtents>& __other) noexcept
1533 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1534 { __glibcxx_assert(*
this == __other); }
1536#if __glibcxx_padded_layouts
1537 template<
typename _LeftpadMapping>
1538 requires __mdspan::__is_left_padded_mapping<_LeftpadMapping>
1539 && is_constructible_v<extents_type,
1540 typename _LeftpadMapping::extents_type>
1542 explicit(!is_convertible_v<
typename _LeftpadMapping::extents_type,
1544 mapping(
const _LeftpadMapping& __other) noexcept
1545 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1547 constexpr size_t __ostride_sta
1548 = __mdspan::__get_static_stride<_LeftpadMapping>();
1550 if constexpr (extents_type::rank() > 1)
1552 if constexpr (extents_type::static_extent(0) != dynamic_extent
1553 && __ostride_sta != dynamic_extent)
1554 static_assert(extents_type::static_extent(0) == __ostride_sta);
1556 __glibcxx_assert(__other.stride(1)
1557 == __other.extents().extent(0));
1563 operator=(
const mapping&)
noexcept =
default;
1565 constexpr const extents_type&
1566 extents() const noexcept {
return _M_extents; }
1568 constexpr index_type
1569 required_span_size() const noexcept
1570 {
return __mdspan::__size(_M_extents); }
1574 template<__mdspan::__val
id_index_type<index_type>... _Indices>
1575 requires (
sizeof...(_Indices) == extents_type::rank())
1576 constexpr index_type
1577 operator()(_Indices... __indices)
const noexcept
1579 return __mdspan::__linear_index_left(_M_extents,
1580 static_cast<index_type
>(
std::move(__indices))...);
1583 static constexpr bool
1584 is_always_unique() noexcept {
return true; }
1586 static constexpr bool
1587 is_always_exhaustive() noexcept {
return true; }
1589 static constexpr bool
1590 is_always_strided() noexcept {
return true; }
1592 static constexpr bool
1593 is_unique() noexcept {
return true; }
1595 static constexpr bool
1596 is_exhaustive() noexcept {
return true; }
1598 static constexpr bool
1599 is_strided() noexcept {
return true; }
1601 constexpr index_type
1602 stride(rank_type __i)
const noexcept
1603 requires (extents_type::rank() > 0)
1605 __glibcxx_assert(__i < extents_type::rank());
1606 return __mdspan::__fwd_prod(_M_extents, __i);
1609 template<
typename _OExtents>
1610 requires (extents_type::rank() == _OExtents::rank())
1611 friend constexpr bool
1612 operator==(
const mapping& __self,
const mapping<_OExtents>& __other)
1614 {
return __self.extents() == __other.extents(); }
1617 template<
typename _OExtents>
1619 mapping(
const _OExtents& __oexts, __mdspan::__internal_ctor) noexcept
1620 : _M_extents(__oexts)
1622 static_assert(__mdspan::__representable_size<_OExtents, index_type>,
1623 "The size of OtherExtents must be representable as index_type");
1624 __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents));
1627#if __glibcxx_submdspan
1628 template<
typename... _Slices>
1629 requires (extents_type::rank() ==
sizeof...(_Slices))
1630 friend constexpr auto
1631 submdspan_mapping(
const mapping& __mapping, _Slices... __slices)
1632 {
return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
1635 [[no_unique_address]] extents_type _M_extents{};
1640 template<
typename _Extents,
typename... _Indices>
1641 constexpr typename _Extents::index_type
1642 __linear_index_right(
const _Extents& __exts, _Indices... __indices)
1645 using _IndexType =
typename _Extents::index_type;
1646 array<_IndexType,
sizeof...(__indices)> __ind_arr{__indices...};
1647 _IndexType __res = 0;
1648 if constexpr (
sizeof...(__indices) > 0)
1650 _IndexType __mult = 1;
1651 auto __update = [&, __pos = __exts.rank()](_IndexType)
mutable
1654 _GLIBCXX_DEBUG_ASSERT(cmp_less(__ind_arr[__pos],
1655 __exts.extent(__pos)));
1656 __res += __ind_arr[__pos] * __mult;
1657 __mult *= __exts.extent(__pos);
1659 (__update(__indices), ...);
1665 template<
typename _Extents>
1666 class layout_right::mapping
1669 using extents_type = _Extents;
1670 using index_type =
typename extents_type::index_type;
1671 using size_type =
typename extents_type::size_type;
1672 using rank_type =
typename extents_type::rank_type;
1673 using layout_type = layout_right;
1675 static_assert(__mdspan::__representable_size<extents_type, index_type>,
1676 "The size of extents_type must be representable as index_type");
1679 mapping() noexcept = default;
1682 mapping(const mapping&) noexcept = default;
1685 mapping(const extents_type& __extents) noexcept
1686 : _M_extents(__extents)
1687 { __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); }
1689 template<
typename _OExtents>
1690 requires is_constructible_v<extents_type, _OExtents>
1691 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
1692 mapping(
const mapping<_OExtents>& __other) noexcept
1693 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1696 template<
typename _OExtents>
1697 requires (extents_type::rank() <= 1)
1698 && is_constructible_v<extents_type, _OExtents>
1699 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
1700 mapping(
const layout_left::mapping<_OExtents>& __other) noexcept
1701 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1704 template<
typename _OExtents>
1705 requires is_constructible_v<extents_type, _OExtents>
1706 constexpr explicit(!(extents_type::rank() == 0
1707 && is_convertible_v<_OExtents, extents_type>))
1708 mapping(
const layout_stride::mapping<_OExtents>& __other) noexcept
1709 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1710 { __glibcxx_assert(*
this == __other); }
1712#if __glibcxx_padded_layouts
1713 template<
typename _RightPaddedMapping>
1714 requires __mdspan::__is_right_padded_mapping<_RightPaddedMapping>
1715 && is_constructible_v<extents_type,
1716 typename _RightPaddedMapping::extents_type>
1718 explicit(!is_convertible_v<
typename _RightPaddedMapping::extents_type,
1720 mapping(
const _RightPaddedMapping& __other) noexcept
1721 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1723 constexpr size_t __rank = extents_type::rank();
1724 constexpr size_t __ostride_sta
1725 = __mdspan::__get_static_stride<_RightPaddedMapping>();
1727 if constexpr (__rank > 1)
1729 if constexpr (extents_type::static_extent(__rank - 1) != dynamic_extent
1730 && __ostride_sta != dynamic_extent)
1731 static_assert(extents_type::static_extent(__rank - 1)
1734 __glibcxx_assert(__other.stride(__rank - 2)
1735 == __other.extents().extent(__rank - 1));
1741 operator=(
const mapping&)
noexcept =
default;
1743 constexpr const extents_type&
1744 extents() const noexcept {
return _M_extents; }
1746 constexpr index_type
1747 required_span_size() const noexcept
1748 {
return __mdspan::__size(_M_extents); }
1752 template<__mdspan::__val
id_index_type<index_type>... _Indices>
1753 requires (
sizeof...(_Indices) == extents_type::rank())
1754 constexpr index_type
1755 operator()(_Indices... __indices)
const noexcept
1757 return __mdspan::__linear_index_right(
1758 _M_extents,
static_cast<index_type
>(
std::move(__indices))...);
1761 static constexpr bool
1762 is_always_unique() noexcept
1765 static constexpr bool
1766 is_always_exhaustive() noexcept
1769 static constexpr bool
1770 is_always_strided() noexcept
1773 static constexpr bool
1774 is_unique() noexcept
1777 static constexpr bool
1778 is_exhaustive() noexcept
1781 static constexpr bool
1782 is_strided() noexcept
1785 constexpr index_type
1786 stride(rank_type __i)
const noexcept
1787 requires (extents_type::rank() > 0)
1789 __glibcxx_assert(__i < extents_type::rank());
1790 return __mdspan::__rev_prod(_M_extents, __i);
1793 template<
typename _OExtents>
1794 requires (extents_type::rank() == _OExtents::rank())
1795 friend constexpr bool
1796 operator==(
const mapping& __self,
const mapping<_OExtents>& __other)
1798 {
return __self.extents() == __other.extents(); }
1801 template<
typename _OExtents>
1803 mapping(
const _OExtents& __oexts, __mdspan::__internal_ctor) noexcept
1804 : _M_extents(__oexts)
1806 static_assert(__mdspan::__representable_size<_OExtents, index_type>,
1807 "The size of OtherExtents must be representable as index_type");
1808 __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents));
1811#if __glibcxx_submdspan
1812 template<
typename... _Slices>
1813 requires (extents_type::rank() ==
sizeof...(_Slices))
1814 friend constexpr auto
1815 submdspan_mapping(
const mapping& __mapping, _Slices... __slices)
1816 {
return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
1819 [[no_unique_address]] extents_type _M_extents{};
1824 template<
typename _Mp>
1825 concept __mapping_alike =
requires
1827 requires __is_extents<typename _Mp::extents_type>;
1828 { _Mp::is_always_strided() } -> same_as<bool>;
1829 { _Mp::is_always_exhaustive() } -> same_as<bool>;
1830 { _Mp::is_always_unique() } -> same_as<bool>;
1831 bool_constant<_Mp::is_always_strided()>::value;
1832 bool_constant<_Mp::is_always_exhaustive()>::value;
1833 bool_constant<_Mp::is_always_unique()>::value;
1836 template<
typename _Mapping,
typename... _Indices>
1837 constexpr typename _Mapping::index_type
1838 __linear_index_strides(
const _Mapping& __m, _Indices... __indices)
1841 using _IndexType =
typename _Mapping::index_type;
1842 _IndexType __res = 0;
1843 if constexpr (
sizeof...(__indices) > 0)
1845 auto __update = [&, __pos = 0u](_IndexType __idx)
mutable
1847 _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx,
1848 __m.extents().extent(__pos)));
1849 __res += __idx * __m.stride(__pos++);
1851 (__update(__indices), ...);
1857 template<
typename _Extents>
1858 class layout_stride::mapping
1861 using extents_type = _Extents;
1862 using index_type =
typename extents_type::index_type;
1863 using size_type =
typename extents_type::size_type;
1864 using rank_type =
typename extents_type::rank_type;
1865 using layout_type = layout_stride;
1867 static_assert(__mdspan::__representable_size<extents_type, index_type>,
1868 "The size of extents_type must be representable as index_type");
1875 size_t __stride = 1;
1876 for (
size_t __i = extents_type::rank(); __i > 0; --__i)
1878 _M_strides[__i - 1] = index_type(__stride);
1879 __stride *= size_t(_M_extents.extent(__i - 1));
1884 mapping(
const mapping&)
noexcept =
default;
1886 template<
typename _OIndexType>
1887 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
1889 mapping(
const extents_type& __exts,
1890 span<_OIndexType, extents_type::rank()> __strides) noexcept
1891 : _M_extents(__exts)
1893 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
1895 __mdspan::__index_type_cast<index_type>(as_const(__strides[__i]));
1897 __glibcxx_assert(_M_check_unique());
1900 template<
typename _OIndexType>
1901 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
1903 mapping(
const extents_type& __exts,
1904 const array<_OIndexType, extents_type::rank()>& __strides)
1907 span<
const _OIndexType, extents_type::rank()>(__strides))
1910 template<__mdspan::__mapping_alike _Str
idedMapping>
1911 requires (is_constructible_v<extents_type,
1912 typename _StridedMapping::extents_type>
1913 && _StridedMapping::is_always_unique()
1914 && _StridedMapping::is_always_strided())
1915 constexpr explicit(!(
1916 is_convertible_v<typename _StridedMapping::extents_type, extents_type>
1917 && __mdspan::__standardized_mapping<_StridedMapping>))
1918 mapping(
const _StridedMapping& __other) noexcept
1919 : _M_extents(__other.extents())
1921 using _OIndexType = _StridedMapping::index_type;
1922 using _OExtents = _StridedMapping::extents_type;
1924 __glibcxx_assert(__mdspan::__offset(__other) == 0);
1925 static_assert(__mdspan::__representable_size<_OExtents, index_type>,
1926 "The size of StridedMapping::extents_type must be representable as"
1928 if constexpr (cmp_greater(__gnu_cxx::__int_traits<_OIndexType>::__max,
1929 __gnu_cxx::__int_traits<index_type>::__max))
1930 __glibcxx_assert(!cmp_less(
1931 __gnu_cxx::__int_traits<index_type>::__max,
1932 __other.required_span_size())
1933 &&
"other.required_span_size() must be representable"
1935 if constexpr (extents_type::rank() > 0)
1936 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
1937 _M_strides[__i] = index_type(__other.stride(__i));
1941 operator=(
const mapping&)
noexcept =
default;
1943 constexpr const extents_type&
1944 extents() const noexcept {
return _M_extents; }
1946 constexpr array<index_type, extents_type::rank()>
1947 strides() const noexcept
1949 array<index_type, extents_type::rank()> __ret;
1950 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
1951 __ret[__i] = _M_strides[__i];
1955 constexpr index_type
1956 required_span_size() const noexcept
1958 if (__mdspan::__empty(_M_extents))
1961 index_type __ret = 1;
1962 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
1963 __ret += (_M_extents.extent(__i) - 1) * _M_strides[__i];
1969 template<__mdspan::__val
id_index_type<index_type>... _Indices>
1970 requires (
sizeof...(_Indices) == extents_type::rank())
1971 constexpr index_type
1972 operator()(_Indices... __indices)
const noexcept
1974 return __mdspan::__linear_index_strides(*
this,
1975 static_cast<index_type
>(
std::move(__indices))...);
1978 static constexpr bool
1979 is_always_unique() noexcept {
return true; }
1983 static constexpr bool
1984 is_always_exhaustive() noexcept
1986 return (_Extents::rank() == 0) || __mdspan::__contains_zero(
1987 __mdspan::__static_extents<extents_type>());
1990 static constexpr bool
1991 is_always_strided() noexcept {
return true; }
1993 static constexpr bool
1994 is_unique() noexcept {
return true; }
1999 is_exhaustive() const noexcept
2001 if constexpr (!is_always_exhaustive())
2003 auto __size = __mdspan::__size(_M_extents);
2005 return __size == required_span_size();
2010 static constexpr bool
2011 is_strided() noexcept {
return true; }
2013 constexpr index_type
2014 stride(rank_type __r)
const noexcept {
return _M_strides[__r]; }
2016 template<__mdspan::__mapping_alike _OMapping>
2017 requires ((extents_type::rank() == _OMapping::extents_type::rank())
2018 && _OMapping::is_always_strided())
2019 friend constexpr bool
2020 operator==(
const mapping& __self,
const _OMapping& __other)
noexcept
2022 if (__self.extents() != __other.extents())
2024 if constexpr (extents_type::rank() > 0)
2025 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
2026 if (!cmp_equal(__self.stride(__i), __other.stride(__i)))
2028 return __mdspan::__offset(__other) == 0;
2032 using _Strides =
typename __array_traits<index_type,
2033 extents_type::rank()>::_Type;
2036 _M_check_unique()
const
2038 constexpr size_t __rank = extents_type::rank();
2039 if constexpr (__rank == 0)
2043 else if (__mdspan::__empty(_M_extents))
2045 else if constexpr (__rank == 1)
2046 return _M_strides[0] > 0;
2047 else if (__mdspan::__contains_zero<const index_type, __rank>(_M_strides))
2049 else if constexpr (__rank == 2)
2050 return (_M_strides[1] >= _M_strides[0] * _M_extents.extent(0))
2051 || (_M_strides[0] >= _M_strides[1] * _M_extents.extent(1));
2057 if (required_span_size() < __mdspan::__size(_M_extents))
2062#ifdef _GLIBCXX_DEBUG
2063 size_t __perm[__rank];
2064 for (
size_t __i = 0; __i < __rank; ++__i)
2067 auto __popmin = [&](
size_t __from)
2069 size_t __min = __perm[__rank - 1];
2070 for (
size_t __i = __rank - 1; __i > __from; --__i)
2072 const size_t __cur = __perm[__i - 1];
2073 const auto __res = _M_strides[__cur] <=> _M_strides[__min];
2075 if (__res < 0 || (__res == 0 && _M_extents.extent(__cur) == 1))
2077 __perm[__i] = __min;
2081 __perm[__i] = __cur;
2083 __perm[__from] = __min;
2088 size_t __prev = __popmin(0);
2089 for (
size_t __i = 1; __i < __rank; ++__i)
2091 const size_t __next = __popmin(__i);
2092 if (_M_strides[__next] < _M_strides[__prev] * _M_extents.extent(__prev))
2101#if __glibcxx_submdspan
2102 template<
typename... _Slices>
2103 requires (extents_type::rank() ==
sizeof...(_Slices))
2104 friend constexpr auto
2105 submdspan_mapping(
const mapping& __mapping, _Slices... __slices)
2107 if constexpr (
sizeof...(_Slices) == 0)
2108 return submdspan_mapping_result{__mapping, 0};
2111 auto __offset = __mdspan::__suboffset(__mapping, __slices...);
2112 auto __sub_exts = __mdspan::__subextents(__mapping.extents(), __slices...);
2114 = __mdspan::__substrides<decltype(__sub_exts)>(__mapping, __slices...);
2115 return submdspan_mapping_result{
2116 layout_stride::mapping(__sub_exts, __sub_strides), __offset};
2121 [[no_unique_address]] extents_type _M_extents;
2122 [[no_unique_address]] _Strides _M_strides;
2125#ifdef __glibcxx_padded_layouts
2129 __least_multiple(
size_t __x,
size_t __y)
2133 return (__y / __x + (__y % __x != 0)) * __x ;
2136 template<
typename _IndexType>
2138 __is_representable_least_multiple(
size_t __x,
size_t __y)
2140 constexpr auto __y_max = __gnu_cxx::__int_traits<_IndexType>::__max;
2141 if(std::cmp_greater(__y, __y_max))
2147 auto __max_delta = __y_max -
static_cast<_IndexType
>(__y);
2148 auto __y_mod_x = __y % __x;
2149 auto __delta = (__y_mod_x == 0) ?
size_t(0) : (__x - __y_mod_x);
2150 return std::cmp_less_equal(__delta, __max_delta);
2153 template<
typename _Extents,
size_t _PaddingValue,
typename _LayoutTraits,
2154 size_t _Rank = _Extents::rank()>
2155 concept __valid_static_stride = (_Extents::rank() <= 1)
2156 || (_PaddingValue == dynamic_extent)
2157 || (_Extents::static_extent(_LayoutTraits::_S_ext_idx) == dynamic_extent)
2158 || (__is_representable_least_multiple<size_t>(
2159 _PaddingValue, _Extents::static_extent(_LayoutTraits::_S_ext_idx)));
2161 template<
size_t _PaddedStride,
typename _Extents,
2162 typename _LayoutTraits>
2164 __is_representable_padded_size()
2166 using _IndexType =
typename _Extents::index_type;
2167 auto __sta_exts = __static_extents<_Extents>(
2168 _LayoutTraits::_S_unpad_begin, _LayoutTraits::_S_unpad_end);
2169 size_t __max = __gnu_cxx::__int_traits<_IndexType>::__max;
2170 return __static_quotient(__sta_exts, __max / _PaddedStride) != 0;
2173 template<
typename _Extents,
size_t _PaddedStride,
typename _LayoutTraits,
2174 size_t _Rank = _Extents::rank()>
2175 concept __valid_padded_size = (_Rank <= 1)
2176 || (_PaddedStride == dynamic_extent)
2177 || (!__all_static(__static_extents<_Extents>()))
2178 || (__contains_zero(__static_extents<_Extents>()))
2179 || (__is_representable_padded_size<_PaddedStride, _Extents,
2182 template<
typename _Extents,
typename _Stride,
typename... _Indices>
2183 constexpr typename _Extents::index_type
2184 __linear_index_leftpad(
const _Extents& __exts, _Stride __stride,
2185 _Indices... __indices)
2188 using _IndexType =
typename _Extents::index_type;
2189 _IndexType __res = 0;
2190 if constexpr (
sizeof...(__indices) > 0)
2192 _IndexType __mult = 1;
2194 auto __update_rest = [&, __pos = 1u](_IndexType __idx)
mutable
2196 __res += __idx * __mult;
2197 __mult *= __exts.extent(__pos);
2201 auto __update = [&](_IndexType __idx,
auto... __rest)
2204 __mult = __stride.extent(0);
2205 (__update_rest(__rest), ...);
2207 __update(__indices...);
2212 template<
typename _Extents,
typename _Stride,
typename... _Indices>
2213 constexpr typename _Extents::index_type
2214 __linear_index_rightpad(
const _Extents& __exts, _Stride __stride,
2215 _Indices... __indices)
2218 using _IndexType =
typename _Extents::index_type;
2219 _IndexType __res = 0;
2220 if constexpr (
sizeof...(__indices) > 0)
2222 _IndexType __mult = 1;
2223 array<_IndexType,
sizeof...(__indices)> __ind_arr{__indices...};
2225 auto __update_rest = [&, __pos = __exts.rank()-1](_IndexType)
mutable
2228 __res += __ind_arr[__pos] * __mult;
2229 __mult *= __exts.extent(__pos);
2232 auto __update = [&](_IndexType,
auto... __rest)
2234 __res += __ind_arr[__exts.rank() - 1];
2235 __mult = __stride.extent(0);
2236 (__update_rest(__rest), ...);
2238 __update(__indices...);
2243 template<
size_t _Rank>
2244 struct _LeftPaddedLayoutTraits
2246 using _LayoutSame = layout_left;
2247 using _LayoutOther = layout_right;
2249 constexpr static const size_t _S_ext_idx = 0;
2250 constexpr static const size_t _S_stride_idx = 1;
2251 constexpr static const size_t _S_unpad_begin = 1;
2252 constexpr static const size_t _S_unpad_end = _Rank;
2254 template<
typename _IndexType,
size_t _StaticStride,
size_t..._Extents>
2255 constexpr static auto
2256 _S_make_padded_extent(
2257 extents<_IndexType, _StaticStride> __stride,
2258 const extents<_IndexType, _Extents...>& __exts)
2260 auto __impl = [&]<
size_t... _Is>(integer_sequence<size_t, _Is...>)
2262 return extents<_IndexType, _StaticStride,
2263 (_Extents...[_Is + 1])...>{
2264 __stride.extent(0), __exts.extent(_Is + 1)...};
2266 return __impl(make_index_sequence<
sizeof...(_Extents) - 1>());
2270 template<
size_t _Rank>
2271 struct _RightPaddedLayoutTraits
2273 using _LayoutSame = layout_right;
2274 using _LayoutOther = layout_left;
2276 constexpr static size_t _S_ext_idx = _Rank - 1;
2277 constexpr static size_t _S_stride_idx = _Rank - 2;
2278 constexpr static size_t _S_unpad_begin = 0;
2279 constexpr static size_t _S_unpad_end = _Rank - 1;
2281 template<
typename _IndexType,
size_t _StaticStride,
size_t..._Extents>
2282 constexpr static auto
2283 _S_make_padded_extent(
2284 extents<_IndexType, _StaticStride> __stride,
2285 const extents<_IndexType, _Extents...>& __exts)
2287 auto __impl = [&]<
size_t... _Is>(integer_sequence<size_t, _Is...>)
2289 return extents<_IndexType, (_Extents...[_Is])..., _StaticStride>{
2290 __exts.extent(_Is)..., __stride.extent(0)};
2292 return __impl(make_index_sequence<
sizeof...(_Extents) - 1>());
2296 template<
size_t _PaddingValue,
typename _Extents,
typename _LayoutTraits>
2297 class _PaddedStorage
2299 using _LayoutSame =
typename _LayoutTraits::_LayoutSame;
2302 using _IndexType =
typename _Extents::index_type;
2303 constexpr static size_t _S_rank = _Extents::rank();
2307 static_assert((_PaddingValue == dynamic_extent)
2308 || (cmp_less_equal(_PaddingValue,
2309 __gnu_cxx::__int_traits<_IndexType>::__max)),
2310 "padding_value must be representable as index_type");
2312 static_assert(__representable_size<_Extents, _IndexType>,
2313 "The size of extents_type must be representable as index_type");
2315 static_assert(__valid_static_stride<_Extents, _PaddingValue,
2317 "The padded stride must be representable as size_t");
2319 static constexpr size_t _S_static_stride = []
consteval
2321 constexpr size_t __rank = _Extents::rank();
2322 if constexpr (__rank <= 1)
2326 constexpr size_t __ext_idx = _LayoutTraits::_S_ext_idx;
2327 constexpr size_t __sta_ext = _Extents::static_extent(__ext_idx);
2328 if constexpr (__sta_ext == 0)
2330 else if constexpr (_PaddingValue == dynamic_extent
2331 || __sta_ext == dynamic_extent)
2332 return dynamic_extent;
2334 return __least_multiple(_PaddingValue, __sta_ext);
2338 static_assert(_S_static_stride == dynamic_extent
2339 || cmp_less_equal(_S_static_stride,
2340 __gnu_cxx::__int_traits<_IndexType>::__max),
2341 "Padded stride must be representable as index_type");
2343 static_assert(__valid_padded_size<_Extents, _S_static_stride,
2347 _PaddedStorage() noexcept
2349 if constexpr (_S_rank > 1)
2350 if constexpr (_S_static_stride == dynamic_extent
2351 && _S_static_padextent() != dynamic_extent)
2352 _M_stride = _Stride{_S_static_padextent()};
2356 _PaddedStorage(
const _Extents& __exts)
2357 : _M_extents(__exts)
2359 if constexpr (!__all_static(__static_extents<_Extents>()))
2360 __glibcxx_assert(__is_representable_extents(_M_extents));
2362 if constexpr (_S_rank > 1)
2364 _IndexType __stride;
2365 if constexpr (_PaddingValue == dynamic_extent)
2366 __stride = _M_padextent();
2367 else if constexpr (_S_static_padextent() != dynamic_extent)
2372 __is_representable_least_multiple<_IndexType>(
2373 _PaddingValue, _M_padextent()));
2375 __stride =
static_cast<_IndexType
>(
2376 __least_multiple(_PaddingValue, _M_padextent()));
2378 __glibcxx_assert(__is_representable_extents(
2379 _LayoutTraits::_S_make_padded_extent(
2380 std::dextents<_IndexType, 1>{__stride},
2383 _M_stride = _Stride{__stride};
2388 _PaddedStorage(
const _Extents& __exts, _IndexType __pad)
2389 : _M_extents(__exts)
2391 if constexpr (_PaddingValue != dynamic_extent)
2392 __glibcxx_assert(cmp_equal(_PaddingValue, __pad));
2393 if constexpr (_S_rank > 1 && _S_static_stride == dynamic_extent)
2396 __is_representable_least_multiple<_IndexType>(
2397 __pad, _M_padextent()));
2399 _M_stride = _Stride{
static_cast<_IndexType
>(
2400 __least_multiple(__pad, _M_padextent()))};
2402 __glibcxx_assert(__is_representable_extents(
2403 _LayoutTraits::_S_make_padded_extent(
2404 _M_stride, _M_extents)));
2408 template<
typename _OExtents>
2411 const typename _LayoutSame::template mapping<_OExtents>& __other)
2412 : _PaddedStorage(_Extents(__other.extents()))
2414 constexpr size_t __stride_idx = _LayoutTraits::_S_stride_idx;
2415 constexpr size_t __ext_idx = _LayoutTraits::_S_ext_idx;
2416 if constexpr (_S_rank > 1 && _PaddingValue != dynamic_extent)
2418 static_assert(_S_static_stride == dynamic_extent
2419 || _OExtents::static_extent(__ext_idx) == dynamic_extent
2420 || _S_static_stride == _OExtents::static_extent(__ext_idx),
2421 "The padded stride must be compatible with other");
2423 if constexpr (_S_static_stride == dynamic_extent
2424 || _OExtents::static_extent(__stride_idx) == dynamic_extent)
2425 __glibcxx_assert(std::cmp_equal(_M_padstride(),
2430 template<
typename _OExtents>
2432 _PaddedStorage(
const typename layout_stride::mapping<_OExtents>&
2434 : _M_extents(__other.extents())
2436 __glibcxx_assert(cmp_less_equal(__other.required_span_size(),
2440 constexpr size_t __stride_idx = _LayoutTraits::_S_stride_idx;
2441 if constexpr (_S_rank > 1)
2443 if constexpr (_PaddingValue != dynamic_extent)
2444 __glibcxx_assert(cmp_equal(__other.stride(__stride_idx),
2445 _M_calc_padstride())
2446 &&
"The padded stride must be compatible with other");
2447 if constexpr (_S_static_stride == dynamic_extent)
2448 _M_stride = _Stride{__other.stride(__stride_idx)};
2452 template<
typename _SamePaddedMapping>
2454 _PaddedStorage(_LayoutTraits::_LayoutSame,
2455 const _SamePaddedMapping& __other)
2456 : _M_extents(__other.extents())
2458 if constexpr (_S_rank > 1)
2460 static_assert(_PaddingValue == dynamic_extent
2461 || _SamePaddedMapping::padding_value == dynamic_extent
2462 || _PaddingValue == _SamePaddedMapping::padding_value,
2463 "If neither PaddingValue is dynamic_extent, then they must "
2466 constexpr size_t __stride_idx = _LayoutTraits::_S_stride_idx;
2467 if constexpr (_PaddingValue != dynamic_extent)
2468 __glibcxx_assert(cmp_equal(__other.stride(__stride_idx),
2469 _M_calc_padstride())
2470 &&
"The padded stride must be compatible with other");
2471 if constexpr (_S_static_stride == dynamic_extent)
2472 _M_stride = _Stride{__other.stride(__stride_idx)};
2474 __glibcxx_assert(cmp_less_equal(__other.required_span_size(),
2475 __gnu_cxx::__int_traits<_IndexType>::__max));
2478 template<
typename _OtherPaddedMapping>
2480 _PaddedStorage(_LayoutTraits::_LayoutOther,
2481 const _OtherPaddedMapping& __other) noexcept
2482 : _M_extents(__other.extents())
2484 __glibcxx_assert(cmp_less_equal(__other.required_span_size(),
2485 __gnu_cxx::__int_traits<_IndexType>::__max));
2488 static constexpr bool
2489 _M_is_always_exhaustive() noexcept
2491 if constexpr (_S_rank <= 1)
2494 return _S_static_padextent() != dynamic_extent
2495 && _S_static_stride != dynamic_extent
2496 && _S_static_padextent() == _S_static_stride;
2500 _M_is_exhaustive() const noexcept
2502 if constexpr (_M_is_always_exhaustive())
2505 return cmp_equal(_M_padextent(), _M_padstride());
2508 constexpr static size_t
2509 _S_static_padextent() noexcept
2510 {
return _Extents::static_extent(_LayoutTraits::_S_ext_idx); }
2512 constexpr _IndexType
2513 _M_padextent() const noexcept
2514 {
return _M_extents.extent(_LayoutTraits::_S_ext_idx); }
2516 constexpr _IndexType
2517 _M_calc_padstride() const noexcept
2519 if constexpr (_S_static_stride != dynamic_extent)
2520 return _S_static_stride;
2521 else if constexpr (_PaddingValue != dynamic_extent)
2522 return __least_multiple(_PaddingValue, _M_padextent());
2524 return _M_padextent();
2527 constexpr _IndexType
2528 _M_padstride() const noexcept
2529 {
return _M_stride.extent(0); }
2531 constexpr _IndexType
2532 _M_required_span_size() const noexcept
2534 if constexpr (_S_rank == 0)
2536 else if (__mdspan::__empty(_M_extents))
2540 size_t __stride =
static_cast<size_t>(_M_padstride());
2541 size_t __prod_rest = __mdspan::__fwd_prod(_M_extents,
2542 _LayoutTraits::_S_unpad_begin, _LayoutTraits::_S_unpad_end);
2543 size_t __delta = _M_padstride() - _M_padextent();
2544 return static_cast<_IndexType
>(__stride * __prod_rest - __delta);
2548 template<
typename _SamePaddedMapping>
2550 _M_equal(
const _SamePaddedMapping& __other)
const noexcept
2552 return _M_extents == __other.extents()
2554 || cmp_equal(_M_stride.extent(0),
2555 __other.stride(_LayoutTraits::_S_stride_idx)));
2558 using _Stride = std::extents<_IndexType, _S_static_stride>;
2559 [[no_unique_address]] _Stride _M_stride;
2560 [[no_unique_address]] _Extents _M_extents;
2564 template<
size_t _PaddingValue>
2565 template<
typename _Extents>
2566 class layout_left_padded<_PaddingValue>::mapping
2569 static constexpr size_t padding_value = _PaddingValue;
2571 using extents_type = _Extents;
2572 using index_type =
typename extents_type::index_type;
2573 using size_type =
typename extents_type::size_type;
2574 using rank_type =
typename extents_type::rank_type;
2575 using layout_type = layout_left_padded<padding_value>;
2578 static constexpr size_t _S_rank = extents_type::rank();
2579 using _PaddedStorage = __mdspan::_PaddedStorage<_PaddingValue,
2580 _Extents, __mdspan::_LeftPaddedLayoutTraits<_S_rank>>;
2581 [[no_unique_address]] _PaddedStorage _M_storage;
2583 consteval friend size_t
2584 __mdspan::__get_static_stride<mapping>();
2586 constexpr index_type
2587 _M_extent(
size_t __r)
const noexcept
2588 {
return _M_storage._M_extents.extent(__r); }
2590 constexpr index_type
2591 _M_padstride() const noexcept
2592 {
return _M_storage._M_stride.extent(0); }
2600 mapping(
const mapping&)
noexcept =
default;
2603 mapping(
const extents_type& __exts)
2604 : _M_storage(__exts)
2607 template<__mdspan::__val
id_index_type<index_type> _OIndexType>
2609 mapping(
const extents_type& __exts, _OIndexType __pad)
2610 : _M_storage(__exts,
2611 __mdspan::__index_type_cast<index_type>(std::move(__pad)))
2614 template<
typename _OExtents>
2615 requires is_constructible_v<extents_type, _OExtents>
2616 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
2617 mapping(
const layout_left::mapping<_OExtents>& __other)
2618 : _M_storage(__other)
2621 template<
typename _OExtents>
2622 requires is_constructible_v<_OExtents, extents_type>
2623 constexpr explicit(!(_OExtents::rank() == 0
2624 && is_convertible_v<_OExtents, extents_type>))
2625 mapping(
const typename layout_stride::mapping<_OExtents>& __other)
2626 : _M_storage(__other)
2627 { __glibcxx_assert(*
this == __other); }
2629 template<
typename _LeftPaddedMapping>
2630 requires __mdspan::__is_left_padded_mapping<_LeftPaddedMapping>
2631 && is_constructible_v<extents_type,
2632 typename _LeftPaddedMapping::extents_type>
2634 !is_convertible_v<
typename _LeftPaddedMapping::extents_type,
2636 || _S_rank > 1 && (padding_value != dynamic_extent
2637 || _LeftPaddedMapping::padding_value == dynamic_extent))
2638 mapping(
const _LeftPaddedMapping& __other)
2639 : _M_storage(layout_left{}, __other)
2642 template<
typename _RightPaddedMapping>
2643 requires (__mdspan::__is_right_padded_mapping<_RightPaddedMapping>
2644 || __mdspan::__mapping_of<layout_right, _RightPaddedMapping>)
2646 && is_constructible_v<extents_type,
2647 typename _RightPaddedMapping::extents_type>
2648 constexpr explicit(!is_convertible_v<
2649 typename _RightPaddedMapping::extents_type, extents_type>)
2650 mapping(
const _RightPaddedMapping& __other) noexcept
2651 : _M_storage(layout_right{}, __other)
2655 operator=(
const mapping&)
noexcept =
default;
2657 constexpr const extents_type&
2658 extents() const noexcept {
return _M_storage._M_extents; }
2660 constexpr array<index_type, _S_rank>
2661 strides() const noexcept
2663 array<index_type, _S_rank> __ret;
2664 if constexpr (_S_rank > 0)
2666 if constexpr (_S_rank > 1)
2667 __ret[1] = _M_padstride();
2668 if constexpr (_S_rank > 2)
2669 for(
size_t __i = 2; __i < _S_rank; ++__i)
2670 __ret[__i] = __ret[__i - 1] * _M_extent(__i - 1);
2674 constexpr index_type
2675 required_span_size() const noexcept
2676 {
return _M_storage._M_required_span_size(); }
2680 template<__mdspan::__val
id_index_type<index_type>... _Indices>
2681 requires (
sizeof...(_Indices) == _S_rank)
2682 constexpr index_type
2683 operator()(_Indices... __indices)
const noexcept
2685 return __mdspan::__linear_index_leftpad(
2686 extents(), _M_storage._M_stride,
2687 static_cast<index_type
>(
std::move(__indices))...);
2690 static constexpr bool
2691 is_always_exhaustive() noexcept
2692 {
return _PaddedStorage::_M_is_always_exhaustive(); }
2695 is_exhaustive() const noexcept
2696 {
return _M_storage._M_is_exhaustive(); }
2698 static constexpr bool
2699 is_always_unique() noexcept {
return true; }
2701 static constexpr bool
2702 is_unique() noexcept {
return true; }
2704 static constexpr bool
2705 is_always_strided() noexcept {
return true; }
2707 static constexpr bool
2708 is_strided() noexcept {
return true; }
2710 constexpr index_type
2711 stride(rank_type __r)
const noexcept
2713 __glibcxx_assert(__r < _S_rank);
2717 return static_cast<index_type
>(
2718 static_cast<size_t>(_M_padstride()) *
2719 static_cast<size_t>(__mdspan::__fwd_prod(extents(), 1, __r)));
2722 template<
typename _LeftpadMapping>
2723 requires(__mdspan::__is_left_padded_mapping<_LeftpadMapping>
2724 && _LeftpadMapping::extents_type::rank() == _S_rank)
2725 friend constexpr bool
2726 operator==(
const mapping& __self,
const _LeftpadMapping& __other)
2728 {
return __self._M_storage._M_equal(__other); }
2731#if __glibcxx_submdspan
2732 template<
typename... _Slices>
2733 requires (extents_type::rank() ==
sizeof...(_Slices))
2734 friend constexpr auto
2735 submdspan_mapping(
const mapping& __mapping, _Slices... __slices)
2736 {
return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
2740 template<
size_t _PaddingValue>
2741 template<
typename _Extents>
2742 class layout_right_padded<_PaddingValue>::mapping {
2744 static constexpr size_t padding_value = _PaddingValue;
2745 using extents_type = _Extents;
2746 using index_type =
typename extents_type::index_type;
2747 using size_type =
typename extents_type::size_type;
2748 using rank_type =
typename extents_type::rank_type;
2749 using layout_type = layout_right_padded<_PaddingValue>;
2752 static constexpr size_t _S_rank = extents_type::rank();
2753 using _PaddedStorage = __mdspan::_PaddedStorage<_PaddingValue,
2754 _Extents, __mdspan::_RightPaddedLayoutTraits<_S_rank>>;
2755 [[no_unique_address]] _PaddedStorage _M_storage;
2757 consteval friend size_t
2758 __mdspan::__get_static_stride<mapping>();
2760 constexpr index_type
2761 _M_extent(
size_t __r)
const noexcept
2762 {
return _M_storage._M_extents.extent(__r); }
2764 constexpr index_type
2765 _M_padstride() const noexcept
2766 {
return _M_storage._M_stride.extent(0); }
2774 mapping(
const mapping&)
noexcept =
default;
2777 mapping(
const extents_type& __exts)
2778 : _M_storage(__exts)
2781 template<__mdspan::__val
id_index_type<index_type> _OIndexType>
2783 mapping(
const extents_type& __exts, _OIndexType __pad)
2784 : _M_storage(__exts,
2785 __mdspan::__index_type_cast<index_type>(std::move(__pad)))
2788 template<
typename _OExtents>
2789 requires is_constructible_v<extents_type, _OExtents>
2790 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
2791 mapping(
const layout_right::mapping<_OExtents>& __other)
2792 : _M_storage(__other)
2795 template<
typename _OExtents>
2796 requires is_constructible_v<_OExtents, extents_type>
2797 constexpr explicit(!(_OExtents::rank() == 0
2798 && is_convertible_v<_OExtents, extents_type>))
2799 mapping(
const typename layout_stride::mapping<_OExtents>& __other)
2800 : _M_storage(__other)
2801 { __glibcxx_assert(*
this == __other); }
2803 template<
typename _RightPaddedMapping>
2804 requires __mdspan::__is_right_padded_mapping<_RightPaddedMapping>
2805 && is_constructible_v<extents_type,
2806 typename _RightPaddedMapping::extents_type>
2808 !is_convertible_v<
typename _RightPaddedMapping::extents_type,
2810 || _S_rank > 1 && (padding_value != dynamic_extent
2811 || _RightPaddedMapping::padding_value == dynamic_extent))
2812 mapping(
const _RightPaddedMapping& __other)
2813 : _M_storage(layout_right{}, __other)
2816 template<
typename _LeftPaddedMapping>
2817 requires (__mdspan::__is_left_padded_mapping<_LeftPaddedMapping>
2818 || __mdspan::__mapping_of<layout_left, _LeftPaddedMapping>)
2820 && is_constructible_v<extents_type,
2821 typename _LeftPaddedMapping::extents_type>
2822 constexpr explicit(!is_convertible_v<
2823 typename _LeftPaddedMapping::extents_type, extents_type>)
2824 mapping(
const _LeftPaddedMapping& __other) noexcept
2825 : _M_storage(layout_left{}, __other)
2828 constexpr mapping& operator=(
const mapping&)
noexcept =
default;
2830 constexpr const extents_type&
2831 extents() const noexcept {
return _M_storage._M_extents; }
2833 constexpr array<index_type, _S_rank>
2834 strides() const noexcept
2836 array<index_type, _S_rank> __ret;
2837 if constexpr (_S_rank > 0)
2838 __ret[_S_rank - 1] = 1;
2839 if constexpr (_S_rank > 1)
2840 __ret[_S_rank - 2] = _M_padstride();
2841 if constexpr (_S_rank > 2)
2842 for(
size_t __i = _S_rank - 2; __i > 0; --__i)
2843 __ret[__i - 1] = __ret[__i] * _M_extent(__i);
2847 constexpr index_type
2848 required_span_size() const noexcept
2849 {
return _M_storage._M_required_span_size(); }
2853 template<__mdspan::__val
id_index_type<index_type>... _Indices>
2854 requires (
sizeof...(_Indices) == _S_rank)
2855 constexpr index_type
2856 operator()(_Indices... __indices)
const noexcept
2858 return __mdspan::__linear_index_rightpad(
2859 extents(), _M_storage._M_stride,
2860 static_cast<index_type
>(
std::move(__indices))...);
2863 static constexpr bool
2864 is_always_exhaustive() noexcept
2865 {
return _PaddedStorage::_M_is_always_exhaustive(); }
2868 is_exhaustive() const noexcept
2869 {
return _M_storage._M_is_exhaustive(); }
2871 static constexpr bool
2872 is_always_unique() noexcept {
return true; }
2874 static constexpr bool
2875 is_unique() noexcept {
return true; }
2877 static constexpr bool
2878 is_always_strided() noexcept {
return true; }
2880 static constexpr bool
2881 is_strided() noexcept {
return true; }
2883 constexpr index_type
2884 stride(rank_type __r)
const noexcept
2886 __glibcxx_assert(__r < _S_rank);
2887 if constexpr (_S_rank <= 1)
2889 else if (__r == _S_rank - 1)
2891 else if (__r == _S_rank - 2)
2892 return _M_padstride();
2894 return static_cast<index_type
>(
2895 static_cast<size_t>(_M_padstride()) *
2896 static_cast<size_t>(__mdspan::__fwd_prod(
2897 extents(), __r + 1, _S_rank - 1)));
2900 template<
typename _RightPaddedMapping>
2901 requires(__mdspan::__is_right_padded_mapping<_RightPaddedMapping>
2902 && _RightPaddedMapping::extents_type::rank() == _S_rank)
2903 friend constexpr bool
2904 operator==(
const mapping& __self,
const _RightPaddedMapping& __other)
2906 {
return __self._M_storage._M_equal(__other); }
2908#if __glibcxx_submdspan
2910 template<
typename... _Slices>
2911 requires (extents_type::rank() ==
sizeof...(_Slices))
2912 friend constexpr auto
2913 submdspan_mapping(
const mapping& __mapping, _Slices... __slices)
2914 {
return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
2919 template<
typename _ElementType>
2920 struct default_accessor
2922 static_assert(!is_array_v<_ElementType>,
2923 "ElementType must not be an array type");
2924 static_assert(!is_abstract_v<_ElementType>,
2925 "ElementType must not be an abstract class type");
2927 using offset_policy = default_accessor;
2928 using element_type = _ElementType;
2929 using reference = element_type&;
2930 using data_handle_type = element_type*;
2933 default_accessor() noexcept = default;
2935 template<typename _OElementType>
2936 requires is_convertible_v<_OElementType(*)[], element_type(*)[]>
2938 default_accessor(default_accessor<_OElementType>) noexcept
2942 access(data_handle_type __p,
size_t __i)
const noexcept
2943 {
return __p[__i]; }
2945 constexpr data_handle_type
2946 offset(data_handle_type __p,
size_t __i)
const noexcept
2947 {
return __p + __i; }
2950#ifdef __glibcxx_aligned_accessor
2951 template<
typename _ElementType,
size_t _ByteAlignment>
2952 struct aligned_accessor
2954 static_assert(has_single_bit(_ByteAlignment),
2955 "ByteAlignment must be a power of two");
2956 static_assert(_ByteAlignment >=
alignof(_ElementType));
2958 using offset_policy = default_accessor<_ElementType>;
2959 using element_type = _ElementType;
2960 using reference = element_type&;
2961 using data_handle_type = element_type*;
2963 static constexpr size_t byte_alignment = _ByteAlignment;
2966 aligned_accessor() noexcept = default;
2968 template<typename _OElementType,
size_t _OByteAlignment>
2969 requires (_OByteAlignment >= byte_alignment)
2970 && is_convertible_v<_OElementType(*)[], element_type(*)[]>
2972 aligned_accessor(aligned_accessor<_OElementType, _OByteAlignment>)
2976 template<
typename _OElementType>
2977 requires is_convertible_v<_OElementType(*)[], element_type(*)[]>
2979 aligned_accessor(default_accessor<_OElementType>)
noexcept
2982 template<
typename _OElementType>
2983 requires is_convertible_v<element_type(*)[], _OElementType(*)[]>
2985 operator default_accessor<_OElementType>() const noexcept
2989 access(data_handle_type __p,
size_t __i)
const noexcept
2992 constexpr typename offset_policy::data_handle_type
2993 offset(data_handle_type __p,
size_t __i)
const noexcept
2998 template<
typename _ElementType,
typename _Extents,
2999 typename _LayoutPolicy = layout_right,
3000 typename _AccessorPolicy = default_accessor<_ElementType>>
3003 static_assert(!is_array_v<_ElementType>,
3004 "ElementType must not be an array type");
3005 static_assert(!is_abstract_v<_ElementType>,
3006 "ElementType must not be an abstract class type");
3007 static_assert(__mdspan::__is_extents<_Extents>,
3008 "Extents must be a specialization of std::extents");
3009 static_assert(is_same_v<_ElementType,
3010 typename _AccessorPolicy::element_type>);
3013 using extents_type = _Extents;
3014 using layout_type = _LayoutPolicy;
3015 using accessor_type = _AccessorPolicy;
3016 using mapping_type =
typename layout_type::template mapping<extents_type>;
3017 using element_type = _ElementType;
3018 using value_type = remove_cv_t<element_type>;
3019 using index_type =
typename extents_type::index_type;
3020 using size_type =
typename extents_type::size_type;
3021 using rank_type =
typename extents_type::rank_type;
3022 using data_handle_type =
typename accessor_type::data_handle_type;
3023 using reference =
typename accessor_type::reference;
3025 static constexpr rank_type
3026 rank() noexcept {
return extents_type::rank(); }
3028 static constexpr rank_type
3029 rank_dynamic() noexcept {
return extents_type::rank_dynamic(); }
3031 static constexpr size_t
3032 static_extent(rank_type __r)
noexcept
3033 {
return extents_type::static_extent(__r); }
3035 constexpr index_type
3036 extent(rank_type __r)
const noexcept {
return extents().extent(__r); }
3040 requires (rank_dynamic() > 0)
3041 && is_default_constructible_v<data_handle_type>
3042 && is_default_constructible_v<mapping_type>
3043 && is_default_constructible_v<accessor_type> =
default;
3046 mdspan(
const mdspan& __other) =
default;
3049 mdspan(mdspan&& __other) =
default;
3051 template<__mdspan::__val
id_index_type<index_type>... _OIndexTypes>
3052 requires (
sizeof...(_OIndexTypes) == rank()
3053 ||
sizeof...(_OIndexTypes) == rank_dynamic())
3054 && is_constructible_v<mapping_type, extents_type>
3055 && is_default_constructible_v<accessor_type>
3057 mdspan(data_handle_type __handle, _OIndexTypes... __exts)
3059 _M_mapping(_Extents(
static_cast<index_type
>(
std::move(__exts))...)),
3063 template<
typename _OIndexType,
size_t _Nm>
3064 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3065 && (_Nm == rank() || _Nm == rank_dynamic())
3066 && is_constructible_v<mapping_type, extents_type>
3067 && is_default_constructible_v<accessor_type>
3068 constexpr explicit(_Nm != rank_dynamic())
3069 mdspan(data_handle_type __handle, span<_OIndexType, _Nm> __exts)
3070 : _M_accessor(), _M_mapping(extents_type(__exts)),
3071 _M_handle(std::move(__handle))
3074 template<
typename _OIndexType,
size_t _Nm>
3075 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3076 && (_Nm == rank() || _Nm == rank_dynamic())
3077 && is_constructible_v<mapping_type, extents_type>
3078 && is_default_constructible_v<accessor_type>
3079 constexpr explicit(_Nm != rank_dynamic())
3080 mdspan(data_handle_type __handle,
const array<_OIndexType, _Nm>& __exts)
3081 : _M_accessor(), _M_mapping(extents_type(__exts)),
3082 _M_handle(std::move(__handle))
3086 mdspan(data_handle_type __handle,
const extents_type& __exts)
3087 requires is_constructible_v<mapping_type, const extents_type&>
3088 && is_default_constructible_v<accessor_type>
3089 : _M_accessor(), _M_mapping(__exts), _M_handle(
std::move(__handle))
3093 mdspan(data_handle_type __handle,
const mapping_type& __mapping)
3094 requires is_default_constructible_v<accessor_type>
3095 : _M_accessor(), _M_mapping(__mapping), _M_handle(
std::move(__handle))
3099 mdspan(data_handle_type __handle,
const mapping_type& __mapping,
3100 const accessor_type& __accessor)
3101 : _M_accessor(__accessor), _M_mapping(__mapping),
3102 _M_handle(std::move(__handle))
3105 template<
typename _OElementType,
typename _OExtents,
typename _OLayout,
3106 typename _OAccessor>
3107 requires is_constructible_v<mapping_type,
3108 const typename _OLayout::template mapping<_OExtents>&>
3109 && is_constructible_v<accessor_type, const _OAccessor&>
3110 constexpr explicit(!is_convertible_v<
3111 const typename _OLayout::template mapping<_OExtents>&, mapping_type>
3112 || !is_convertible_v<const _OAccessor&, accessor_type>)
3113 mdspan(
const mdspan<_OElementType, _OExtents, _OLayout, _OAccessor>&
3115 : _M_accessor(__other.accessor()), _M_mapping(__other.mapping()),
3116 _M_handle(__other.data_handle())
3118 static_assert(is_constructible_v<data_handle_type,
3119 const typename _OAccessor::data_handle_type&>);
3120 static_assert(is_constructible_v<extents_type, _OExtents>);
3124 operator=(
const mdspan& __other) =
default;
3127 operator=(mdspan&& __other) =
default;
3129 template<__mdspan::__val
id_index_type<index_type>... _OIndexTypes>
3130 requires (
sizeof...(_OIndexTypes) == rank())
3132 operator[](_OIndexTypes... __indices)
const
3134 if constexpr (rank() == 0)
3135 return _M_accessor.access(_M_handle, _M_mapping());
3136 else if constexpr (!(is_integral_v<_OIndexTypes> && ...))
3137 return operator[](__index_int_t<_OIndexTypes>(
std::move(__indices))...);
3140 auto __is_valid_index = [&]<
typename _OIntType>(
size_t __dim, _OIntType __index)
3142 if constexpr (is_signed_v<_OIntType>)
3145 return std::cmp_less(__index, extents().extent(__dim));
3147 auto __is_multi_index = [&]<
size_t... _Counts>(
index_sequence<_Counts...>)
3148 {
return (__is_valid_index(_Counts, __indices) && ...); };
3150 __glibcxx_assert(__is_multi_index(make_index_sequence<rank()>()));
3151 auto __index = _M_mapping(
static_cast<index_type
>(__indices)...);
3152 return _M_accessor.access(_M_handle, __index);
3156 template<
typename _OIndexType>
3157 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3159 operator[](span<_OIndexType, rank()> __indices)
const
3165 __index_int_t<_OIndexType>(as_const(__indices[_Counts]))...);
3167 return __call(make_index_sequence<rank()>());
3170 template<
typename _OIndexType>
3171 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3173 operator[](
const array<_OIndexType, rank()>& __indices)
const
3174 {
return operator[](span<
const _OIndexType, rank()>(__indices)); }
3176#if __cplusplus > 202302L
3177 template<__mdspan::__val
id_index_type<index_type>... _OIndexTypes>
3178 requires (
sizeof...(_OIndexTypes) == rank())
3180 at(_OIndexTypes... __indices)
const
3182 if constexpr (rank() == 0)
3183 return _M_accessor.access(_M_handle, _M_mapping());
3184 else if constexpr (!(is_integral_v<_OIndexTypes> && ...))
3185 return at(__index_int_t<_OIndexTypes>(
std::move(__indices))...);
3188 auto __check_bound = [&]<
typename _OIntType>(
size_t __dim, _OIntType __index)
3190 if constexpr (is_signed_v<_OIntType>)
3192 std::__throw_out_of_range_fmt(
3193 __N(
"mdspan::at: %zuth index is negative"), __dim);
3195 const auto __ext = extents().extent(__dim);
3196 if (std::cmp_greater_equal(__index, __ext))
3197 std::__throw_out_of_range_fmt(
3198 __N(
"mdspan::at: %zuth index (which is %zu)"
3199 " >= extent(%zu) (which is %zu)"),
3200 __dim,
size_t(__index), __dim,
size_t(__ext));
3202 auto __check_bounds = [&]<
size_t... _Counts>(
index_sequence<_Counts...>)
3203 { (__check_bound(_Counts, __indices), ...); };
3205 __check_bounds(make_index_sequence<rank()>());
3206 auto __index = _M_mapping(
static_cast<index_type
>(__indices)...);
3207 return _M_accessor.access(_M_handle, __index);
3211 template<
typename _OIndexType>
3212 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3214 at(span<_OIndexType, rank()> __indices)
const
3220 __index_int_t<_OIndexType>(as_const(__indices[_Counts]))...);
3222 return __call(make_index_sequence<rank()>());
3225 template<
typename _OIndexType>
3226 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3228 at(
const array<_OIndexType, rank()>& __indices)
const
3229 {
return at(span<
const _OIndexType, rank()>(__indices)); }
3233 size() const noexcept
3235 __glibcxx_assert(cmp_less_equal(_M_mapping.required_span_size(),
3238 return size_type(__mdspan::__size(extents()));
3243 empty() const noexcept
3244 {
return __mdspan::__empty(extents()); }
3246 friend constexpr void
3247 swap(mdspan& __x, mdspan& __y)
noexcept
3250 swap(__x._M_mapping, __y._M_mapping);
3251 swap(__x._M_accessor, __y._M_accessor);
3252 swap(__x._M_handle, __y._M_handle);
3255 constexpr const extents_type&
3256 extents() const noexcept {
return _M_mapping.extents(); }
3258 constexpr const data_handle_type&
3259 data_handle() const noexcept {
return _M_handle; }
3261 constexpr const mapping_type&
3262 mapping() const noexcept {
return _M_mapping; }
3264 constexpr const accessor_type&
3265 accessor() const noexcept {
return _M_accessor; }
3269 static constexpr bool
3270 is_always_unique() noexcept(noexcept(mapping_type::is_always_unique()))
3271 {
return mapping_type::is_always_unique(); }
3273 static constexpr bool
3274 is_always_exhaustive()
3275 noexcept(noexcept(mapping_type::is_always_exhaustive()))
3276 {
return mapping_type::is_always_exhaustive(); }
3278 static constexpr bool
3280 noexcept(noexcept(mapping_type::is_always_strided()))
3281 {
return mapping_type::is_always_strided(); }
3284 is_unique() const noexcept(noexcept(_M_mapping.is_unique()))
3285 {
return _M_mapping.is_unique(); }
3288 is_exhaustive() const noexcept(noexcept(_M_mapping.is_exhaustive()))
3289 {
return _M_mapping.is_exhaustive(); }
3292 is_strided() const noexcept(noexcept(_M_mapping.is_strided()))
3293 {
return _M_mapping.is_strided(); }
3295 constexpr index_type
3296 stride(rank_type __r)
const {
return _M_mapping.stride(__r); }
3299 template<
typename _OIndexType>
3300 using __index_int_t = std::__conditional_t<
3301 is_integral_v<_OIndexType>, _OIndexType, index_type>;
3303 [[no_unique_address]] accessor_type _M_accessor = accessor_type();
3304 [[no_unique_address]] mapping_type _M_mapping = mapping_type();
3305 [[no_unique_address]] data_handle_type _M_handle = data_handle_type();
3308 template<
typename _CArray>
3309 requires is_array_v<_CArray> && (rank_v<_CArray> == 1)
3311 -> mdspan<remove_all_extents_t<_CArray>,
3312 extents<size_t, extent_v<_CArray, 0>>>;
3314 template<
typename _Po
inter>
3315 requires is_pointer_v<remove_reference_t<_Pointer>>
3317 -> mdspan<remove_pointer_t<remove_reference_t<_Pointer>>, extents<size_t>>;
3319 template<
typename _ElementType,
typename... _Integrals>
3320 requires (is_convertible_v<_Integrals, size_t> && ...)
3321 && (
sizeof...(_Integrals) > 0)
3322 explicit mdspan(_ElementType*, _Integrals...)
3323 -> mdspan<_ElementType,
3324 extents<size_t, __detail::__maybe_static_ext<_Integrals>...>>;
3326 template<
typename _ElementType,
typename _OIndexType,
size_t _Nm>
3327 mdspan(_ElementType*, span<_OIndexType, _Nm>)
3328 -> mdspan<_ElementType, dextents<size_t, _Nm>>;
3330 template<
typename _ElementType,
typename _OIndexType,
size_t _Nm>
3331 mdspan(_ElementType*,
const array<_OIndexType, _Nm>&)
3332 -> mdspan<_ElementType, dextents<size_t, _Nm>>;
3334 template<
typename _ElementType,
typename _IndexType,
size_t... _ExtentsPack>
3335 mdspan(_ElementType*,
const extents<_IndexType, _ExtentsPack...>&)
3336 -> mdspan<_ElementType, extents<_IndexType, _ExtentsPack...>>;
3338 template<
typename _ElementType,
typename _MappingType>
3339 mdspan(_ElementType*,
const _MappingType&)
3340 -> mdspan<_ElementType,
typename _MappingType::extents_type,
3341 typename _MappingType::layout_type>;
3345 template<
typename _MappingType,
typename _AccessorType>
3346 mdspan(
typename _AccessorType::data_handle_type,
const _MappingType&,
3347 const _AccessorType&)
3348 -> mdspan<
typename _AccessorType::element_type,
3349 typename _MappingType::extents_type,
3350 typename _MappingType::layout_type, _AccessorType>;
3352#if __glibcxx_submdspan
3355 template<
typename _IndexType,
typename _Slice>
3357 __canonical_index(_Slice&& __slice)
3359 if constexpr (__detail::__integral_constant_like<_Slice>)
3361 static_assert(__is_representable_integer<_IndexType>(_Slice::value));
3362 static_assert(_Slice::value >= 0);
3363 return std::cw<_IndexType(_Slice::value)>;
3366 return __mdspan::__index_type_cast<_IndexType>(
std::move(__slice));
3369 template<
typename _IndexType,
3370 typename _OffsetType,
typename _SpanType,
typename _StrideType>
3372 __canonical_range_slice(_OffsetType __offset, _SpanType __span,
3373 _StrideType __stride)
3375 if constexpr (is_same_v<_SpanType, constant_wrapper<_IndexType(0)>>
3376 || is_same_v<_StrideType, constant_wrapper<_IndexType(1)>>)
3377 return extent_slice{
3380 .stride = cw<_IndexType(1)>
3382 else if constexpr (__is_constant_wrapper_v<_StrideType>)
3384 static_assert(_StrideType::value > 0);
3385 if constexpr (__is_constant_wrapper_v<_SpanType>)
3386 return extent_slice{
3388 .extent = cw<_IndexType(1 + (_SpanType::value - 1) / _StrideType::value)>,
3392 return extent_slice{
3394 .extent = _IndexType(__span > 0 ? 1 + (__span - 1) / _StrideType::value : 0),
3398 else if (__span == 0 || __stride == 1)
3399 return extent_slice{
3401 .extent = _IndexType(__span),
3402 .stride = _IndexType(1)
3406 __glibcxx_assert(__stride > 0);
3407 return extent_slice{
3409 .extent = _IndexType(1 + (__span - 1) / __stride),
3415 template<
typename _IndexType,
typename _Slice>
3417 __slice_cast(_Slice&& __slice)
3419 using _SliceType = remove_cvref_t<_Slice>;
3420 if constexpr (is_convertible_v<_SliceType, full_extent_t>)
3421 return static_cast<full_extent_t
>(
std::move(__slice));
3422 else if constexpr (is_convertible_v<_SliceType, _IndexType>)
3423 return __mdspan::__canonical_index<_IndexType>(
std::move(__slice));
3424 else if constexpr (__is_extent_slice<_SliceType>)
3425 return extent_slice{
3426 .offset = __mdspan::__canonical_index<_IndexType>(
std::move(__slice.offset)),
3427 .extent = __mdspan::__canonical_index<_IndexType>(
std::move(__slice.extent)),
3428 .stride = __mdspan::__canonical_index<_IndexType>(
std::move(__slice.stride))
3430 else if constexpr (__is_range_slice<_SliceType>)
3433 = __mdspan::__canonical_index<_IndexType>(
std::move(__slice.first));
3435 = __mdspan::__canonical_index<_IndexType>(
std::move(__slice.last));
3436 return __mdspan::__canonical_range_slice<_IndexType>(
3438 __mdspan::__canonical_index<_IndexType>(__last - __first),
3439 __mdspan::__canonical_index<_IndexType>(
std::move(__slice.stride)));
3443 auto [__sbegin, __send] =
std::move(__slice);
3445 = __mdspan::__canonical_index<_IndexType>(
std::move(__sbegin));
3447 = __mdspan::__canonical_index<_IndexType>(
std::move(__send));
3449 = __mdspan::__canonical_index<_IndexType>(__cend - __cbegin);
3450 return __mdspan::__canonical_range_slice<_IndexType>(
3451 __cbegin, __cspan, cw<_IndexType(1)>);
3455 template<
typename _IndexType,
size_t _Extent,
typename _OIndexType>
3457 __check_inrange_index(
const extents<_IndexType, _Extent>& __ext,
3458 const _OIndexType& __idx)
3460 if constexpr (__is_constant_wrapper_v<_OIndexType>
3461 && _Extent != dynamic_extent)
3463 static_assert(_OIndexType::value >= 0);
3464 static_assert(std::cmp_less(_OIndexType::value, _Extent));
3467 __glibcxx_assert(__idx < __ext.extent(0));
3470 template<
typename _IndexType,
size_t _Extent,
typename _OIndexType>
3472 __check_valid_index(
const extents<_IndexType, _Extent>& __ext,
3473 const _OIndexType& __idx)
3475 if constexpr (__is_constant_wrapper_v<_OIndexType>
3476 && _Extent != dynamic_extent)
3478 static_assert(_OIndexType::value >= 0);
3479 static_assert(std::cmp_less_equal(_OIndexType::value, _Extent));
3482 __glibcxx_assert(__idx <= __ext.extent(0));
3485 template<
typename _IndexType,
size_t _Extent,
typename _Slice>
3487 __check_valid_slice(
const extents<_IndexType, _Extent>& __ext,
3488 const _Slice& __slice)
3490 if constexpr (__is_extent_slice<_Slice>)
3492 __mdspan::__check_valid_index(__ext, __slice.extent);
3497 if constexpr (is_same_v<
typename _Slice::extent_type,
3498 constant_wrapper<_IndexType(0)>>)
3499 __mdspan::__check_valid_index(__ext, __slice.offset);
3500 else if constexpr (is_same_v<
typename _Slice::extent_type,
3501 constant_wrapper<_IndexType(1)>>)
3502 __mdspan::__check_inrange_index(__ext, __slice.offset);
3503 else if constexpr (__is_constant_wrapper_v<typename _Slice::extent_type>)
3505 __mdspan::__check_inrange_index(__ext, __slice.offset);
3506 if constexpr (__is_constant_wrapper_v<typename _Slice::stride_type>)
3507 static_assert(_Slice::stride_type::value > 0);
3509 __glibcxx_assert(__slice.stride > 0);
3511 if constexpr (_Extent != dynamic_extent
3512 && __is_constant_wrapper_v<typename _Slice::offset_type>)
3513 static_assert(std::cmp_greater_equal(
3514 _Extent - _Slice::offset_type::value,
3515 _Slice::extent_type::value));
3516 if constexpr (_Extent != dynamic_extent
3517 && __is_constant_wrapper_v<typename _Slice::stride_type>)
3518 static_assert(std::cmp_greater(
3520 (_Slice::extent_type::value - 1) * _Slice::stride_type::value));
3522 if constexpr (_Extent != dynamic_extent
3523 && __is_constant_wrapper_v<typename _Slice::offset_type>
3524 && __is_constant_wrapper_v<typename _Slice::stride_type>)
3525 static_assert(std::cmp_greater(
3526 _Extent - _Slice::offset_type::value,
3527 (_Slice::extent_type::value - 1) * _Slice::stride_type::value));
3529 __glibcxx_assert(std::cmp_greater(
3530 __ext.extent(0) - __slice.offset,
3531 (_Slice::extent_type::value - 1) * __slice.stride));
3533 else if constexpr (is_same_v<
typename _Slice::stride_type,
3534 constant_wrapper<_IndexType(1)>>)
3536 __mdspan::__check_valid_index(__ext, __slice.offset);
3537 __glibcxx_assert(std::cmp_greater_equal(
3538 __ext.extent(0) - __slice.offset,
3541 else if (__slice.extent == 0)
3542 __mdspan::__check_valid_index(__ext, __slice.offset);
3545 __glibcxx_assert(__slice.offset < __ext.extent(0));
3546 __glibcxx_assert(__slice.extent == 1 || __slice.stride > 0);
3547 __glibcxx_assert(__slice.extent == 1 || std::cmp_greater(
3548 __ext.extent(0) - __slice.offset,
3549 (__slice.extent - 1) * __slice.stride));
3552 else if constexpr (!is_same_v<_Slice, full_extent_t>)
3553 __mdspan::__check_inrange_index(__ext, __slice);
3556 template<
typename _Extents,
typename... _Slices>
3558 __check_valid_slices(
const _Extents& __exts,
const _Slices&... __slices)
3560 constexpr auto __rank = _Extents::rank();
3563 ((__mdspan::__check_valid_slice(__extract_extent<_Is>(__exts),
3564 __slices...[_Is])),...);
3566 __impl(make_index_sequence<__rank>());
3569 template<
typename _Slice>
3570 using __full_extent_t = std::full_extent_t;
3573 void submdspan_mapping() =
delete;
3575 template<
typename _Mapping,
typename... _Slices>
3576 concept __sliceable_mapping =
requires(
const _Mapping __m, _Slices... __slices)
3578 { submdspan_mapping(__m, __slices...) } -> __submdspan_mapping_result;
3581 template<
typename _Mapping,
typename... _Slices>
3583 __submapping(
const _Mapping& __mapping, _Slices... __slices)
3585 __mdspan::__check_valid_slices(__mapping.extents(), __slices...);
3586 return submdspan_mapping(__mapping, __slices...);
3590 template<
typename _IndexType,
size_t... _Extents,
typename... _RawSlices>
3591 requires (
sizeof...(_RawSlices) ==
sizeof...(_Extents))
3593 subextents(
const extents<_IndexType, _Extents...>& __exts,
3594 _RawSlices... __raw_slices)
3596 auto __impl = [&__exts](
auto... __slices)
3598 __mdspan::__check_valid_slices(__exts, __slices...);
3599 return __mdspan::__subextents(__exts, __slices...);
3601 return __impl(__mdspan::__slice_cast<_IndexType>(__raw_slices)...);
3604 template<
typename _IndexType,
size_t... _Extents,
typename... _RawSlices>
3605 requires (
sizeof...(_Extents) ==
sizeof...(_RawSlices))
3607 canonical_slices(
const extents<_IndexType, _Extents...>& __exts,
3608 _RawSlices... __raw_slices)
3610 auto __impl = [&__exts](
auto... __slices)
3612 __mdspan::__check_valid_slices(__exts, __slices...);
3615 return __impl(__mdspan::__slice_cast<_IndexType>(__raw_slices)...);
3618 template<
typename _ElementType,
typename _Extents,
typename _Layout,
3619 typename _Accessor,
typename... _RawSlices>
3620 requires (
sizeof...(_RawSlices) == _Extents::rank()
3621 && __mdspan::__sliceable_mapping<typename _Layout::template mapping<_Extents>,
3622 __mdspan::__full_extent_t<_RawSlices>...>)
3625 const mdspan<_ElementType, _Extents, _Layout, _Accessor>& __md,
3626 _RawSlices... __raw_slices)
3628 using _IndexType =
typename _Extents::index_type;
3629 auto [__mapping, __offset] = __mdspan::__submapping(
3630 __md.mapping(), __mdspan::__slice_cast<_IndexType>(__raw_slices)...);
3632 __md.accessor().offset(__md.data_handle(), __offset),
3634 typename _Accessor::offset_policy(__md.accessor()));
3638_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>.