29#ifndef _GLIBCXX_MDSPAN
30#define _GLIBCXX_MDSPAN 1
33#pragma GCC system_header
41#define __glibcxx_want_mdspan
42#define __glibcxx_want_aligned_accessor
43#define __glibcxx_want_submdspan
46#if __glibcxx_aligned_accessor
50#if __glibcxx_submdspan
55#ifdef __glibcxx_mdspan
57namespace std _GLIBCXX_VISIBILITY(default)
59_GLIBCXX_BEGIN_NAMESPACE_VERSION
63 __all_static(std::span<const size_t> __extents)
65 for(
auto __ext : __extents)
66 if (__ext == dynamic_extent)
72 __all_dynamic(std::span<const size_t> __extents)
74 for(
auto __ext : __extents)
75 if (__ext != dynamic_extent)
80 template<
typename _IndexType,
typename _OIndexType>
82 __index_type_cast(_OIndexType&& __other)
84 if constexpr (std::is_integral_v<_OIndexType>)
86 constexpr _IndexType __index_type_max
87 = __gnu_cxx::__int_traits<_IndexType>::__max;
88 constexpr _OIndexType __oindex_type_max
89 = __gnu_cxx::__int_traits<_OIndexType>::__max;
91 if constexpr (__index_type_max < __oindex_type_max)
92 __glibcxx_assert(cmp_less_equal(__other, __index_type_max));
94 if constexpr (std::is_signed_v<_OIndexType>)
95 __glibcxx_assert(__other >= 0);
96 return static_cast<_IndexType
>(__other);
100 auto __ret =
static_cast<_IndexType
>(
std::move(__other));
101 if constexpr (std::is_signed_v<_IndexType>)
102 __glibcxx_assert(__ret >= 0);
107 template<array _Extents>
111 static constexpr size_t _S_rank = _Extents.size();
119 static constexpr size_t
120 _S_dynamic_index(
size_t __r)
noexcept
121 {
return _S_dynamic_index_data[__r]; }
123 static constexpr auto _S_dynamic_index_data = []
consteval
125 array<size_t, _S_rank+1> __ret;
127 for (
size_t __i = 0; __i < _S_rank; ++__i)
130 __dyn += (_Extents[__i] == dynamic_extent);
132 __ret[_S_rank] = __dyn;
136 static constexpr size_t _S_rank_dynamic = _S_dynamic_index(_S_rank);
140 static constexpr size_t
141 _S_dynamic_index_inv(
size_t __r)
noexcept
142 {
return _S_dynamic_index_inv_data[__r]; }
144 static constexpr auto _S_dynamic_index_inv_data = []
consteval
146 array<size_t, _S_rank_dynamic> __ret;
147 for (
size_t __i = 0, __r = 0; __i < _S_rank; ++__i)
148 if (_Extents[__i] == dynamic_extent)
153 static constexpr size_t
154 _S_static_extent(
size_t __r)
noexcept
155 {
return _Extents[__r]; }
158 template<array _Extents>
159 requires (__all_dynamic<_Extents>())
160 class _StaticExtents<_Extents>
163 static constexpr size_t _S_rank = _Extents.size();
165 static constexpr size_t
166 _S_dynamic_index(
size_t __r)
noexcept
169 static constexpr size_t _S_rank_dynamic = _S_rank;
171 static constexpr size_t
172 _S_dynamic_index_inv(
size_t __k)
noexcept
175 static constexpr size_t
176 _S_static_extent(
size_t)
noexcept
177 {
return dynamic_extent; }
180 template<
typename _IndexType, array _Extents>
181 class _ExtentsStorage :
public _StaticExtents<_Extents>
184 using _Base = _StaticExtents<_Extents>;
187 using _Base::_S_rank;
188 using _Base::_S_rank_dynamic;
189 using _Base::_S_dynamic_index;
190 using _Base::_S_dynamic_index_inv;
191 using _Base::_S_static_extent;
193 static constexpr bool
194 _S_is_dynamic(
size_t __r)
noexcept
196 if constexpr (__all_static(_Extents))
198 else if constexpr (__all_dynamic(_Extents))
201 return _Extents[__r] == dynamic_extent;
204 template<
typename _OIndexType>
205 static constexpr _IndexType
206 _S_int_cast(
const _OIndexType& __other)
noexcept
207 {
return _IndexType(__other); }
210 _M_extent(
size_t __r)
const noexcept
212 if (_S_is_dynamic(__r))
213 return _M_dyn_exts[_S_dynamic_index(__r)];
215 return _S_static_extent(__r);
218 template<
size_t _OtherRank,
typename _GetOtherExtent>
219 static constexpr bool
220 _S_is_compatible_extents(_GetOtherExtent __get_extent)
noexcept
222 if constexpr (_OtherRank == _S_rank)
223 for (
size_t __i = 0; __i < _S_rank; ++__i)
224 if (!_S_is_dynamic(__i)
225 && !cmp_equal(_Extents[__i], _S_int_cast(__get_extent(__i))))
230 template<
size_t _OtherRank,
typename _GetOtherExtent>
232 _M_init_dynamic_extents(_GetOtherExtent __get_extent)
noexcept
234 __glibcxx_assert(_S_is_compatible_extents<_OtherRank>(__get_extent));
235 for (
size_t __i = 0; __i < _S_rank_dynamic; ++__i)
238 if constexpr (_OtherRank != _S_rank_dynamic)
239 __di = _S_dynamic_index_inv(__i);
240 _M_dyn_exts[__i] = _S_int_cast(__get_extent(__di));
245 _ExtentsStorage() noexcept = default;
247 template<typename _OIndexType, array _OExtents>
249 _ExtentsStorage(const _ExtentsStorage<_OIndexType, _OExtents>&
252 _M_init_dynamic_extents<_S_rank>([&__other](
size_t __i)
253 {
return __other._M_extent(__i); });
256 template<
typename _OIndexType,
size_t _Nm>
258 _ExtentsStorage(span<const _OIndexType, _Nm> __exts)
noexcept
260 _M_init_dynamic_extents<_Nm>(
261 [&__exts](
size_t __i) ->
const _OIndexType&
262 {
return __exts[__i]; });
265 static constexpr const array<size_t, _S_rank>&
266 _S_static_extents() noexcept
269 constexpr span<const _IndexType>
270 _M_dynamic_extents(
size_t __begin,
size_t __end)
const noexcept
271 requires (_Extents.size() > 0)
273 return {_M_dyn_exts + _S_dynamic_index(__begin),
274 _M_dyn_exts + _S_dynamic_index(__end)};
278 using _Storage = __array_traits<_IndexType, _S_rank_dynamic>::_Type;
279 [[no_unique_address]] _Storage _M_dyn_exts{};
282 template<
typename _OIndexType,
typename _SIndexType>
283 concept __valid_index_type =
284 is_convertible_v<_OIndexType, _SIndexType> &&
285 is_nothrow_constructible_v<_SIndexType, _OIndexType>;
287 template<
size_t _Extent,
typename _IndexType>
289 __valid_static_extent = _Extent == dynamic_extent
290 || _Extent <= __gnu_cxx::__int_traits<_IndexType>::__max;
292 template<
typename _Extents>
293 constexpr const array<size_t, _Extents::rank()>&
294 __static_extents() noexcept
295 {
return _Extents::_Storage::_S_static_extents(); }
297 template<
typename _Extents>
298 constexpr span<const size_t>
299 __static_extents(
size_t __begin,
size_t __end)
noexcept
301 const auto& __sta_exts = __static_extents<_Extents>();
302 return span<const size_t>(__sta_exts.data() + __begin, __end - __begin);
306 template<array _Extents>
307 constexpr auto __fwd_partial_prods = []
consteval
309 constexpr size_t __rank = _Extents.size();
310 std::array<size_t, __rank> __ret;
312 for (
size_t __r = 0; __r < __rank; ++__r)
315 if (
size_t __ext = _Extents[__r]; __ext != dynamic_extent)
322 template<array _Extents>
323 constexpr auto __rev_partial_prods = []
consteval
325 constexpr size_t __rank = _Extents.size();
326 std::array<size_t, __rank> __ret;
328 for (
size_t __r = __rank; __r > 0; --__r)
330 __ret[__r - 1] = __prod;
331 if (
size_t __ext = _Extents[__r - 1]; __ext != dynamic_extent)
337 template<
typename _Extents>
338 constexpr span<const typename _Extents::index_type>
339 __dynamic_extents(
const _Extents& __exts,
size_t __begin = 0,
340 size_t __end = _Extents::rank()) noexcept
341 {
return __exts._M_exts._M_dynamic_extents(__begin, __end); }
344#if __glibcxx_submdspan
347 explicit full_extent_t() =
default;
350 inline constexpr full_extent_t full_extent{};
352 template<
typename _OffsetType,
typename _ExtentType,
typename _Str
ideType>
355 static_assert(__is_standard_integer<_OffsetType>::value
356 || __detail::__integral_constant_like<_OffsetType>);
357 static_assert(__is_standard_integer<_ExtentType>::value
358 || __detail::__integral_constant_like<_ExtentType>);
359 static_assert(__is_standard_integer<_StrideType>::value
360 || __detail::__integral_constant_like<_StrideType>);
362 using offset_type = _OffsetType;
363 using extent_type = _ExtentType;
364 using stride_type = _StrideType;
366 [[no_unique_address]] offset_type offset{};
367 [[no_unique_address]] extent_type extent{};
368 [[no_unique_address]] stride_type stride{};
371 template<
typename _Mapping>
372 struct submdspan_mapping_result
374 [[no_unique_address]] _Mapping mapping = _Mapping();
379 template<
typename _IndexType,
size_t... _Extents>
382 static_assert(__is_standard_integer<_IndexType>::value,
383 "IndexType must be a signed or unsigned integer type");
385 (__mdspan::__valid_static_extent<_Extents, _IndexType> && ...),
386 "Extents must either be dynamic or representable as IndexType");
388 using _Storage = __mdspan::_ExtentsStorage<
389 _IndexType, array<size_t,
sizeof...(_Extents)>{_Extents...}>;
390 [[no_unique_address]] _Storage _M_exts;
393 using index_type = _IndexType;
394 using size_type = make_unsigned_t<index_type>;
395 using rank_type = size_t;
397 static constexpr rank_type
398 rank() noexcept {
return _Storage::_S_rank; }
400 static constexpr rank_type
401 rank_dynamic() noexcept {
return _Storage::_S_rank_dynamic; }
403 static constexpr size_t
404 static_extent(rank_type __r)
noexcept
406 __glibcxx_assert(__r < rank());
407 if constexpr (rank() == 0)
410 return _Storage::_S_static_extent(__r);
414 extent(rank_type __r)
const noexcept
416 __glibcxx_assert(__r < rank());
417 if constexpr (rank() == 0)
420 return _M_exts._M_extent(__r);
424 extents() noexcept = default;
427 static consteval
bool
428 _S_is_less_dynamic(
size_t __ext,
size_t __oext)
429 {
return (__ext != dynamic_extent) && (__oext == dynamic_extent); }
431 template<
typename _OIndexType,
size_t... _OExtents>
432 static consteval bool
435 return (_S_is_less_dynamic(_Extents, _OExtents) || ...)
436 || (__gnu_cxx::__int_traits<index_type>::__max
437 < __gnu_cxx::__int_traits<_OIndexType>::__max);
440 template<
size_t... _OExtents>
441 static consteval bool
442 _S_is_compatible_extents()
444 if constexpr (
sizeof...(_OExtents) != rank())
447 return ((_OExtents == dynamic_extent || _Extents == dynamic_extent
448 || _OExtents == _Extents) && ...);
452 template<
typename _OIndexType,
size_t... _OExtents>
453 requires (_S_is_compatible_extents<_OExtents...>())
454 constexpr explicit(_S_ctor_explicit<_OIndexType, _OExtents...>())
455 extents(
const extents<_OIndexType, _OExtents...>& __other) noexcept
456 : _M_exts(__other._M_exts)
459 template<__mdspan::__val
id_index_type<index_type>... _OIndexTypes>
460 requires (
sizeof...(_OIndexTypes) == rank()
461 ||
sizeof...(_OIndexTypes) == rank_dynamic())
462 constexpr explicit extents(_OIndexTypes... __exts) noexcept
463 : _M_exts(span<
const _IndexType,
sizeof...(_OIndexTypes)>(
464 initializer_list{
static_cast<_IndexType
>(
std::move(__exts))...}))
467 template<
typename _OIndexType,
size_t _Nm>
468 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
469 && (_Nm == rank() || _Nm == rank_dynamic())
470 constexpr explicit(_Nm != rank_dynamic())
471 extents(span<_OIndexType, _Nm> __exts) noexcept
472 : _M_exts(span<const _OIndexType, _Nm>(__exts))
475 template<
typename _OIndexType,
size_t _Nm>
476 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
477 && (_Nm == rank() || _Nm == rank_dynamic())
478 constexpr explicit(_Nm != rank_dynamic())
479 extents(
const array<_OIndexType, _Nm>& __exts) noexcept
480 : _M_exts(span<const _OIndexType, _Nm>(__exts))
483 template<
typename _OIndexType,
size_t... _OExtents>
484 friend constexpr bool
485 operator==(
const extents& __self,
486 const extents<_OIndexType, _OExtents...>& __other)
noexcept
488 if constexpr (!_S_is_compatible_extents<_OExtents...>())
492 auto __impl = [&__self, &__other]<
size_t... _Counts>(
494 {
return (cmp_equal(__self.extent(_Counts),
495 __other.extent(_Counts)) && ...); };
496 return __impl(make_index_sequence<__self.rank()>());
501 friend constexpr const array<size_t, rank()>&
502 __mdspan::__static_extents<extents>() noexcept;
504 friend constexpr span<const index_type>
505 __mdspan::__dynamic_extents<extents>(const extents&,
size_t,
size_t)
508 template<typename _OIndexType,
size_t... _OExtents>
509 friend class extents;
514 template<
typename _Tp,
size_t _Nm>
516 __contains_zero(span<_Tp, _Nm> __exts)
noexcept
518 for (
size_t __i = 0; __i < __exts.size(); ++__i)
519 if (__exts[__i] == 0)
524 template<
typename _Tp,
size_t _Nm>
526 __contains_zero(
const array<_Tp, _Nm>& __exts)
noexcept
527 {
return __contains_zero(span<const _Tp>(__exts)); }
529 template<
typename _Extents>
531 __empty(
const _Extents& __exts)
noexcept
533 if constexpr (__contains_zero(__static_extents<_Extents>()))
535 else if constexpr (_Extents::rank_dynamic() > 0)
536 return __contains_zero(__dynamic_extents(__exts));
541 template<
typename _Extents>
542 constexpr typename _Extents::index_type
543 __extents_prod(
const _Extents& __exts,
size_t __sta_prod,
size_t __begin,
544 size_t __end)
noexcept
549 size_t __ret = __sta_prod;
550 if constexpr (_Extents::rank_dynamic() > 0)
551 for (
auto __factor : __dynamic_extents(__exts, __begin, __end))
552 __ret *= size_t(__factor);
553 return static_cast<typename _Extents::index_type
>(__ret);
557 template<
typename _Extents>
558 constexpr typename _Extents::index_type
559 __fwd_prod(
const _Extents& __exts,
size_t __begin,
size_t __end)
noexcept
561 size_t __sta_prod = [__begin, __end] {
562 span<const size_t> __sta_exts
563 = __static_extents<_Extents>(__begin, __end);
565 for(
auto __ext : __sta_exts)
566 if (__ext != dynamic_extent)
570 return __extents_prod(__exts, __sta_prod, __begin, __end);
573 template<
typename _Extents>
574 constexpr typename _Extents::index_type
575 __fwd_prod(
const _Extents& __exts,
size_t __r)
noexcept
577 constexpr size_t __rank = _Extents::rank();
578 constexpr auto& __sta_exts = __static_extents<_Extents>();
579 if constexpr (__rank == 1)
581 else if constexpr (__rank == 2)
582 return __r == 0 ? 1 : __exts.extent(0);
583 else if constexpr (__all_dynamic(std::span(__sta_exts).first(__rank-1)))
584 return __extents_prod(__exts, 1, 0, __r);
587 size_t __sta_prod = __fwd_partial_prods<__sta_exts>[__r];
588 return __extents_prod(__exts, __sta_prod, 0, __r);
593 template<
typename _Extents>
594 constexpr typename _Extents::index_type
595 __rev_prod(
const _Extents& __exts,
size_t __r)
noexcept
597 constexpr size_t __rank = _Extents::rank();
598 constexpr auto& __sta_exts = __static_extents<_Extents>();
599 if constexpr (__rank == 1)
601 else if constexpr (__rank == 2)
602 return __r == 0 ? __exts.extent(1) : 1;
603 else if constexpr (__all_dynamic(std::span(__sta_exts).last(__rank-1)))
604 return __extents_prod(__exts, 1, __r + 1, __rank);
607 size_t __sta_prod = __rev_partial_prods<__sta_exts>[__r];
608 return __extents_prod(__exts, __sta_prod, __r + 1, __rank);
612 template<
typename _Extents>
613 constexpr typename _Extents::index_type
614 __size(
const _Extents& __exts)
noexcept
616 constexpr size_t __sta_prod = [] {
617 span<const size_t> __sta_exts = __static_extents<_Extents>();
619 for(
auto __ext : __sta_exts)
620 if (__ext != dynamic_extent)
624 return __extents_prod(__exts, __sta_prod, 0, _Extents::rank());
627 template<
typename _IndexType,
size_t... _Counts>
628 auto __build_dextents_type(integer_sequence<size_t, _Counts...>)
629 -> extents<_IndexType, ((void) _Counts, dynamic_extent)...>;
632 template<
typename _IndexType,
size_t _Rank>
633 using dextents =
decltype(__mdspan::__build_dextents_type<_IndexType>(
634 make_index_sequence<_Rank>()));
636#if __glibcxx_mdspan >= 202406L
637 template<
size_t _Rank,
typename _IndexType =
size_t>
638 using dims = dextents<_IndexType, _Rank>;
641 template<
typename... _Integrals>
642 requires (is_convertible_v<_Integrals, size_t> && ...)
643 explicit extents(_Integrals...) ->
644 extents<size_t, __detail::__maybe_static_ext<_Integrals>...>;
648 template<
typename _Extents>
654 template<
typename _Extents>
660 template<
typename _Extents>
664#ifdef __glibcxx_padded_layouts
665 template<
size_t _PaddingValue>
666 struct layout_left_padded
668 template<
typename _Extents>
672 template<
size_t _PaddingValue>
673 struct layout_right_padded
675 template<
typename _Extents>
682 template<
typename _Tp>
683 constexpr bool __is_extents =
false;
685 template<
typename _IndexType,
size_t... _Extents>
686 constexpr bool __is_extents<extents<_IndexType, _Extents...>> =
true;
688 template<
typename _Extents,
typename... _Indices>
689 constexpr typename _Extents::index_type
690 __linear_index_left(
const _Extents& __exts, _Indices... __indices)
693 using _IndexType =
typename _Extents::index_type;
694 _IndexType __res = 0;
695 if constexpr (
sizeof...(__indices) > 0)
697 _IndexType __mult = 1;
698 auto __update = [&, __pos = 0u](_IndexType __idx)
mutable
700 _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx, __exts.extent(__pos)));
701 __res += __idx * __mult;
702 __mult *= __exts.extent(__pos);
705 (__update(__indices), ...);
710 template<
typename _IndexType>
712 __static_quotient(std::span<const size_t> __sta_exts,
713 _IndexType __nom = __gnu_cxx::__int_traits<_IndexType>::__max)
715 for (
auto __factor : __sta_exts)
717 if (__factor != dynamic_extent)
718 __nom /= _IndexType(__factor);
725 template<
typename _Extents,
726 typename _IndexType =
typename _Extents::index_type>
727 requires __is_extents<_Extents>
729 __static_quotient(_IndexType __nom
730 = __gnu_cxx::__int_traits<_IndexType>::__max)
732 std::span<const size_t> __sta_exts = __static_extents<_Extents>();
733 return __static_quotient<_IndexType>(__sta_exts, __nom);
736 template<
typename _Extents>
738 __is_representable_extents(
const _Extents& __exts)
noexcept
740 using _IndexType = _Extents::index_type;
742 if constexpr (__contains_zero(__static_extents<_Extents>()))
746 constexpr auto __sta_quo = __static_quotient<_Extents>();
747 if constexpr (_Extents::rank_dynamic() == 0)
748 return __sta_quo != 0;
751 auto __dyn_exts = __dynamic_extents(__exts);
752 if (__contains_zero(__dyn_exts))
755 if constexpr (__sta_quo == 0)
759 auto __dyn_quo = _IndexType(__sta_quo);
760 for (
auto __factor : __dyn_exts)
762 __dyn_quo /= __factor;
772 template<
typename _Extents,
typename _IndexType>
773 concept __representable_size = _Extents::rank_dynamic() != 0
774 || __contains_zero(__static_extents<_Extents>())
775 || (__static_quotient<_Extents, _IndexType>() != 0);
777 template<
typename _Layout,
typename _Mapping>
778 concept __mapping_of =
779 is_same_v<
typename _Layout::template mapping<
780 typename _Mapping::extents_type>,
783 template<
template<
size_t>
typename _Layout,
typename _Mapping>
784 concept __padded_mapping_of = __mapping_of<
785 _Layout<_Mapping::padding_value>, _Mapping>;
787#ifdef __glibcxx_padded_layouts
788 template<
typename _Mapping>
789 constexpr bool __is_left_padded_mapping = __padded_mapping_of<
790 layout_left_padded, _Mapping>;
792 template<
typename _Mapping>
793 constexpr bool __is_right_padded_mapping = __padded_mapping_of<
794 layout_right_padded, _Mapping>;
797 template<
typename _PaddedMapping>
799 __get_static_stride()
800 {
return _PaddedMapping::_PaddedStorage::_S_static_stride; }
802 template<
typename _Mapping>
803 concept __standardized_mapping = __mapping_of<layout_left, _Mapping>
804 || __mapping_of<layout_right, _Mapping>
805 || __mapping_of<layout_stride, _Mapping>
806#ifdef __glibcxx_padded_layouts
807 || __is_left_padded_mapping<_Mapping>
808 || __is_right_padded_mapping<_Mapping>
813 class __internal_ctor
816 template<
typename _Mapping>
817 constexpr typename _Mapping::index_type
818 __offset(
const _Mapping& __m)
noexcept
820 using _IndexType =
typename _Mapping::index_type;
821 constexpr auto __rank = _Mapping::extents_type::rank();
823 if constexpr (__standardized_mapping<_Mapping>)
825 else if (__empty(__m.extents()))
829 auto __impl = [&__m]<
size_t... _Counts>(
index_sequence<_Counts...>)
830 {
return __m(((
void) _Counts, _IndexType(0))...); };
831 return __impl(make_index_sequence<__rank>());
835#ifdef __glibcxx_submdspan
836 template<
typename _Tp>
837 constexpr bool __is_strided_slice =
false;
839 template<
typename _OffsetType,
typename _ExtentType,
typename _Str
ideType>
840 constexpr bool __is_strided_slice<strided_slice<_OffsetType,
841 _ExtentType, _StrideType>> =
true;
843 template<
typename _IndexType,
typename _OIndexType>
845 __is_representable_integer(_OIndexType __value)
847 constexpr auto __min = __gnu_cxx::__int_traits<_IndexType>::__min;
848 constexpr auto __max = __gnu_cxx::__int_traits<_IndexType>::__max;
849 return std::cmp_less_equal(__min, __value)
850 && std::cmp_less_equal(__value, __max);
853 template<
typename _Tp>
854 constexpr bool __is_constant_wrapper =
false;
856 template<_CwFixedValue _Xv,
typename _Tp>
857 constexpr bool __is_constant_wrapper<constant_wrapper<_Xv, _Tp>>
860 template<
size_t _Index,
typename _Extents>
862 __extract_extent(
const _Extents& __exts)
864 using _IndexType =
typename _Extents::index_type;
865 return extents<_IndexType, _Extents::static_extent(_Index)>{
866 __exts.extent(_Index)};
869 template<
typename _IndexType,
typename... _Slices>
873 return (
static_cast<size_t>(!convertible_to<_Slices, _IndexType>)
877 template<
typename _IndexType,
typename... _Slices>
881 constexpr auto __rank =
sizeof...(_Slices);
882 constexpr auto __sub_rank = __subrank<_IndexType, _Slices...>();
883 auto __map = std::array<size_t, __sub_rank>{};
884 auto __is_int_like = std::array<bool, __rank>{
885 convertible_to<_Slices, _IndexType>...};
888 for (
size_t __k = 0; __k < __rank; ++__k)
889 if (!__is_int_like[__k])
896 template<
typename _Extents>
897 class layout_left::mapping
900 using extents_type = _Extents;
901 using index_type =
typename extents_type::index_type;
902 using size_type =
typename extents_type::size_type;
903 using rank_type =
typename extents_type::rank_type;
904 using layout_type = layout_left;
906 static_assert(__mdspan::__representable_size<extents_type, index_type>,
907 "The size of extents_type must be representable as index_type");
910 mapping() noexcept = default;
913 mapping(const mapping&) noexcept = default;
916 mapping(const extents_type& __extents) noexcept
917 : _M_extents(__extents)
918 { __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); }
920 template<
typename _OExtents>
921 requires is_constructible_v<extents_type, _OExtents>
922 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
923 mapping(
const mapping<_OExtents>& __other) noexcept
924 : mapping(__other.extents(), __mdspan::__internal_ctor{})
927 template<
typename _OExtents>
928 requires (extents_type::rank() <= 1)
929 && is_constructible_v<extents_type, _OExtents>
930 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
931 mapping(
const layout_right::mapping<_OExtents>& __other) noexcept
932 : mapping(__other.extents(), __mdspan::__internal_ctor{})
936 template<
typename _OExtents>
937 requires is_constructible_v<extents_type, _OExtents>
938 constexpr explicit(extents_type::rank() > 0)
939 mapping(
const layout_stride::mapping<_OExtents>& __other) noexcept
940 : mapping(__other.extents(), __mdspan::__internal_ctor{})
941 { __glibcxx_assert(*
this == __other); }
943#if __glibcxx_padded_layouts
944 template<
typename _LeftpadMapping>
945 requires __mdspan::__is_left_padded_mapping<_LeftpadMapping>
946 && is_constructible_v<extents_type,
947 typename _LeftpadMapping::extents_type>
949 explicit(!is_convertible_v<
typename _LeftpadMapping::extents_type,
951 mapping(
const _LeftpadMapping& __other) noexcept
952 : mapping(__other.extents(), __mdspan::__internal_ctor{})
954 constexpr size_t __ostride_sta
955 = __mdspan::__get_static_stride<_LeftpadMapping>();
957 if constexpr (extents_type::rank() > 1)
959 if constexpr (extents_type::static_extent(0) != dynamic_extent
960 && __ostride_sta != dynamic_extent)
961 static_assert(extents_type::static_extent(0) == __ostride_sta);
963 __glibcxx_assert(__other.stride(1)
964 == __other.extents().extent(0));
970 operator=(
const mapping&)
noexcept =
default;
972 constexpr const extents_type&
973 extents() const noexcept {
return _M_extents; }
976 required_span_size() const noexcept
977 {
return __mdspan::__size(_M_extents); }
981 template<__mdspan::__val
id_index_type<index_type>... _Indices>
982 requires (
sizeof...(_Indices) == extents_type::rank())
984 operator()(_Indices... __indices)
const noexcept
986 return __mdspan::__linear_index_left(_M_extents,
987 static_cast<index_type
>(
std::move(__indices))...);
990 static constexpr bool
991 is_always_unique() noexcept {
return true; }
993 static constexpr bool
994 is_always_exhaustive() noexcept {
return true; }
996 static constexpr bool
997 is_always_strided() noexcept {
return true; }
999 static constexpr bool
1000 is_unique() noexcept {
return true; }
1002 static constexpr bool
1003 is_exhaustive() noexcept {
return true; }
1005 static constexpr bool
1006 is_strided() noexcept {
return true; }
1008 constexpr index_type
1009 stride(rank_type __i)
const noexcept
1010 requires (extents_type::rank() > 0)
1012 __glibcxx_assert(__i < extents_type::rank());
1013 return __mdspan::__fwd_prod(_M_extents, __i);
1016 template<
typename _OExtents>
1017 requires (extents_type::rank() == _OExtents::rank())
1018 friend constexpr bool
1019 operator==(
const mapping& __self,
const mapping<_OExtents>& __other)
1021 {
return __self.extents() == __other.extents(); }
1024 template<
typename _OExtents>
1026 mapping(
const _OExtents& __oexts, __mdspan::__internal_ctor) noexcept
1027 : _M_extents(__oexts)
1029 static_assert(__mdspan::__representable_size<_OExtents, index_type>,
1030 "The size of OtherExtents must be representable as index_type");
1031 __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents));
1034 [[no_unique_address]] extents_type _M_extents{};
1039 template<
typename _Extents,
typename... _Indices>
1040 constexpr typename _Extents::index_type
1041 __linear_index_right(
const _Extents& __exts, _Indices... __indices)
1044 using _IndexType =
typename _Extents::index_type;
1045 array<_IndexType,
sizeof...(__indices)> __ind_arr{__indices...};
1046 _IndexType __res = 0;
1047 if constexpr (
sizeof...(__indices) > 0)
1049 _IndexType __mult = 1;
1050 auto __update = [&, __pos = __exts.rank()](_IndexType)
mutable
1053 _GLIBCXX_DEBUG_ASSERT(cmp_less(__ind_arr[__pos],
1054 __exts.extent(__pos)));
1055 __res += __ind_arr[__pos] * __mult;
1056 __mult *= __exts.extent(__pos);
1058 (__update(__indices), ...);
1064 template<
typename _Extents>
1065 class layout_right::mapping
1068 using extents_type = _Extents;
1069 using index_type =
typename extents_type::index_type;
1070 using size_type =
typename extents_type::size_type;
1071 using rank_type =
typename extents_type::rank_type;
1072 using layout_type = layout_right;
1074 static_assert(__mdspan::__representable_size<extents_type, index_type>,
1075 "The size of extents_type must be representable as index_type");
1078 mapping() noexcept = default;
1081 mapping(const mapping&) noexcept = default;
1084 mapping(const extents_type& __extents) noexcept
1085 : _M_extents(__extents)
1086 { __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); }
1088 template<
typename _OExtents>
1089 requires is_constructible_v<extents_type, _OExtents>
1090 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
1091 mapping(
const mapping<_OExtents>& __other) noexcept
1092 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1095 template<
typename _OExtents>
1096 requires (extents_type::rank() <= 1)
1097 && is_constructible_v<extents_type, _OExtents>
1098 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
1099 mapping(
const layout_left::mapping<_OExtents>& __other) noexcept
1100 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1103 template<
typename _OExtents>
1104 requires is_constructible_v<extents_type, _OExtents>
1105 constexpr explicit(extents_type::rank() > 0)
1106 mapping(
const layout_stride::mapping<_OExtents>& __other) noexcept
1107 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1108 { __glibcxx_assert(*
this == __other); }
1110#if __glibcxx_padded_layouts
1111 template<
typename _RightPaddedMapping>
1112 requires __mdspan::__is_right_padded_mapping<_RightPaddedMapping>
1113 && is_constructible_v<extents_type,
1114 typename _RightPaddedMapping::extents_type>
1116 explicit(!is_convertible_v<
typename _RightPaddedMapping::extents_type,
1118 mapping(
const _RightPaddedMapping& __other) noexcept
1119 : mapping(__other.extents(), __mdspan::__internal_ctor{})
1121 constexpr size_t __rank = extents_type::rank();
1122 constexpr size_t __ostride_sta
1123 = __mdspan::__get_static_stride<_RightPaddedMapping>();
1125 if constexpr (__rank > 1)
1127 if constexpr (extents_type::static_extent(__rank - 1) != dynamic_extent
1128 && __ostride_sta != dynamic_extent)
1129 static_assert(extents_type::static_extent(__rank - 1)
1132 __glibcxx_assert(__other.stride(__rank - 2)
1133 == __other.extents().extent(__rank - 1));
1139 operator=(
const mapping&)
noexcept =
default;
1141 constexpr const extents_type&
1142 extents() const noexcept {
return _M_extents; }
1144 constexpr index_type
1145 required_span_size() const noexcept
1146 {
return __mdspan::__size(_M_extents); }
1150 template<__mdspan::__val
id_index_type<index_type>... _Indices>
1151 requires (
sizeof...(_Indices) == extents_type::rank())
1152 constexpr index_type
1153 operator()(_Indices... __indices)
const noexcept
1155 return __mdspan::__linear_index_right(
1156 _M_extents,
static_cast<index_type
>(
std::move(__indices))...);
1159 static constexpr bool
1160 is_always_unique() noexcept
1163 static constexpr bool
1164 is_always_exhaustive() noexcept
1167 static constexpr bool
1168 is_always_strided() noexcept
1171 static constexpr bool
1172 is_unique() noexcept
1175 static constexpr bool
1176 is_exhaustive() noexcept
1179 static constexpr bool
1180 is_strided() noexcept
1183 constexpr index_type
1184 stride(rank_type __i)
const noexcept
1185 requires (extents_type::rank() > 0)
1187 __glibcxx_assert(__i < extents_type::rank());
1188 return __mdspan::__rev_prod(_M_extents, __i);
1191 template<
typename _OExtents>
1192 requires (extents_type::rank() == _OExtents::rank())
1193 friend constexpr bool
1194 operator==(
const mapping& __self,
const mapping<_OExtents>& __other)
1196 {
return __self.extents() == __other.extents(); }
1199 template<
typename _OExtents>
1201 mapping(
const _OExtents& __oexts, __mdspan::__internal_ctor) noexcept
1202 : _M_extents(__oexts)
1204 static_assert(__mdspan::__representable_size<_OExtents, index_type>,
1205 "The size of OtherExtents must be representable as index_type");
1206 __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents));
1209 [[no_unique_address]] extents_type _M_extents{};
1214 template<
typename _Mp>
1215 concept __mapping_alike =
requires
1217 requires __is_extents<typename _Mp::extents_type>;
1218 { _Mp::is_always_strided() } -> same_as<bool>;
1219 { _Mp::is_always_exhaustive() } -> same_as<bool>;
1220 { _Mp::is_always_unique() } -> same_as<bool>;
1221 bool_constant<_Mp::is_always_strided()>::value;
1222 bool_constant<_Mp::is_always_exhaustive()>::value;
1223 bool_constant<_Mp::is_always_unique()>::value;
1226 template<
typename _Mapping,
typename... _Indices>
1227 constexpr typename _Mapping::index_type
1228 __linear_index_strides(
const _Mapping& __m, _Indices... __indices)
1231 using _IndexType =
typename _Mapping::index_type;
1232 _IndexType __res = 0;
1233 if constexpr (
sizeof...(__indices) > 0)
1235 auto __update = [&, __pos = 0u](_IndexType __idx)
mutable
1237 _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx,
1238 __m.extents().extent(__pos)));
1239 __res += __idx * __m.stride(__pos++);
1241 (__update(__indices), ...);
1247 template<
typename _Extents>
1248 class layout_stride::mapping
1251 using extents_type = _Extents;
1252 using index_type =
typename extents_type::index_type;
1253 using size_type =
typename extents_type::size_type;
1254 using rank_type =
typename extents_type::rank_type;
1255 using layout_type = layout_stride;
1257 static_assert(__mdspan::__representable_size<extents_type, index_type>,
1258 "The size of extents_type must be representable as index_type");
1265 size_t __stride = 1;
1266 for (
size_t __i = extents_type::rank(); __i > 0; --__i)
1268 _M_strides[__i - 1] = index_type(__stride);
1269 __stride *= size_t(_M_extents.extent(__i - 1));
1274 mapping(
const mapping&)
noexcept =
default;
1276 template<
typename _OIndexType>
1277 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
1279 mapping(
const extents_type& __exts,
1280 span<_OIndexType, extents_type::rank()> __strides) noexcept
1281 : _M_extents(__exts)
1283 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
1284 _M_strides[__i] = index_type(as_const(__strides[__i]));
1287 template<
typename _OIndexType>
1288 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
1290 mapping(
const extents_type& __exts,
1291 const array<_OIndexType, extents_type::rank()>& __strides)
1294 span<
const _OIndexType, extents_type::rank()>(__strides))
1297 template<__mdspan::__mapping_alike _Str
idedMapping>
1298 requires (is_constructible_v<extents_type,
1299 typename _StridedMapping::extents_type>
1300 && _StridedMapping::is_always_unique()
1301 && _StridedMapping::is_always_strided())
1302 constexpr explicit(!(
1303 is_convertible_v<typename _StridedMapping::extents_type, extents_type>
1304 && __mdspan::__standardized_mapping<_StridedMapping>))
1305 mapping(
const _StridedMapping& __other) noexcept
1306 : _M_extents(__other.extents())
1308 using _OIndexType = _StridedMapping::index_type;
1309 using _OExtents = _StridedMapping::extents_type;
1311 __glibcxx_assert(__mdspan::__offset(__other) == 0);
1312 static_assert(__mdspan::__representable_size<_OExtents, index_type>,
1313 "The size of StridedMapping::extents_type must be representable as"
1315 if constexpr (cmp_greater(__gnu_cxx::__int_traits<_OIndexType>::__max,
1316 __gnu_cxx::__int_traits<index_type>::__max))
1317 __glibcxx_assert(!cmp_less(
1318 __gnu_cxx::__int_traits<index_type>::__max,
1319 __other.required_span_size())
1320 &&
"other.required_span_size() must be representable"
1322 if constexpr (extents_type::rank() > 0)
1323 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
1324 _M_strides[__i] = index_type(__other.stride(__i));
1328 operator=(
const mapping&)
noexcept =
default;
1330 constexpr const extents_type&
1331 extents() const noexcept {
return _M_extents; }
1333 constexpr array<index_type, extents_type::rank()>
1334 strides() const noexcept
1336 array<index_type, extents_type::rank()> __ret;
1337 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
1338 __ret[__i] = _M_strides[__i];
1342 constexpr index_type
1343 required_span_size() const noexcept
1345 if (__mdspan::__empty(_M_extents))
1348 index_type __ret = 1;
1349 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
1350 __ret += (_M_extents.extent(__i) - 1) * _M_strides[__i];
1356 template<__mdspan::__val
id_index_type<index_type>... _Indices>
1357 requires (
sizeof...(_Indices) == extents_type::rank())
1358 constexpr index_type
1359 operator()(_Indices... __indices)
const noexcept
1361 return __mdspan::__linear_index_strides(*
this,
1362 static_cast<index_type
>(
std::move(__indices))...);
1365 static constexpr bool
1366 is_always_unique() noexcept {
return true; }
1370 static constexpr bool
1371 is_always_exhaustive() noexcept
1373 return (_Extents::rank() == 0) || __mdspan::__contains_zero(
1374 __mdspan::__static_extents<extents_type>());
1377 static constexpr bool
1378 is_always_strided() noexcept {
return true; }
1380 static constexpr bool
1381 is_unique() noexcept {
return true; }
1386 is_exhaustive() const noexcept
1388 if constexpr (!is_always_exhaustive())
1390 auto __size = __mdspan::__size(_M_extents);
1392 return __size == required_span_size();
1397 static constexpr bool
1398 is_strided() noexcept {
return true; }
1400 constexpr index_type
1401 stride(rank_type __r)
const noexcept {
return _M_strides[__r]; }
1403 template<__mdspan::__mapping_alike _OMapping>
1404 requires ((extents_type::rank() == _OMapping::extents_type::rank())
1405 && _OMapping::is_always_strided())
1406 friend constexpr bool
1407 operator==(
const mapping& __self,
const _OMapping& __other)
noexcept
1409 if (__self.extents() != __other.extents())
1411 if constexpr (extents_type::rank() > 0)
1412 for (
size_t __i = 0; __i < extents_type::rank(); ++__i)
1413 if (!cmp_equal(__self.stride(__i), __other.stride(__i)))
1415 return __mdspan::__offset(__other) == 0;
1419 using _Strides =
typename __array_traits<index_type,
1420 extents_type::rank()>::_Type;
1421 [[no_unique_address]] extents_type _M_extents;
1422 [[no_unique_address]] _Strides _M_strides;
1425#ifdef __glibcxx_padded_layouts
1429 __least_multiple(
size_t __x,
size_t __y)
1433 return (__y / __x + (__y % __x != 0)) * __x ;
1436 template<
typename _IndexType>
1438 __is_representable_least_multiple(
size_t __x,
size_t __y)
1440 constexpr auto __y_max = __gnu_cxx::__int_traits<_IndexType>::__max;
1441 if(std::cmp_greater(__y, __y_max))
1447 auto __max_delta = __y_max -
static_cast<_IndexType
>(__y);
1448 auto __y_mod_x = __y % __x;
1449 auto __delta = (__y_mod_x == 0) ?
size_t(0) : (__x - __y_mod_x);
1450 return std::cmp_less_equal(__delta, __max_delta);
1453 template<
typename _Extents,
size_t _PaddingValue,
typename _LayoutTraits,
1454 size_t _Rank = _Extents::rank()>
1455 concept __valid_static_stride = (_Extents::rank() <= 1)
1456 || (_PaddingValue == dynamic_extent)
1457 || (_Extents::static_extent(_LayoutTraits::_S_ext_idx) == dynamic_extent)
1458 || (__is_representable_least_multiple<size_t>(
1459 _PaddingValue, _Extents::static_extent(_LayoutTraits::_S_ext_idx)));
1461 template<
size_t _PaddedStride,
typename _Extents,
1462 typename _LayoutTraits>
1464 __is_representable_padded_size()
1466 using _IndexType =
typename _Extents::index_type;
1467 auto __sta_exts = __static_extents<_Extents>(
1468 _LayoutTraits::_S_unpad_begin, _LayoutTraits::_S_unpad_end);
1469 size_t __max = __gnu_cxx::__int_traits<_IndexType>::__max;
1470 return __static_quotient(__sta_exts, __max / _PaddedStride) != 0;
1473 template<
typename _Extents,
size_t _PaddedStride,
typename _LayoutTraits,
1474 size_t _Rank = _Extents::rank()>
1475 concept __valid_padded_size = (_Rank <= 1)
1476 || (_PaddedStride == dynamic_extent)
1477 || (!__all_static(__static_extents<_Extents>()))
1478 || (__contains_zero(__static_extents<_Extents>()))
1479 || (__is_representable_padded_size<_PaddedStride, _Extents,
1482 template<
typename _Extents,
typename _Stride,
typename... _Indices>
1483 constexpr typename _Extents::index_type
1484 __linear_index_leftpad(
const _Extents& __exts, _Stride __stride,
1485 _Indices... __indices)
1488 using _IndexType =
typename _Extents::index_type;
1489 _IndexType __res = 0;
1490 if constexpr (
sizeof...(__indices) > 0)
1492 _IndexType __mult = 1;
1494 auto __update_rest = [&, __pos = 1u](_IndexType __idx)
mutable
1496 __res += __idx * __mult;
1497 __mult *= __exts.extent(__pos);
1501 auto __update = [&](_IndexType __idx,
auto... __rest)
1504 __mult = __stride.extent(0);
1505 (__update_rest(__rest), ...);
1507 __update(__indices...);
1512 template<
typename _Extents,
typename _Stride,
typename... _Indices>
1513 constexpr typename _Extents::index_type
1514 __linear_index_rightpad(
const _Extents& __exts, _Stride __stride,
1515 _Indices... __indices)
1518 using _IndexType =
typename _Extents::index_type;
1519 _IndexType __res = 0;
1520 if constexpr (
sizeof...(__indices) > 0)
1522 _IndexType __mult = 1;
1523 array<_IndexType,
sizeof...(__indices)> __ind_arr{__indices...};
1525 auto __update_rest = [&, __pos = __exts.rank()-1](_IndexType)
mutable
1528 __res += __ind_arr[__pos] * __mult;
1529 __mult *= __exts.extent(__pos);
1532 auto __update = [&](_IndexType,
auto... __rest)
1534 __res += __ind_arr[__exts.rank() - 1];
1535 __mult = __stride.extent(0);
1536 (__update_rest(__rest), ...);
1538 __update(__indices...);
1543 template<
size_t _Rank>
1544 struct _LeftPaddedLayoutTraits
1546 using _LayoutSame = layout_left;
1547 using _LayoutOther = layout_right;
1549 constexpr static const size_t _S_ext_idx = 0;
1550 constexpr static const size_t _S_stride_idx = 1;
1551 constexpr static const size_t _S_unpad_begin = 1;
1552 constexpr static const size_t _S_unpad_end = _Rank;
1554 template<
typename _IndexType,
size_t _StaticStride,
size_t..._Extents>
1555 constexpr static auto
1556 _S_make_padded_extent(
1557 extents<_IndexType, _StaticStride> __stride,
1558 const extents<_IndexType, _Extents...>& __exts)
1560 auto __impl = [&]<
size_t... _Is>(integer_sequence<size_t, _Is...>)
1562 return extents<_IndexType, _StaticStride,
1563 (_Extents...[_Is + 1])...>{
1564 __stride.extent(0), __exts.extent(_Is + 1)...};
1566 return __impl(make_index_sequence<
sizeof...(_Extents) - 1>());
1570 template<
size_t _Rank>
1571 struct _RightPaddedLayoutTraits
1573 using _LayoutSame = layout_right;
1574 using _LayoutOther = layout_left;
1576 constexpr static size_t _S_ext_idx = _Rank - 1;
1577 constexpr static size_t _S_stride_idx = _Rank - 2;
1578 constexpr static size_t _S_unpad_begin = 0;
1579 constexpr static size_t _S_unpad_end = _Rank - 1;
1581 template<
typename _IndexType,
size_t _StaticStride,
size_t..._Extents>
1582 constexpr static auto
1583 _S_make_padded_extent(
1584 extents<_IndexType, _StaticStride> __stride,
1585 const extents<_IndexType, _Extents...>& __exts)
1587 auto __impl = [&]<
size_t... _Is>(integer_sequence<size_t, _Is...>)
1589 return extents<_IndexType, (_Extents...[_Is])..., _StaticStride>{
1590 __exts.extent(_Is)..., __stride.extent(0)};
1592 return __impl(make_index_sequence<
sizeof...(_Extents) - 1>());
1596 template<
size_t _PaddingValue,
typename _Extents,
typename _LayoutTraits>
1597 class _PaddedStorage
1599 using _LayoutSame =
typename _LayoutTraits::_LayoutSame;
1602 using _IndexType =
typename _Extents::index_type;
1603 constexpr static size_t _S_rank = _Extents::rank();
1607 static_assert((_PaddingValue == dynamic_extent)
1608 || (cmp_less_equal(_PaddingValue,
1609 __gnu_cxx::__int_traits<_IndexType>::__max)),
1610 "padding_value must be representable as index_type");
1612 static_assert(__representable_size<_Extents, _IndexType>,
1613 "The size of extents_type must be representable as index_type");
1615 static_assert(__valid_static_stride<_Extents, _PaddingValue,
1617 "The padded stride must be representable as size_t");
1619 static constexpr size_t _S_static_stride = []
consteval
1621 constexpr size_t __rank = _Extents::rank();
1622 if constexpr (__rank <= 1)
1626 constexpr size_t __ext_idx = _LayoutTraits::_S_ext_idx;
1627 constexpr size_t __sta_ext = _Extents::static_extent(__ext_idx);
1628 if constexpr (__sta_ext == 0)
1630 else if constexpr (_PaddingValue == dynamic_extent
1631 || __sta_ext == dynamic_extent)
1632 return dynamic_extent;
1634 return __least_multiple(_PaddingValue, __sta_ext);
1638 static_assert(_S_static_stride == dynamic_extent
1639 || cmp_less_equal(_S_static_stride,
1640 __gnu_cxx::__int_traits<_IndexType>::__max),
1641 "Padded stride must be representable as index_type");
1643 static_assert(__valid_padded_size<_Extents, _S_static_stride,
1647 _PaddedStorage() noexcept
1649 if constexpr (_S_rank > 1)
1650 if constexpr (_S_static_stride == dynamic_extent
1651 && _S_static_padextent() != dynamic_extent)
1652 _M_stride = _Stride{_S_static_padextent()};
1656 _PaddedStorage(
const _Extents& __exts)
1657 : _M_extents(__exts)
1659 if constexpr (!__all_static(__static_extents<_Extents>()))
1660 __glibcxx_assert(__is_representable_extents(_M_extents));
1662 if constexpr (_S_rank > 1)
1664 _IndexType __stride;
1665 if constexpr (_PaddingValue == dynamic_extent)
1666 __stride = _M_padextent();
1667 else if constexpr (_S_static_padextent() != dynamic_extent)
1672 __is_representable_least_multiple<_IndexType>(
1673 _PaddingValue, _M_padextent()));
1675 __stride =
static_cast<_IndexType
>(
1676 __least_multiple(_PaddingValue, _M_padextent()));
1678 __glibcxx_assert(__is_representable_extents(
1679 _LayoutTraits::_S_make_padded_extent(
1680 std::dextents<_IndexType, 1>{__stride},
1683 _M_stride = _Stride{__stride};
1688 _PaddedStorage(
const _Extents& __exts, _IndexType __pad)
1689 : _M_extents(__exts)
1691 if constexpr (_PaddingValue != dynamic_extent)
1692 __glibcxx_assert(cmp_equal(_PaddingValue, __pad));
1693 if constexpr (_S_rank > 1 && _S_static_stride == dynamic_extent)
1696 __is_representable_least_multiple<_IndexType>(
1697 __pad, _M_padextent()));
1699 _M_stride = _Stride{
static_cast<_IndexType
>(
1700 __least_multiple(__pad, _M_padextent()))};
1702 __glibcxx_assert(__is_representable_extents(
1703 _LayoutTraits::_S_make_padded_extent(
1704 _M_stride, _M_extents)));
1708 template<
typename _OExtents>
1711 const typename _LayoutSame::template mapping<_OExtents>& __other)
1712 : _PaddedStorage(_Extents(__other.extents()))
1714 constexpr size_t __stride_idx = _LayoutTraits::_S_stride_idx;
1715 constexpr size_t __ext_idx = _LayoutTraits::_S_ext_idx;
1716 if constexpr (_S_rank > 1 && _PaddingValue != dynamic_extent)
1718 static_assert(_S_static_stride == dynamic_extent
1719 || _OExtents::static_extent(__ext_idx) == dynamic_extent
1720 || _S_static_stride == _OExtents::static_extent(__ext_idx),
1721 "The padded stride must be compatible with other");
1723 if constexpr (_S_static_stride == dynamic_extent
1724 || _OExtents::static_extent(__stride_idx) == dynamic_extent)
1725 __glibcxx_assert(std::cmp_equal(_M_padstride(),
1730 template<
typename _OExtents>
1732 _PaddedStorage(
const typename layout_stride::mapping<_OExtents>&
1734 : _M_extents(__other.extents())
1736 __glibcxx_assert(cmp_less_equal(__other.required_span_size(),
1740 constexpr size_t __stride_idx = _LayoutTraits::_S_stride_idx;
1741 if constexpr (_S_rank > 1)
1743 if constexpr (_PaddingValue != dynamic_extent)
1744 __glibcxx_assert(cmp_equal(__other.stride(__stride_idx),
1745 _M_calc_padstride())
1746 &&
"The padded stride must be compatible with other");
1747 if constexpr (_S_static_stride == dynamic_extent)
1748 _M_stride = _Stride{__other.stride(__stride_idx)};
1752 template<
typename _SamePaddedMapping>
1754 _PaddedStorage(_LayoutTraits::_LayoutSame,
1755 const _SamePaddedMapping& __other)
1756 : _M_extents(__other.extents())
1758 if constexpr (_S_rank > 1)
1760 static_assert(_PaddingValue == dynamic_extent
1761 || _SamePaddedMapping::padding_value == dynamic_extent
1762 || _PaddingValue == _SamePaddedMapping::padding_value,
1763 "If neither PaddingValue is dynamic_extent, then they must "
1766 constexpr size_t __stride_idx = _LayoutTraits::_S_stride_idx;
1767 if constexpr (_PaddingValue != dynamic_extent)
1768 __glibcxx_assert(cmp_equal(__other.stride(__stride_idx),
1769 _M_calc_padstride())
1770 &&
"The padded stride must be compatible with other");
1771 if constexpr (_S_static_stride == dynamic_extent)
1772 _M_stride = _Stride{__other.stride(__stride_idx)};
1774 __glibcxx_assert(cmp_less_equal(__other.required_span_size(),
1775 __gnu_cxx::__int_traits<_IndexType>::__max));
1778 template<
typename _OtherPaddedMapping>
1780 _PaddedStorage(_LayoutTraits::_LayoutOther,
1781 const _OtherPaddedMapping& __other) noexcept
1782 : _M_extents(__other.extents())
1784 __glibcxx_assert(cmp_less_equal(__other.required_span_size(),
1785 __gnu_cxx::__int_traits<_IndexType>::__max));
1788 static constexpr bool
1789 _M_is_always_exhaustive() noexcept
1791 if constexpr (_S_rank <= 1)
1794 return _S_static_padextent() != dynamic_extent
1795 && _S_static_stride != dynamic_extent
1796 && _S_static_padextent() == _S_static_stride;
1800 _M_is_exhaustive() const noexcept
1802 if constexpr (_M_is_always_exhaustive())
1805 return cmp_equal(_M_padextent(), _M_padstride());
1808 constexpr static size_t
1809 _S_static_padextent() noexcept
1810 {
return _Extents::static_extent(_LayoutTraits::_S_ext_idx); }
1812 constexpr _IndexType
1813 _M_padextent() const noexcept
1814 {
return _M_extents.extent(_LayoutTraits::_S_ext_idx); }
1816 constexpr _IndexType
1817 _M_calc_padstride() const noexcept
1819 if constexpr (_S_static_stride != dynamic_extent)
1820 return _S_static_stride;
1821 else if constexpr (_PaddingValue != dynamic_extent)
1822 return __least_multiple(_PaddingValue, _M_padextent());
1824 return _M_padextent();
1827 constexpr _IndexType
1828 _M_padstride() const noexcept
1829 {
return _M_stride.extent(0); }
1831 constexpr _IndexType
1832 _M_required_span_size() const noexcept
1834 if constexpr (_S_rank == 0)
1836 else if (__mdspan::__empty(_M_extents))
1840 size_t __stride =
static_cast<size_t>(_M_padstride());
1841 size_t __prod_rest = __mdspan::__fwd_prod(_M_extents,
1842 _LayoutTraits::_S_unpad_begin, _LayoutTraits::_S_unpad_end);
1843 size_t __delta = _M_padstride() - _M_padextent();
1844 return static_cast<_IndexType
>(__stride * __prod_rest - __delta);
1848 template<
typename _SamePaddedMapping>
1850 _M_equal(
const _SamePaddedMapping& __other)
const noexcept
1852 return _M_extents == __other.extents()
1854 || cmp_equal(_M_stride.extent(0),
1855 __other.stride(_LayoutTraits::_S_stride_idx)));
1858 using _Stride = std::extents<_IndexType, _S_static_stride>;
1859 [[no_unique_address]] _Stride _M_stride;
1860 [[no_unique_address]] _Extents _M_extents;
1864 template<
size_t _PaddingValue>
1865 template<
typename _Extents>
1866 class layout_left_padded<_PaddingValue>::mapping
1869 static constexpr size_t padding_value = _PaddingValue;
1871 using extents_type = _Extents;
1872 using index_type =
typename extents_type::index_type;
1873 using size_type =
typename extents_type::size_type;
1874 using rank_type =
typename extents_type::rank_type;
1875 using layout_type = layout_left_padded<padding_value>;
1878 static constexpr size_t _S_rank = extents_type::rank();
1879 using _PaddedStorage = __mdspan::_PaddedStorage<_PaddingValue,
1880 _Extents, __mdspan::_LeftPaddedLayoutTraits<_S_rank>>;
1881 [[no_unique_address]] _PaddedStorage _M_storage;
1883 consteval friend size_t
1884 __mdspan::__get_static_stride<mapping>();
1886 constexpr index_type
1887 _M_extent(
size_t __r)
const noexcept
1888 {
return _M_storage._M_extents.extent(__r); }
1890 constexpr index_type
1891 _M_padstride() const noexcept
1892 {
return _M_storage._M_stride.extent(0); }
1900 mapping(
const mapping&)
noexcept =
default;
1903 mapping(
const extents_type& __exts)
1904 : _M_storage(__exts)
1907 template<__mdspan::__val
id_index_type<index_type> _OIndexType>
1909 mapping(
const extents_type& __exts, _OIndexType __pad)
1910 : _M_storage(__exts,
1911 __mdspan::__index_type_cast<index_type>(std::
move(__pad)))
1914 template<
typename _OExtents>
1915 requires is_constructible_v<extents_type, _OExtents>
1916 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
1917 mapping(
const layout_left::mapping<_OExtents>& __other)
1918 : _M_storage(__other)
1921 template<
typename _OExtents>
1922 requires is_constructible_v<_OExtents, extents_type>
1923 constexpr explicit(_OExtents::rank() > 0)
1924 mapping(
const typename layout_stride::mapping<_OExtents>& __other)
1925 : _M_storage(__other)
1926 { __glibcxx_assert(*
this == __other); }
1928 template<
typename _LeftpadMapping>
1929 requires __mdspan::__is_left_padded_mapping<_LeftpadMapping>
1930 && is_constructible_v<extents_type,
1931 typename _LeftpadMapping::extents_type>
1932 constexpr explicit(_S_rank > 1 && (padding_value != dynamic_extent
1933 || _LeftpadMapping::padding_value == dynamic_extent))
1934 mapping(
const _LeftpadMapping& __other)
1935 : _M_storage(layout_left{}, __other)
1938 template<
typename _RightPaddedMapping>
1939 requires (__mdspan::__is_right_padded_mapping<_RightPaddedMapping>
1940 || __mdspan::__mapping_of<layout_right, _RightPaddedMapping>)
1942 && is_constructible_v<extents_type,
1943 typename _RightPaddedMapping::extents_type>
1944 constexpr explicit(!is_convertible_v<
1945 typename _RightPaddedMapping::extents_type, extents_type>)
1946 mapping(
const _RightPaddedMapping& __other) noexcept
1947 : _M_storage(layout_right{}, __other)
1951 operator=(
const mapping&)
noexcept =
default;
1953 constexpr const extents_type&
1954 extents() const noexcept {
return _M_storage._M_extents; }
1956 constexpr array<index_type, _S_rank>
1957 strides() const noexcept
1959 array<index_type, _S_rank> __ret;
1960 if constexpr (_S_rank > 0)
1962 if constexpr (_S_rank > 1)
1963 __ret[1] = _M_padstride();
1964 if constexpr (_S_rank > 2)
1965 for(
size_t __i = 2; __i < _S_rank; ++__i)
1966 __ret[__i] = __ret[__i - 1] * _M_extent(__i - 1);
1970 constexpr index_type
1971 required_span_size() const noexcept
1972 {
return _M_storage._M_required_span_size(); }
1976 template<__mdspan::__val
id_index_type<index_type>... _Indices>
1977 requires (
sizeof...(_Indices) == _S_rank)
1978 constexpr index_type
1979 operator()(_Indices... __indices)
const noexcept
1981 return __mdspan::__linear_index_leftpad(
1982 extents(), _M_storage._M_stride,
1983 static_cast<index_type
>(
std::move(__indices))...);
1986 static constexpr bool
1987 is_always_exhaustive() noexcept
1988 {
return _PaddedStorage::_M_is_always_exhaustive(); }
1991 is_exhaustive() noexcept
1992 {
return _M_storage._M_is_exhaustive(); }
1994 static constexpr bool
1995 is_always_unique() noexcept {
return true; }
1997 static constexpr bool
1998 is_unique() noexcept {
return true; }
2000 static constexpr bool
2001 is_always_strided() noexcept {
return true; }
2003 static constexpr bool
2004 is_strided() noexcept {
return true; }
2006 constexpr index_type
2007 stride(rank_type __r)
const noexcept
2009 __glibcxx_assert(__r < _S_rank);
2013 return static_cast<index_type
>(
2014 static_cast<size_t>(_M_padstride()) *
2015 static_cast<size_t>(__mdspan::__fwd_prod(extents(), 1, __r)));
2018 template<
typename _LeftpadMapping>
2019 requires(__mdspan::__is_left_padded_mapping<_LeftpadMapping>
2020 && _LeftpadMapping::extents_type::rank() == _S_rank)
2021 friend constexpr bool
2022 operator==(
const mapping& __self,
const _LeftpadMapping& __other)
2024 {
return __self._M_storage._M_equal(__other); }
2027 template<
size_t _PaddingValue>
2028 template<
typename _Extents>
2029 class layout_right_padded<_PaddingValue>::mapping {
2031 static constexpr size_t padding_value = _PaddingValue;
2032 using extents_type = _Extents;
2033 using index_type =
typename extents_type::index_type;
2034 using size_type =
typename extents_type::size_type;
2035 using rank_type =
typename extents_type::rank_type;
2036 using layout_type = layout_right_padded<_PaddingValue>;
2039 static constexpr size_t _S_rank = extents_type::rank();
2040 using _PaddedStorage = __mdspan::_PaddedStorage<_PaddingValue,
2041 _Extents, __mdspan::_RightPaddedLayoutTraits<_S_rank>>;
2042 [[no_unique_address]] _PaddedStorage _M_storage;
2044 consteval friend size_t
2045 __mdspan::__get_static_stride<mapping>();
2047 constexpr index_type
2048 _M_extent(
size_t __r)
const noexcept
2049 {
return _M_storage._M_extents.extent(__r); }
2051 constexpr index_type
2052 _M_padstride() const noexcept
2053 {
return _M_storage._M_stride.extent(0); }
2061 mapping(
const mapping&)
noexcept =
default;
2064 mapping(
const extents_type& __exts)
2065 : _M_storage(__exts)
2068 template<__mdspan::__val
id_index_type<index_type> _OIndexType>
2070 mapping(
const extents_type& __exts, _OIndexType __pad)
2071 : _M_storage(__exts,
2072 __mdspan::__index_type_cast<index_type>(std::
move(__pad)))
2075 template<
typename _OExtents>
2076 requires is_constructible_v<extents_type, _OExtents>
2077 constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
2078 mapping(
const layout_right::mapping<_OExtents>& __other)
2079 : _M_storage(__other)
2082 template<
typename _OExtents>
2083 requires is_constructible_v<_OExtents, extents_type>
2084 constexpr explicit(_OExtents::rank() > 0)
2085 mapping(
const typename layout_stride::mapping<_OExtents>& __other)
2086 : _M_storage(__other)
2087 { __glibcxx_assert(*
this == __other); }
2089 template<
typename _RightPaddedMapping>
2090 requires __mdspan::__is_right_padded_mapping<_RightPaddedMapping>
2091 && is_constructible_v<extents_type,
2092 typename _RightPaddedMapping::extents_type>
2093 constexpr explicit(_S_rank > 1 && (padding_value != dynamic_extent
2094 || _RightPaddedMapping::padding_value == dynamic_extent))
2095 mapping(
const _RightPaddedMapping& __other)
2096 : _M_storage(layout_right{}, __other)
2099 template<
typename _LeftPaddedMapping>
2100 requires (__mdspan::__is_left_padded_mapping<_LeftPaddedMapping>
2101 || __mdspan::__mapping_of<layout_left, _LeftPaddedMapping>)
2103 && is_constructible_v<extents_type,
2104 typename _LeftPaddedMapping::extents_type>
2105 constexpr explicit(!is_convertible_v<
2106 typename _LeftPaddedMapping::extents_type, extents_type>)
2107 mapping(
const _LeftPaddedMapping& __other) noexcept
2108 : _M_storage(layout_left{}, __other)
2111 constexpr mapping& operator=(
const mapping&)
noexcept =
default;
2113 constexpr const extents_type&
2114 extents() const noexcept {
return _M_storage._M_extents; }
2116 constexpr array<index_type, _S_rank>
2117 strides() const noexcept
2119 array<index_type, _S_rank> __ret;
2120 if constexpr (_S_rank > 0)
2121 __ret[_S_rank - 1] = 1;
2122 if constexpr (_S_rank > 1)
2123 __ret[_S_rank - 2] = _M_padstride();
2124 if constexpr (_S_rank > 2)
2125 for(
size_t __i = _S_rank - 2; __i > 0; --__i)
2126 __ret[__i - 1] = __ret[__i] * _M_extent(__i);
2130 constexpr index_type
2131 required_span_size() const noexcept
2132 {
return _M_storage._M_required_span_size(); }
2136 template<__mdspan::__val
id_index_type<index_type>... _Indices>
2137 requires (
sizeof...(_Indices) == _S_rank)
2138 constexpr index_type
2139 operator()(_Indices... __indices)
const noexcept
2141 return __mdspan::__linear_index_rightpad(
2142 extents(), _M_storage._M_stride,
2143 static_cast<index_type
>(
std::move(__indices))...);
2146 static constexpr bool
2147 is_always_exhaustive() noexcept
2148 {
return _PaddedStorage::_M_is_always_exhaustive(); }
2151 is_exhaustive() noexcept
2152 {
return _M_storage._M_is_exhaustive(); }
2154 static constexpr bool
2155 is_always_unique() noexcept {
return true; }
2157 static constexpr bool
2158 is_unique() noexcept {
return true; }
2160 static constexpr bool
2161 is_always_strided() noexcept {
return true; }
2163 static constexpr bool
2164 is_strided() noexcept {
return true; }
2166 constexpr index_type
2167 stride(rank_type __r)
const noexcept
2169 __glibcxx_assert(__r < _S_rank);
2170 if constexpr (_S_rank <= 1)
2172 else if (__r == _S_rank - 1)
2174 else if (__r == _S_rank - 2)
2175 return _M_padstride();
2177 return static_cast<index_type
>(
2178 static_cast<size_t>(_M_padstride()) *
2179 static_cast<size_t>(__mdspan::__fwd_prod(
2180 extents(), __r + 1, _S_rank - 1)));
2183 template<
typename _RightPaddedMapping>
2184 requires(__mdspan::__is_right_padded_mapping<_RightPaddedMapping>
2185 && _RightPaddedMapping::extents_type::rank() == _S_rank)
2186 friend constexpr bool
2187 operator==(
const mapping& __self,
const _RightPaddedMapping& __other)
2189 {
return __self._M_storage._M_equal(__other); }
2193 template<
typename _ElementType>
2194 struct default_accessor
2196 static_assert(!is_array_v<_ElementType>,
2197 "ElementType must not be an array type");
2198 static_assert(!is_abstract_v<_ElementType>,
2199 "ElementType must not be an abstract class type");
2201 using offset_policy = default_accessor;
2202 using element_type = _ElementType;
2203 using reference = element_type&;
2204 using data_handle_type = element_type*;
2207 default_accessor() noexcept = default;
2209 template<typename _OElementType>
2210 requires is_convertible_v<_OElementType(*)[], element_type(*)[]>
2212 default_accessor(default_accessor<_OElementType>) noexcept
2216 access(data_handle_type __p,
size_t __i)
const noexcept
2217 {
return __p[__i]; }
2219 constexpr data_handle_type
2220 offset(data_handle_type __p,
size_t __i)
const noexcept
2221 {
return __p + __i; }
2224#ifdef __glibcxx_aligned_accessor
2225 template<
typename _ElementType,
size_t _ByteAlignment>
2226 struct aligned_accessor
2228 static_assert(has_single_bit(_ByteAlignment),
2229 "ByteAlignment must be a power of two");
2230 static_assert(_ByteAlignment >=
alignof(_ElementType));
2232 using offset_policy = default_accessor<_ElementType>;
2233 using element_type = _ElementType;
2234 using reference = element_type&;
2235 using data_handle_type = element_type*;
2237 static constexpr size_t byte_alignment = _ByteAlignment;
2240 aligned_accessor() noexcept = default;
2242 template<typename _OElementType,
size_t _OByteAlignment>
2243 requires (_OByteAlignment >= byte_alignment)
2244 && is_convertible_v<_OElementType(*)[], element_type(*)[]>
2246 aligned_accessor(aligned_accessor<_OElementType, _OByteAlignment>)
2250 template<
typename _OElementType>
2251 requires is_convertible_v<_OElementType(*)[], element_type(*)[]>
2253 aligned_accessor(default_accessor<_OElementType>)
noexcept
2256 template<
typename _OElementType>
2257 requires is_convertible_v<element_type(*)[], _OElementType(*)[]>
2259 operator default_accessor<_OElementType>() const noexcept
2263 access(data_handle_type __p,
size_t __i)
const noexcept
2266 constexpr typename offset_policy::data_handle_type
2267 offset(data_handle_type __p,
size_t __i)
const noexcept
2274 template<
typename _Extents,
typename _IndexType,
size_t _Nm>
2276 __is_multi_index(
const _Extents& __exts, span<_IndexType, _Nm> __indices)
2278 static_assert(__exts.rank() == _Nm);
2279 for (
size_t __i = 0; __i < __exts.rank(); ++__i)
2280 if (__indices[__i] >= __exts.extent(__i))
2286 template<
typename _ElementType,
typename _Extents,
2287 typename _LayoutPolicy = layout_right,
2288 typename _AccessorPolicy = default_accessor<_ElementType>>
2291 static_assert(!is_array_v<_ElementType>,
2292 "ElementType must not be an array type");
2293 static_assert(!is_abstract_v<_ElementType>,
2294 "ElementType must not be an abstract class type");
2295 static_assert(__mdspan::__is_extents<_Extents>,
2296 "Extents must be a specialization of std::extents");
2297 static_assert(is_same_v<_ElementType,
2298 typename _AccessorPolicy::element_type>);
2301 using extents_type = _Extents;
2302 using layout_type = _LayoutPolicy;
2303 using accessor_type = _AccessorPolicy;
2304 using mapping_type =
typename layout_type::template mapping<extents_type>;
2305 using element_type = _ElementType;
2306 using value_type = remove_cv_t<element_type>;
2307 using index_type =
typename extents_type::index_type;
2308 using size_type =
typename extents_type::size_type;
2309 using rank_type =
typename extents_type::rank_type;
2310 using data_handle_type =
typename accessor_type::data_handle_type;
2311 using reference =
typename accessor_type::reference;
2313 static constexpr rank_type
2314 rank() noexcept {
return extents_type::rank(); }
2316 static constexpr rank_type
2317 rank_dynamic() noexcept {
return extents_type::rank_dynamic(); }
2319 static constexpr size_t
2320 static_extent(rank_type __r)
noexcept
2321 {
return extents_type::static_extent(__r); }
2323 constexpr index_type
2324 extent(rank_type __r)
const noexcept {
return extents().extent(__r); }
2328 requires (rank_dynamic() > 0)
2329 && is_default_constructible_v<data_handle_type>
2330 && is_default_constructible_v<mapping_type>
2331 && is_default_constructible_v<accessor_type> =
default;
2334 mdspan(
const mdspan& __other) =
default;
2337 mdspan(mdspan&& __other) =
default;
2339 template<__mdspan::__val
id_index_type<index_type>... _OIndexTypes>
2340 requires (
sizeof...(_OIndexTypes) == rank()
2341 ||
sizeof...(_OIndexTypes) == rank_dynamic())
2342 && is_constructible_v<mapping_type, extents_type>
2343 && is_default_constructible_v<accessor_type>
2345 mdspan(data_handle_type __handle, _OIndexTypes... __exts)
2347 _M_mapping(_Extents(
static_cast<index_type
>(
std::move(__exts))...)),
2351 template<
typename _OIndexType,
size_t _Nm>
2352 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
2353 && (_Nm == rank() || _Nm == rank_dynamic())
2354 && is_constructible_v<mapping_type, extents_type>
2355 && is_default_constructible_v<accessor_type>
2356 constexpr explicit(_Nm != rank_dynamic())
2357 mdspan(data_handle_type __handle, span<_OIndexType, _Nm> __exts)
2358 : _M_accessor(), _M_mapping(extents_type(__exts)),
2359 _M_handle(std::move(__handle))
2362 template<
typename _OIndexType,
size_t _Nm>
2363 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
2364 && (_Nm == rank() || _Nm == rank_dynamic())
2365 && is_constructible_v<mapping_type, extents_type>
2366 && is_default_constructible_v<accessor_type>
2367 constexpr explicit(_Nm != rank_dynamic())
2368 mdspan(data_handle_type __handle,
const array<_OIndexType, _Nm>& __exts)
2369 : _M_accessor(), _M_mapping(extents_type(__exts)),
2370 _M_handle(std::
move(__handle))
2374 mdspan(data_handle_type __handle,
const extents_type& __exts)
2375 requires is_constructible_v<mapping_type, const extents_type&>
2376 && is_default_constructible_v<accessor_type>
2377 : _M_accessor(), _M_mapping(__exts), _M_handle(
std::move(__handle))
2381 mdspan(data_handle_type __handle,
const mapping_type& __mapping)
2382 requires is_default_constructible_v<accessor_type>
2383 : _M_accessor(), _M_mapping(__mapping), _M_handle(
std::move(__handle))
2387 mdspan(data_handle_type __handle,
const mapping_type& __mapping,
2388 const accessor_type& __accessor)
2389 : _M_accessor(__accessor), _M_mapping(__mapping),
2390 _M_handle(std::
move(__handle))
2393 template<
typename _OElementType,
typename _OExtents,
typename _OLayout,
2394 typename _OAccessor>
2395 requires is_constructible_v<mapping_type,
2396 const typename _OLayout::template mapping<_OExtents>&>
2397 && is_constructible_v<accessor_type, const _OAccessor&>
2398 constexpr explicit(!is_convertible_v<
2399 const typename _OLayout::template mapping<_OExtents>&, mapping_type>
2400 || !is_convertible_v<const _OAccessor&, accessor_type>)
2401 mdspan(
const mdspan<_OElementType, _OExtents, _OLayout, _OAccessor>&
2403 : _M_accessor(__other.accessor()), _M_mapping(__other.mapping()),
2404 _M_handle(__other.data_handle())
2406 static_assert(is_constructible_v<data_handle_type,
2407 const typename _OAccessor::data_handle_type&>);
2408 static_assert(is_constructible_v<extents_type, _OExtents>);
2412 operator=(
const mdspan& __other) =
default;
2415 operator=(mdspan&& __other) =
default;
2417 template<__mdspan::__val
id_index_type<index_type>... _OIndexTypes>
2418 requires (
sizeof...(_OIndexTypes) == rank())
2420 operator[](_OIndexTypes... __indices)
const
2422 auto __checked_call = [
this](
auto... __idxs) -> index_type
2424 if constexpr (
sizeof...(__idxs) > 0)
2425 __glibcxx_assert(__mdspan::__is_multi_index(extents(),
2426 span<
const index_type,
sizeof...(__idxs)>({__idxs...})));
2427 return _M_mapping(__idxs...);
2430 auto __index = __checked_call(
2431 static_cast<index_type
>(
std::move(__indices))...);
2432 return _M_accessor.access(_M_handle, __index);
2435 template<
typename _OIndexType>
2436 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
2438 operator[](span<_OIndexType, rank()> __indices)
const
2442 {
return (*
this)[index_type(as_const(__indices[_Counts]))...]; };
2443 return __call(make_index_sequence<rank()>());
2446 template<
typename _OIndexType>
2447 requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
2449 operator[](
const array<_OIndexType, rank()>& __indices)
const
2450 {
return (*
this)[span<const _OIndexType, rank()>(__indices)]; }
2453 size() const noexcept
2455 __glibcxx_assert(cmp_less_equal(_M_mapping.required_span_size(),
2458 return size_type(__mdspan::__size(extents()));
2463 empty() const noexcept
2464 {
return __mdspan::__empty(extents()); }
2466 friend constexpr void
2467 swap(mdspan& __x, mdspan& __y)
noexcept
2470 swap(__x._M_mapping, __y._M_mapping);
2471 swap(__x._M_accessor, __y._M_accessor);
2472 swap(__x._M_handle, __y._M_handle);
2475 constexpr const extents_type&
2476 extents() const noexcept {
return _M_mapping.extents(); }
2478 constexpr const data_handle_type&
2479 data_handle() const noexcept {
return _M_handle; }
2481 constexpr const mapping_type&
2482 mapping() const noexcept {
return _M_mapping; }
2484 constexpr const accessor_type&
2485 accessor() const noexcept {
return _M_accessor; }
2489 static constexpr bool
2490 is_always_unique() noexcept(noexcept(mapping_type::is_always_unique()))
2491 {
return mapping_type::is_always_unique(); }
2493 static constexpr bool
2494 is_always_exhaustive()
2495 noexcept(noexcept(mapping_type::is_always_exhaustive()))
2496 {
return mapping_type::is_always_exhaustive(); }
2498 static constexpr bool
2500 noexcept(noexcept(mapping_type::is_always_strided()))
2501 {
return mapping_type::is_always_strided(); }
2504 is_unique() const noexcept(noexcept(_M_mapping.is_unique()))
2505 {
return _M_mapping.is_unique(); }
2508 is_exhaustive() const noexcept(noexcept(_M_mapping.is_exhaustive()))
2509 {
return _M_mapping.is_exhaustive(); }
2512 is_strided() const noexcept(noexcept(_M_mapping.is_strided()))
2513 {
return _M_mapping.is_strided(); }
2515 constexpr index_type
2516 stride(rank_type __r)
const {
return _M_mapping.stride(__r); }
2519 [[no_unique_address]] accessor_type _M_accessor = accessor_type();
2520 [[no_unique_address]] mapping_type _M_mapping = mapping_type();
2521 [[no_unique_address]] data_handle_type _M_handle = data_handle_type();
2524 template<
typename _CArray>
2525 requires is_array_v<_CArray> && (rank_v<_CArray> == 1)
2527 -> mdspan<remove_all_extents_t<_CArray>,
2528 extents<size_t, extent_v<_CArray, 0>>>;
2530 template<
typename _Po
inter>
2531 requires is_pointer_v<remove_reference_t<_Pointer>>
2533 -> mdspan<remove_pointer_t<remove_reference_t<_Pointer>>, extents<size_t>>;
2535 template<
typename _ElementType,
typename... _Integrals>
2536 requires (is_convertible_v<_Integrals, size_t> && ...)
2537 && (
sizeof...(_Integrals) > 0)
2538 explicit mdspan(_ElementType*, _Integrals...)
2539 -> mdspan<_ElementType,
2540 extents<size_t, __detail::__maybe_static_ext<_Integrals>...>>;
2542 template<
typename _ElementType,
typename _OIndexType,
size_t _Nm>
2543 mdspan(_ElementType*, span<_OIndexType, _Nm>)
2544 -> mdspan<_ElementType, dextents<size_t, _Nm>>;
2546 template<
typename _ElementType,
typename _OIndexType,
size_t _Nm>
2547 mdspan(_ElementType*,
const array<_OIndexType, _Nm>&)
2548 -> mdspan<_ElementType, dextents<size_t, _Nm>>;
2550 template<
typename _ElementType,
typename _IndexType,
size_t... _ExtentsPack>
2551 mdspan(_ElementType*,
const extents<_IndexType, _ExtentsPack...>&)
2552 -> mdspan<_ElementType, extents<_IndexType, _ExtentsPack...>>;
2554 template<
typename _ElementType,
typename _MappingType>
2555 mdspan(_ElementType*,
const _MappingType&)
2556 -> mdspan<_ElementType,
typename _MappingType::extents_type,
2557 typename _MappingType::layout_type>;
2559 template<
typename _MappingType,
typename _AccessorType>
2560 mdspan(
const typename _AccessorType::data_handle_type&,
const _MappingType&,
2561 const _AccessorType&)
2562 -> mdspan<
typename _AccessorType::element_type,
2563 typename _MappingType::extents_type,
2564 typename _MappingType::layout_type, _AccessorType>;
2566#if __glibcxx_submdspan
2569 template<
typename _IndexType,
typename _Slice>
2571 __canonical_index(_Slice&& __slice)
2573 if constexpr (__detail::__integral_constant_like<_Slice>)
2575 static_assert(__is_representable_integer<_IndexType>(_Slice::value));
2576 static_assert(_Slice::value >= 0);
2577 return std::cw<_IndexType(_Slice::value)>;
2580 return __mdspan::__index_type_cast<_IndexType>(
std::move(__slice));
2583 template<
typename _IndexType,
typename _Slice>
2585 __slice_cast(_Slice&& __slice)
2587 using _SliceType = remove_cvref_t<_Slice>;
2588 if constexpr (is_convertible_v<_SliceType, full_extent_t>)
2589 return static_cast<full_extent_t
>(
std::move(__slice));
2590 else if constexpr (is_convertible_v<_SliceType, _IndexType>)
2591 return __mdspan::__canonical_index<_IndexType>(
std::move(__slice));
2592 else if constexpr (__is_strided_slice<_SliceType>)
2595 = __mdspan::__canonical_index<_IndexType>(
std::move(__slice.extent));
2597 = __mdspan::__canonical_index<_IndexType>(
std::move(__slice.offset));
2598 if constexpr (is_same_v<
decltype(__extent),
2599 constant_wrapper<_IndexType(0)>>)
2600 return strided_slice{
2603 .stride = cw<_IndexType(1)>
2606 return strided_slice{
2610 = __mdspan::__canonical_index<_IndexType>(
std::move(__slice.stride))
2615 auto [__sbegin, __send] =
std::move(__slice);
2617 = __mdspan::__canonical_index<_IndexType>(
std::move(__sbegin));
2619 = __mdspan::__canonical_index<_IndexType>(
std::move(__send));
2620 return strided_slice{
2622 .extent = __mdspan::__canonical_index<_IndexType>(__end - __offset),
2623 .stride = cw<_IndexType(1)>
2628 template<
typename _IndexType,
size_t _Extent,
typename _OIndexType>
2630 __check_valid_index(
const extents<_IndexType, _Extent>& __ext,
2631 const _OIndexType& __idx)
2633 if constexpr (__is_constant_wrapper<_OIndexType>
2634 && _Extent != dynamic_extent)
2636 static_assert(_OIndexType::value >= 0);
2637 static_assert(std::cmp_less_equal(_OIndexType::value, _Extent));
2640 __glibcxx_assert(__idx <= __ext.extent(0));
2643 template<
typename _IndexType,
size_t _Extent,
typename _Slice>
2645 __check_valid_slice(
const extents<_IndexType, _Extent>& __ext,
2646 const _Slice& __slice)
2648 if constexpr (__is_strided_slice<_Slice>)
2654 __mdspan::__check_valid_index(__ext, __slice.offset);
2655 __mdspan::__check_valid_index(__ext, __slice.extent);
2657 if constexpr (__is_constant_wrapper<typename _Slice::extent_type>
2658 && __is_constant_wrapper<typename _Slice::stride_type>)
2659 static_assert(_Slice::stride_type::value > 0);
2661 __glibcxx_assert(__slice.extent == 0 || __slice.stride > 0);
2663 if constexpr (__is_constant_wrapper<typename _Slice::offset_type>
2664 && __is_constant_wrapper<typename _Slice::extent_type>
2665 && _Extent != dynamic_extent)
2666 static_assert(std::cmp_greater_equal(
2667 _Extent - _Slice::offset_type::value,
2668 _Slice::extent_type::value));
2670 __glibcxx_assert(__ext.extent(0) - __slice.offset
2673 else if constexpr (__is_constant_wrapper<_Slice>
2674 && _Extent != dynamic_extent)
2675 static_assert(std::cmp_less(_Slice::value, _Extent));
2676 else if constexpr (convertible_to<_Slice, _IndexType>)
2677 __glibcxx_assert(__slice < __ext.extent(0));
2680 template<
typename _Extents,
typename... _Slices>
2682 __check_valid_slices(
const _Extents& __exts,
const _Slices&... __slices)
2684 constexpr auto __rank = _Extents::rank();
2687 ((__mdspan::__check_valid_slice(__extract_extent<_Is>(__exts),
2688 __slices...[_Is])),...);
2690 __impl(make_index_sequence<__rank>());
2693 template<
typename _IndexType,
size_t _Extent,
typename _Slice>
2695 __static_slice_extent()
2697 if constexpr (same_as<_Slice, full_extent_t>)
2699 else if constexpr (same_as<_Slice, constant_wrapper<_IndexType(0)>>)
2701 else if constexpr (__is_constant_wrapper<typename _Slice::extent_type>
2702 && __is_constant_wrapper<typename _Slice::stride_type>)
2703 return 1 + ((
typename _Slice::extent_type{}) - 1)
2704 / (
typename _Slice::stride_type{});
2706 return dynamic_extent;
2709 template<
size_t _K,
typename _Extents,
typename _Slice>
2710 constexpr typename _Extents::index_type
2711 __dynamic_slice_extent(
const _Extents& __exts, _Slice __slice)
2713 if constexpr (__is_strided_slice<_Slice>)
2714 return __slice.extent == 0 ? 0 : 1 + (__slice.extent - 1) / __slice.stride;
2716 return __exts.extent(_K);
2719 template<
typename _IndexType,
size_t... _Extents,
typename... _Slices>
2720 requires (
sizeof...(_Slices) ==
sizeof...(_Extents))
2722 __subextents(
const extents<_IndexType, _Extents...>& __exts,
2723 _Slices... __slices)
2725 constexpr auto __inv_map = __mdspan::__inv_map_rank<_IndexType, _Slices...>();
2726 auto __impl = [&]<
size_t... _Indices>(
index_sequence<_Indices...>)
2728 using _SubExtents = extents<_IndexType,
2729 (__mdspan::__static_slice_extent<_IndexType,
2730 _Extents...[__inv_map[_Indices]],
2731 _Slices...[__inv_map[_Indices]]>())...>;
2732 if constexpr (_SubExtents::rank_dynamic() == 0)
2733 return _SubExtents{};
2736 using _StaticSubExtents = __mdspan::_StaticExtents<
2737 __mdspan::__static_extents<_SubExtents>()>;
2740 constexpr auto __slice_idx = [__inv_map](
size_t __i)
consteval
2742 return __inv_map[_StaticSubExtents::_S_dynamic_index_inv(__i)];
2746 (__mdspan::__dynamic_slice_extent<__slice_idx(_Is)>(
2747 __exts, __slices...[__slice_idx(_Is)]))...};
2749 constexpr auto __dyn_subrank = _SubExtents::rank_dynamic();
2750 return __create(make_index_sequence<__dyn_subrank>());
2754 return __impl(make_index_sequence<__inv_map.size()>());
2758 template<
typename _IndexType,
size_t... _Extents,
typename... _RawSlices>
2759 requires (
sizeof...(_RawSlices) ==
sizeof...(_Extents))
2761 submdspan_extents(
const extents<_IndexType, _Extents...>& __exts,
2762 _RawSlices... __raw_slices)
2764 auto __impl = [&__exts](
auto... __slices)
2766 __mdspan::__check_valid_slices(__exts, __slices...);
2767 return __mdspan::__subextents(__exts, __slices...);
2769 return __impl(__mdspan::__slice_cast<_IndexType>(__raw_slices)...);
2772 template<
typename _IndexType,
size_t... _Extents,
typename... _RawSlices>
2773 requires (
sizeof...(_Extents) ==
sizeof...(_RawSlices))
2775 submdspan_canonicalize_slices(
const extents<_IndexType, _Extents...>& __exts,
2776 _RawSlices... __raw_slices)
2778 auto __impl = [&__exts](
auto... __slices)
2780 __mdspan::__check_valid_slices(__exts, __slices...);
2783 return __impl(__mdspan::__slice_cast<_IndexType>(__raw_slices)...);
2787_GLIBCXX_END_NAMESPACE_VERSION
constexpr _Tp * assume_aligned(_Tp *__ptr) noexcept
Inform the compiler that a pointer is aligned.
constexpr tuple< typename __decay_and_strip< _Elements >::__type... > make_tuple(_Elements &&... __args)
Create a tuple containing copies of the arguments.
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
ISO C++ entities toplevel namespace is std.
integer_sequence< size_t, _Idx... > index_sequence
Alias template index_sequence.
constexpr auto empty(const _Container &__cont) noexcept(noexcept(__cont.empty())) -> decltype(__cont.empty())
Return whether a container is empty.
constexpr auto size(const _Container &__cont) noexcept(noexcept(__cont.size())) -> decltype(__cont.size())
Return the size of a container.
__numeric_traits_integer< _Tp > __int_traits
Convenience alias for __numeric_traits<integer-type>.