libstdc++
mdspan
Go to the documentation of this file.
1 // <mdspan> -*- C++ -*-
2 
3 // Copyright The GNU Toolchain Authors.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 /** @file mdspan
26  * This is a Standard C++ Library header.
27  */
28 
29 #ifndef _GLIBCXX_MDSPAN
30 #define _GLIBCXX_MDSPAN 1
31 
32 #ifdef _GLIBCXX_SYSHDR
33 #pragma GCC system_header
34 #endif
35 
36 #include <span>
37 #include <array>
38 #include <type_traits>
39 #include <utility>
40 
41 #define __glibcxx_want_mdspan
42 #define __glibcxx_want_aligned_accessor
43 #define __glibcxx_want_submdspan
44 #include <bits/version.h>
45 
46 #if __glibcxx_aligned_accessor
47 #include <bits/align.h>
48 #endif
49 
50 #if __glibcxx_submdspan
51 #include <tuple>
52 #endif
53 
54 #if __cplusplus > 202302L
55 #include <bits/stdexcept_throw.h>
56 #endif
57 
58 #ifdef __glibcxx_mdspan
59 
60 namespace std _GLIBCXX_VISIBILITY(default)
61 {
62 _GLIBCXX_BEGIN_NAMESPACE_VERSION
63  namespace __mdspan
64  {
65  consteval bool
66  __all_static(std::span<const size_t> __extents)
67  {
68  for(auto __ext : __extents)
69  if (__ext == dynamic_extent)
70  return false;
71  return true;
72  }
73 
74  consteval bool
75  __all_dynamic(std::span<const size_t> __extents)
76  {
77  for(auto __ext : __extents)
78  if (__ext != dynamic_extent)
79  return false;
80  return true;
81  }
82 
83  template<typename _IndexType, typename _OIndexTypeRef>
84  constexpr _IndexType
85  __index_type_cast(_OIndexTypeRef&& __other)
86  {
87  // _GLIBCXX_RESOLVE_LIB_DEFECTS
88  // 4020. extents::index-cast weirdness
89  using _OIndexType = std::remove_cvref_t<_OIndexTypeRef>;
90  if constexpr (std::is_integral_v<_OIndexType>)
91  {
92  constexpr _IndexType __index_type_max
93  = __gnu_cxx::__int_traits<_IndexType>::__max;
94  constexpr _OIndexType __oindex_type_max
95  = __gnu_cxx::__int_traits<_OIndexType>::__max;
96 
97  if constexpr (__index_type_max < __oindex_type_max)
98  __glibcxx_assert(cmp_less_equal(__other, __index_type_max));
99 
100  if constexpr (std::is_signed_v<_OIndexType>)
101  __glibcxx_assert(__other >= 0);
102  return static_cast<_IndexType>(__other);
103  }
104  else
105  {
106  // _GLIBCXX_RESOLVE_LIB_DEFECTS
107  // 4314. Missing move in mdspan layout mapping::operator()
108  auto __ret = static_cast<_IndexType>(std::forward<_OIndexTypeRef>(__other));
109  if constexpr (std::is_signed_v<_IndexType>)
110  __glibcxx_assert(__ret >= 0);
111  return __ret;
112  }
113  }
114 
115  template<array _Extents>
116  class _StaticExtents
117  {
118  public:
119  static constexpr size_t _S_rank = _Extents.size();
120 
121  // For __r in [0, _S_rank], _S_dynamic_index(__r) is the number
122  // of dynamic extents up to (and not including) __r.
123  //
124  // If __r is the index of a dynamic extent, then
125  // _S_dynamic_index[__r] is the index of that extent in
126  // _M_dyn_exts.
127  static constexpr size_t
128  _S_dynamic_index(size_t __r) noexcept
129  { return _S_dynamic_index_data[__r]; }
130 
131  static constexpr auto _S_dynamic_index_data = [] consteval
132  {
133  array<size_t, _S_rank+1> __ret;
134  size_t __dyn = 0;
135  for (size_t __i = 0; __i < _S_rank; ++__i)
136  {
137  __ret[__i] = __dyn;
138  __dyn += (_Extents[__i] == dynamic_extent);
139  }
140  __ret[_S_rank] = __dyn;
141  return __ret;
142  }();
143 
144  static constexpr size_t _S_rank_dynamic = _S_dynamic_index(_S_rank);
145 
146  // For __r in [0, _S_rank_dynamic), _S_dynamic_index_inv(__r) is the
147  // index of the __r-th dynamic extent in _Extents.
148  static constexpr size_t
149  _S_dynamic_index_inv(size_t __r) noexcept
150  { return _S_dynamic_index_inv_data[__r]; }
151 
152  static constexpr auto _S_dynamic_index_inv_data = [] consteval
153  {
154  array<size_t, _S_rank_dynamic> __ret;
155  for (size_t __i = 0, __r = 0; __i < _S_rank; ++__i)
156  if (_Extents[__i] == dynamic_extent)
157  __ret[__r++] = __i;
158  return __ret;
159  }();
160 
161  static constexpr size_t
162  _S_static_extent(size_t __r) noexcept
163  { return _Extents[__r]; }
164  };
165 
166  template<array _Extents>
167  requires (__all_dynamic<_Extents>())
168  class _StaticExtents<_Extents>
169  {
170  public:
171  static constexpr size_t _S_rank = _Extents.size();
172 
173  static constexpr size_t
174  _S_dynamic_index(size_t __r) noexcept
175  { return __r; }
176 
177  static constexpr size_t _S_rank_dynamic = _S_rank;
178 
179  static constexpr size_t
180  _S_dynamic_index_inv(size_t __k) noexcept
181  { return __k; }
182 
183  static constexpr size_t
184  _S_static_extent(size_t) noexcept
185  { return dynamic_extent; }
186  };
187 
188  template<typename _IndexType, array _Extents>
189  class _ExtentsStorage : public _StaticExtents<_Extents>
190  {
191  private:
192  using _Base = _StaticExtents<_Extents>;
193 
194  public:
195  using _Base::_S_rank;
196  using _Base::_S_rank_dynamic;
197  using _Base::_S_dynamic_index;
198  using _Base::_S_dynamic_index_inv;
199  using _Base::_S_static_extent;
200 
201  static constexpr bool
202  _S_is_dynamic(size_t __r) noexcept
203  {
204  if constexpr (__all_static(_Extents))
205  return false;
206  else if constexpr (__all_dynamic(_Extents))
207  return true;
208  else
209  return _Extents[__r] == dynamic_extent;
210  }
211 
212  template<typename _OIndexType>
213  static constexpr _IndexType
214  _S_int_cast(const _OIndexType& __other) noexcept
215  { return _IndexType(__other); }
216 
217  constexpr _IndexType
218  _M_extent(size_t __r) const noexcept
219  {
220  if (_S_is_dynamic(__r))
221  return _M_dyn_exts[_S_dynamic_index(__r)];
222  else
223  return _S_static_extent(__r);
224  }
225 
226  template<size_t _OtherRank, typename _GetOtherExtent>
227  static constexpr bool
228  _S_is_compatible_extents(_GetOtherExtent __get_extent) noexcept
229  {
230  if constexpr (_OtherRank == _S_rank)
231  for (size_t __i = 0; __i < _S_rank; ++__i)
232  if (!_S_is_dynamic(__i)
233  && !cmp_equal(_Extents[__i], _S_int_cast(__get_extent(__i))))
234  return false;
235  return true;
236  }
237 
238  template<size_t _OtherRank, typename _GetOtherExtent>
239  constexpr void
240  _M_init_dynamic_extents(_GetOtherExtent __get_extent) noexcept
241  {
242  __glibcxx_assert(_S_is_compatible_extents<_OtherRank>(__get_extent));
243  for (size_t __i = 0; __i < _S_rank_dynamic; ++__i)
244  {
245  size_t __di = __i;
246  if constexpr (_OtherRank != _S_rank_dynamic)
247  __di = _S_dynamic_index_inv(__i);
248  _M_dyn_exts[__i] = _S_int_cast(__get_extent(__di));
249  }
250  }
251 
252  constexpr
253  _ExtentsStorage() noexcept = default;
254 
255  template<typename _OIndexType, array _OExtents>
256  constexpr
257  _ExtentsStorage(const _ExtentsStorage<_OIndexType, _OExtents>&
258  __other) noexcept
259  {
260  _M_init_dynamic_extents<_S_rank>([&__other](size_t __i)
261  { return __other._M_extent(__i); });
262  }
263 
264  template<typename _OIndexType, size_t _Nm>
265  constexpr
266  _ExtentsStorage(span<const _OIndexType, _Nm> __exts) noexcept
267  {
268  _M_init_dynamic_extents<_Nm>(
269  [&__exts](size_t __i) -> const _OIndexType&
270  { return __exts[__i]; });
271  }
272 
273  static constexpr const array<size_t, _S_rank>&
274  _S_static_extents() noexcept
275  { return _Extents; }
276 
277  constexpr span<const _IndexType>
278  _M_dynamic_extents(size_t __begin, size_t __end) const noexcept
279  requires (_Extents.size() > 0)
280  {
281  return {_M_dyn_exts + _S_dynamic_index(__begin),
282  _S_dynamic_index(__end) - _S_dynamic_index(__begin)};
283  }
284 
285  private:
286  using _Storage = __array_traits<_IndexType, _S_rank_dynamic>::_Type;
287  [[no_unique_address]] _Storage _M_dyn_exts{};
288  };
289 
290  template<typename _OIndexType, typename _SIndexType>
291  concept __valid_index_type =
292  is_convertible_v<_OIndexType, _SIndexType> &&
293  is_nothrow_constructible_v<_SIndexType, _OIndexType>;
294 
295  template<size_t _Extent, typename _IndexType>
296  concept
297  __valid_static_extent = _Extent == dynamic_extent
298  || _Extent <= __gnu_cxx::__int_traits<_IndexType>::__max;
299 
300  template<typename _Extents>
301  constexpr const array<size_t, _Extents::rank()>&
302  __static_extents() noexcept
303  { return _Extents::_Storage::_S_static_extents(); }
304 
305  template<typename _Extents>
306  constexpr span<const size_t>
307  __static_extents(size_t __begin, size_t __end) noexcept
308  {
309  const auto& __sta_exts = __static_extents<_Extents>();
310  return span<const size_t>(__sta_exts.data() + __begin, __end - __begin);
311  }
312 
313  // Pre-compute: \prod_{i = 0}^r _Extents[i], for r = 0,..., n (exclusive)
314  template<array _Extents>
315  constexpr auto __fwd_partial_prods = [] consteval
316  {
317  constexpr size_t __rank = _Extents.size();
318  std::array<size_t, __rank> __ret;
319  size_t __prod = 1;
320  for (size_t __r = 0; __r < __rank; ++__r)
321  {
322  __ret[__r] = __prod;
323  if (size_t __ext = _Extents[__r]; __ext != dynamic_extent)
324  __prod *= __ext;
325  }
326  return __ret;
327  }();
328 
329  // Pre-compute: \prod_{i = r+1}^{n-1} _Extents[i]
330  template<array _Extents>
331  constexpr auto __rev_partial_prods = [] consteval
332  {
333  constexpr size_t __rank = _Extents.size();
334  std::array<size_t, __rank> __ret;
335  size_t __prod = 1;
336  for (size_t __r = __rank; __r > 0; --__r)
337  {
338  __ret[__r - 1] = __prod;
339  if (size_t __ext = _Extents[__r - 1]; __ext != dynamic_extent)
340  __prod *= __ext;
341  }
342  return __ret;
343  }();
344 
345  template<typename _Extents>
346  constexpr span<const typename _Extents::index_type>
347  __dynamic_extents(const _Extents& __exts, size_t __begin = 0,
348  size_t __end = _Extents::rank()) noexcept
349  { return __exts._M_exts._M_dynamic_extents(__begin, __end); }
350  }
351 
352 #if __glibcxx_submdspan
353  struct full_extent_t
354  {
355  explicit full_extent_t() = default;
356  };
357 
358  inline constexpr full_extent_t full_extent{};
359 
360  template<typename _OffsetType, typename _ExtentType, typename _StrideType>
361  struct extent_slice
362  {
363  static_assert(__is_signed_or_unsigned_integer<_OffsetType>::value
364  || __detail::__integral_constant_like<_OffsetType>);
365  static_assert(__is_signed_or_unsigned_integer<_ExtentType>::value
366  || __detail::__integral_constant_like<_ExtentType>);
367  static_assert(__is_signed_or_unsigned_integer<_StrideType>::value
368  || __detail::__integral_constant_like<_StrideType>);
369 
370  using offset_type = _OffsetType;
371  using extent_type = _ExtentType;
372  using stride_type = _StrideType;
373 
374  [[no_unique_address]] offset_type offset{};
375  [[no_unique_address]] extent_type extent{};
376  [[no_unique_address]] stride_type stride{};
377  };
378 
379  template<typename _FirstType, typename _LastType, typename _StrideType = constant_wrapper<1zu>>
380  struct range_slice
381  {
382  static_assert(__is_signed_or_unsigned_integer<_FirstType>::value
383  || __detail::__integral_constant_like<_FirstType>);
384  static_assert(__is_signed_or_unsigned_integer<_LastType>::value
385  || __detail::__integral_constant_like<_LastType>);
386  static_assert(__is_signed_or_unsigned_integer<_StrideType>::value
387  || __detail::__integral_constant_like<_StrideType>);
388 
389  [[no_unique_address]] _FirstType first{};
390  [[no_unique_address]] _LastType last{};
391  [[no_unique_address]] _StrideType stride{};
392  };
393 
394  template<typename _Mapping>
395  struct submdspan_mapping_result
396  {
397  [[no_unique_address]] _Mapping mapping = _Mapping();
398  size_t offset{};
399  };
400 
401  template<typename _Tp>
402  constexpr bool __is_submdspan_mapping_result = false;
403 
404  template<typename _Mapping>
405  constexpr bool __is_submdspan_mapping_result<submdspan_mapping_result<_Mapping>> = true;
406 
407  template<typename _Mapping>
408  concept __submdspan_mapping_result = __is_submdspan_mapping_result<_Mapping>;
409 
410 #endif // __glibcxx_submdspan
411 
412  template<typename _IndexType, size_t... _Extents>
413  class extents
414  {
415  static_assert(__is_signed_or_unsigned_integer<_IndexType>::value,
416  "IndexType must be a signed or unsigned integer type");
417  static_assert(
418  (__mdspan::__valid_static_extent<_Extents, _IndexType> && ...),
419  "Extents must either be dynamic or representable as IndexType");
420 
421  using _Storage = __mdspan::_ExtentsStorage<
422  _IndexType, array<size_t, sizeof...(_Extents)>{_Extents...}>;
423  [[no_unique_address]] _Storage _M_exts;
424 
425  public:
426  using index_type = _IndexType;
427  using size_type = make_unsigned_t<index_type>;
428  using rank_type = size_t;
429 
430  static constexpr rank_type
431  rank() noexcept { return _Storage::_S_rank; }
432 
433  static constexpr rank_type
434  rank_dynamic() noexcept { return _Storage::_S_rank_dynamic; }
435 
436  static constexpr size_t
437  static_extent(rank_type __r) noexcept
438  {
439  __glibcxx_assert(__r < rank());
440  if constexpr (rank() == 0)
441  __builtin_trap();
442  else
443  return _Storage::_S_static_extent(__r);
444  }
445 
446  constexpr index_type
447  extent(rank_type __r) const noexcept
448  {
449  __glibcxx_assert(__r < rank());
450  if constexpr (rank() == 0)
451  __builtin_trap();
452  else
453  return _M_exts._M_extent(__r);
454  }
455 
456  constexpr
457  extents() noexcept = default;
458 
459  private:
460  static consteval bool
461  _S_is_less_dynamic(size_t __ext, size_t __oext)
462  { return (__ext != dynamic_extent) && (__oext == dynamic_extent); }
463 
464  template<typename _OIndexType, size_t... _OExtents>
465  static consteval bool
466  _S_ctor_explicit()
467  {
468  return (_S_is_less_dynamic(_Extents, _OExtents) || ...)
469  || (__gnu_cxx::__int_traits<index_type>::__max
470  < __gnu_cxx::__int_traits<_OIndexType>::__max);
471  }
472 
473  template<size_t... _OExtents>
474  static consteval bool
475  _S_is_compatible_extents()
476  {
477  if constexpr (sizeof...(_OExtents) != rank())
478  return false;
479  else
480  return ((_OExtents == dynamic_extent || _Extents == dynamic_extent
481  || _OExtents == _Extents) && ...);
482  }
483 
484  public:
485  template<typename _OIndexType, size_t... _OExtents>
486  requires (_S_is_compatible_extents<_OExtents...>())
487  constexpr explicit(_S_ctor_explicit<_OIndexType, _OExtents...>())
488  extents(const extents<_OIndexType, _OExtents...>& __other) noexcept
489  : _M_exts(__other._M_exts)
490  { }
491 
492  template<__mdspan::__valid_index_type<index_type>... _OIndexTypes>
493  requires (sizeof...(_OIndexTypes) == rank()
494  || sizeof...(_OIndexTypes) == rank_dynamic())
495  constexpr explicit extents(_OIndexTypes... __exts) noexcept
496  : _M_exts(span<const _IndexType, sizeof...(_OIndexTypes)>(
497  initializer_list{static_cast<_IndexType>(std::move(__exts))...}))
498  { }
499 
500  template<typename _OIndexType, size_t _Nm>
501  requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
502  && (_Nm == rank() || _Nm == rank_dynamic())
503  constexpr explicit(_Nm != rank_dynamic())
504  extents(span<_OIndexType, _Nm> __exts) noexcept
505  : _M_exts(span<const _OIndexType, _Nm>(__exts))
506  { }
507 
508  template<typename _OIndexType, size_t _Nm>
509  requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
510  && (_Nm == rank() || _Nm == rank_dynamic())
511  constexpr explicit(_Nm != rank_dynamic())
512  extents(const array<_OIndexType, _Nm>& __exts) noexcept
513  : _M_exts(span<const _OIndexType, _Nm>(__exts))
514  { }
515 
516  template<typename _OIndexType, size_t... _OExtents>
517  friend constexpr bool
518  operator==(const extents& __self,
519  const extents<_OIndexType, _OExtents...>& __other) noexcept
520  {
521  if constexpr (!_S_is_compatible_extents<_OExtents...>())
522  return false;
523  else
524  {
525  auto __impl = [&__self, &__other]<size_t... _Counts>(
526  index_sequence<_Counts...>)
527  { return (cmp_equal(__self.extent(_Counts),
528  __other.extent(_Counts)) && ...); };
529  return __impl(make_index_sequence<__self.rank()>());
530  }
531  }
532 
533  private:
534  friend constexpr const array<size_t, rank()>&
535  __mdspan::__static_extents<extents>() noexcept;
536 
537  friend constexpr span<const index_type>
538  __mdspan::__dynamic_extents<extents>(const extents&, size_t, size_t)
539  noexcept;
540 
541  template<typename _OIndexType, size_t... _OExtents>
542  friend class extents;
543  };
544 
545  namespace __mdspan
546  {
547  template<typename _Tp, size_t _Nm>
548  constexpr bool
549  __contains_zero(span<_Tp, _Nm> __exts) noexcept
550  {
551  for (size_t __i = 0; __i < __exts.size(); ++__i)
552  if (__exts[__i] == 0)
553  return true;
554  return false;
555  }
556 
557  template<typename _Tp, size_t _Nm>
558  consteval bool
559  __contains_zero(const array<_Tp, _Nm>& __exts) noexcept
560  { return __contains_zero(span<const _Tp>(__exts)); }
561 
562  template<typename _Extents>
563  constexpr bool
564  __empty(const _Extents& __exts) noexcept
565  {
566  if constexpr (__contains_zero(__static_extents<_Extents>()))
567  return true;
568  else if constexpr (_Extents::rank_dynamic() > 0)
569  return __contains_zero(__dynamic_extents(__exts));
570  else
571  return false;
572  }
573 
574  template<typename _Extents>
575  constexpr typename _Extents::index_type
576  __extents_prod(const _Extents& __exts, size_t __sta_prod, size_t __begin,
577  size_t __end) noexcept
578  {
579  if (__sta_prod == 0)
580  return 0;
581 
582  size_t __ret = __sta_prod;
583  if constexpr (_Extents::rank_dynamic() > 0)
584  for (auto __factor : __dynamic_extents(__exts, __begin, __end))
585  __ret *= size_t(__factor);
586  return static_cast<typename _Extents::index_type>(__ret);
587  }
588 
589  // Preconditions: _r < _Extents::rank()
590  template<typename _Extents>
591  constexpr typename _Extents::index_type
592  __fwd_prod(const _Extents& __exts, size_t __begin, size_t __end) noexcept
593  {
594  size_t __sta_prod = [__begin, __end] {
595  span<const size_t> __sta_exts
596  = __static_extents<_Extents>(__begin, __end);
597  size_t __ret = 1;
598  for(auto __ext : __sta_exts)
599  if (__ext != dynamic_extent)
600  __ret *= __ext;
601  return __ret;
602  }();
603  return __extents_prod(__exts, __sta_prod, __begin, __end);
604  }
605 
606  template<typename _Extents>
607  constexpr typename _Extents::index_type
608  __fwd_prod(const _Extents& __exts, size_t __r) noexcept
609  {
610  constexpr size_t __rank = _Extents::rank();
611  constexpr auto& __sta_exts = __static_extents<_Extents>();
612  if constexpr (__rank == 1)
613  return 1;
614  else if constexpr (__rank == 2)
615  return __r == 0 ? 1 : __exts.extent(0);
616  else if constexpr (__all_dynamic(std::span(__sta_exts).first(__rank-1)))
617  return __extents_prod(__exts, 1, 0, __r);
618  else
619  {
620  size_t __sta_prod = __fwd_partial_prods<__sta_exts>[__r];
621  return __extents_prod(__exts, __sta_prod, 0, __r);
622  }
623  }
624 
625  template<typename _IndexType, size_t _Nm>
626  consteval _IndexType
627  __fwd_prod(span<const _IndexType, _Nm> __values)
628  {
629  _IndexType __ret = 1;
630  for(auto __value : __values)
631  __ret *= __value;
632  return __ret;
633  }
634 
635  // Preconditions: _r < _Extents::rank()
636  template<typename _Extents>
637  constexpr typename _Extents::index_type
638  __rev_prod(const _Extents& __exts, size_t __r) noexcept
639  {
640  constexpr size_t __rank = _Extents::rank();
641  constexpr auto& __sta_exts = __static_extents<_Extents>();
642  if constexpr (__rank == 1)
643  return 1;
644  else if constexpr (__rank == 2)
645  return __r == 0 ? __exts.extent(1) : 1;
646  else if constexpr (__all_dynamic(std::span(__sta_exts).last(__rank-1)))
647  return __extents_prod(__exts, 1, __r + 1, __rank);
648  else
649  {
650  size_t __sta_prod = __rev_partial_prods<__sta_exts>[__r];
651  return __extents_prod(__exts, __sta_prod, __r + 1, __rank);
652  }
653  }
654 
655  template<typename _Extents>
656  constexpr typename _Extents::index_type
657  __size(const _Extents& __exts) noexcept
658  {
659  constexpr size_t __sta_prod = [] {
660  span<const size_t> __sta_exts = __static_extents<_Extents>();
661  size_t __ret = 1;
662  for(auto __ext : __sta_exts)
663  if (__ext != dynamic_extent)
664  __ret *= __ext;
665  return __ret;
666  }();
667  return __extents_prod(__exts, __sta_prod, 0, _Extents::rank());
668  }
669 
670  template<typename _IndexType, size_t... _Counts>
671  auto __build_dextents_type(integer_sequence<size_t, _Counts...>)
672  -> extents<_IndexType, ((void) _Counts, dynamic_extent)...>;
673  }
674 
675  template<typename _IndexType, size_t _Rank>
676  using dextents = decltype(__mdspan::__build_dextents_type<_IndexType>(
677  make_index_sequence<_Rank>()));
678 
679 #if __glibcxx_mdspan >= 202406L
680  template<size_t _Rank, typename _IndexType = size_t>
681  using dims = dextents<_IndexType, _Rank>;
682 #endif
683 
684  template<typename... _Integrals>
685  requires (is_convertible_v<_Integrals, size_t> && ...)
686  explicit extents(_Integrals...) ->
687  extents<size_t, __detail::__maybe_static_ext<_Integrals>...>;
688 
689  struct layout_left
690  {
691  template<typename _Extents>
692  class mapping;
693  };
694 
695  struct layout_right
696  {
697  template<typename _Extents>
698  class mapping;
699  };
700 
701  struct layout_stride
702  {
703  template<typename _Extents>
704  class mapping;
705  };
706 
707 #ifdef __glibcxx_padded_layouts
708  template<size_t _PaddingValue>
709  struct layout_left_padded
710  {
711  template<typename _Extents>
712  class mapping;
713  };
714 
715  template<size_t _PaddingValue>
716  struct layout_right_padded
717  {
718  template<typename _Extents>
719  class mapping;
720  };
721 #endif
722 
723  namespace __mdspan
724  {
725  template<typename _Tp>
726  constexpr bool __is_extents = false;
727 
728  template<typename _IndexType, size_t... _Extents>
729  constexpr bool __is_extents<extents<_IndexType, _Extents...>> = true;
730 
731  template<typename _Extents, typename... _Indices>
732  constexpr typename _Extents::index_type
733  __linear_index_left(const _Extents& __exts, _Indices... __indices)
734  noexcept
735  {
736  using _IndexType = typename _Extents::index_type;
737  _IndexType __res = 0;
738  if constexpr (sizeof...(__indices) > 0)
739  {
740  _IndexType __mult = 1;
741  auto __update = [&, __pos = 0u](_IndexType __idx) mutable
742  {
743  _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx, __exts.extent(__pos)));
744  __res += __idx * __mult;
745  __mult *= __exts.extent(__pos);
746  ++__pos;
747  };
748  (__update(__indices), ...);
749  }
750  return __res;
751  }
752 
753  template<typename _IndexType>
754  consteval _IndexType
755  __static_quotient(std::span<const size_t> __sta_exts,
756  _IndexType __nom = __gnu_cxx::__int_traits<_IndexType>::__max)
757  {
758  for (auto __factor : __sta_exts)
759  {
760  if (__factor != dynamic_extent)
761  __nom /= _IndexType(__factor);
762  if (__nom == 0)
763  break;
764  }
765  return __nom;
766  }
767 
768  template<typename _Extents,
769  typename _IndexType = typename _Extents::index_type>
770  requires __is_extents<_Extents>
771  consteval _IndexType
772  __static_quotient(_IndexType __nom
773  = __gnu_cxx::__int_traits<_IndexType>::__max)
774  {
775  std::span<const size_t> __sta_exts = __static_extents<_Extents>();
776  return __static_quotient<_IndexType>(__sta_exts, __nom);
777  }
778 
779  template<typename _Extents>
780  constexpr bool
781  __is_representable_extents(const _Extents& __exts) noexcept
782  {
783  using _IndexType = _Extents::index_type;
784 
785  if constexpr (__contains_zero(__static_extents<_Extents>()))
786  return true;
787  else
788  {
789  constexpr auto __sta_quo = __static_quotient<_Extents>();
790  if constexpr (_Extents::rank_dynamic() == 0)
791  return __sta_quo != 0;
792  else
793  {
794  auto __dyn_exts = __dynamic_extents(__exts);
795  if (__contains_zero(__dyn_exts))
796  return true;
797 
798  if constexpr (__sta_quo == 0)
799  return false;
800  else
801  {
802  auto __dyn_quo = _IndexType(__sta_quo);
803  for (auto __factor : __dyn_exts)
804  {
805  __dyn_quo /= __factor;
806  if (__dyn_quo == 0)
807  return false;
808  }
809  return true;
810  }
811  }
812  }
813  }
814 
815  template<typename _Extents, typename _IndexType>
816  concept __representable_size = _Extents::rank_dynamic() != 0
817  || __contains_zero(__static_extents<_Extents>())
818  || (__static_quotient<_Extents, _IndexType>() != 0);
819 
820  template<typename _Layout, typename _Mapping>
821  concept __mapping_of =
822  is_same_v<typename _Layout::template mapping<
823  typename _Mapping::extents_type>,
824  _Mapping>;
825 
826  template<template<size_t> typename _Layout, typename _Mapping>
827  concept __padded_mapping_of = __mapping_of<
828  _Layout<_Mapping::padding_value>, _Mapping>;
829 
830 #ifdef __glibcxx_padded_layouts
831  template<typename _Mapping>
832  constexpr bool __is_left_padded_mapping = __padded_mapping_of<
833  layout_left_padded, _Mapping>;
834 
835  template<typename _Mapping>
836  constexpr bool __is_right_padded_mapping = __padded_mapping_of<
837  layout_right_padded, _Mapping>;
838 
839  template<typename _Mapping>
840  constexpr bool __is_padded_mapping = __is_left_padded_mapping<_Mapping>
841  || __is_right_padded_mapping<_Mapping>;
842 #endif
843 
844  template<typename _PaddedMapping>
845  consteval size_t
846  __get_static_stride()
847  { return _PaddedMapping::_PaddedStorage::_S_static_stride; }
848 
849  template<typename _Mapping>
850  concept __standardized_mapping = __mapping_of<layout_left, _Mapping>
851  || __mapping_of<layout_right, _Mapping>
852  || __mapping_of<layout_stride, _Mapping>
853 #ifdef __glibcxx_padded_layouts
854  || __is_left_padded_mapping<_Mapping>
855  || __is_right_padded_mapping<_Mapping>
856 #endif
857  ;
858 
859  // A tag type to create internal ctors.
860  class __internal_ctor
861  { };
862 
863  template<typename _Mapping>
864  constexpr typename _Mapping::index_type
865  __offset(const _Mapping& __m) noexcept
866  {
867  using _IndexType = typename _Mapping::index_type;
868  constexpr auto __rank = _Mapping::extents_type::rank();
869 
870  if constexpr (__standardized_mapping<_Mapping>)
871  return 0;
872  else if (__empty(__m.extents()))
873  return 0;
874  else
875  {
876  auto __impl = [&__m]<size_t... _Counts>(index_sequence<_Counts...>)
877  { return __m(((void) _Counts, _IndexType(0))...); };
878  return __impl(make_index_sequence<__rank>());
879  }
880  }
881 
882 #ifdef __glibcxx_submdspan
883  template<typename _Tp>
884  constexpr bool __is_extent_slice = false;
885 
886  template<typename _OffsetType, typename _ExtentType, typename _StrideType>
887  constexpr bool __is_extent_slice<extent_slice<_OffsetType,
888  _ExtentType, _StrideType>> = true;
889 
890  template<typename _Tp>
891  constexpr bool __is_range_slice = false;
892 
893  template<typename _FirstType, typename _LastType, typename _StrideType>
894  constexpr bool __is_range_slice<range_slice<_FirstType,
895  _LastType, _StrideType>> = true;
896 
897  template<typename _IndexType, typename _OIndexType>
898  consteval bool
899  __is_representable_integer(_OIndexType __value)
900  {
901  constexpr auto __min = __gnu_cxx::__int_traits<_IndexType>::__min;
902  constexpr auto __max = __gnu_cxx::__int_traits<_IndexType>::__max;
903  return std::cmp_less_equal(__min, __value)
904  && std::cmp_less_equal(__value, __max);
905  }
906 
907  template<typename _Tp>
908  constexpr bool __is_constant_wrapper = false;
909 
910  template<auto _Xv, typename _Tp>
911  constexpr bool __is_constant_wrapper<constant_wrapper<_Xv, _Tp>>
912  = true;
913 
914  template<size_t _Index, typename _Extents>
915  constexpr auto
916  __extract_extent(const _Extents& __exts)
917  {
918  using _IndexType = typename _Extents::index_type;
919  return extents<_IndexType, _Extents::static_extent(_Index)>{
920  __exts.extent(_Index)};
921  }
922 
923  template<typename _Slice, typename _IndexType>
924  concept __acceptable_slice_type = same_as<_Slice, full_extent_t>
925  || same_as<_Slice, _IndexType> || __is_constant_wrapper<_Slice>
926  || __is_extent_slice<_Slice>;
927 
928  template<typename _IndexType, typename... _Slices>
929  consteval auto
930  __subrank()
931  {
932  return (static_cast<size_t>(!convertible_to<_Slices, _IndexType>)
933  + ... + 0);
934  }
935 
936  template<typename _IndexType, typename... _Slices>
937  consteval auto
938  __inv_map_rank()
939  {
940  constexpr auto __rank = sizeof...(_Slices);
941  constexpr auto __sub_rank = __subrank<_IndexType, _Slices...>();
942  auto __map = std::array<size_t, __sub_rank>{};
943  auto __is_int_like = std::array<bool, __rank>{
944  convertible_to<_Slices, _IndexType>...};
945 
946  size_t __i = 0;
947  for (size_t __k = 0; __k < __rank; ++__k)
948  if (!__is_int_like[__k])
949  __map[__i++] = __k;
950  return __map;
951  }
952 
953  template<typename _Slice>
954  constexpr auto
955  __slice_begin(_Slice __slice)
956  {
957  if constexpr (same_as<_Slice, full_extent_t>)
958  return 0;
959  else if constexpr (__is_extent_slice<_Slice>)
960  return __slice.offset;
961  else
962  return __slice; // collapsing slice
963  }
964 
965  template<typename _Mapping, typename... _Slices>
966  constexpr size_t
967  __suboffset(const _Mapping& __mapping, const _Slices&... __slices)
968  {
969  using _IndexType = typename _Mapping::index_type;
970  auto __any_past_the_end = [&]<size_t... _Is>(index_sequence<_Is...>)
971  {
972  auto __is_past_the_end = [](const auto& __slice, const auto& __ext)
973  {
974  using _Slice = remove_cvref_t<decltype(__slice)>;
975  if constexpr (is_convertible_v<_Slice, _IndexType>)
976  return false;
977  else if constexpr (same_as<_Slice, full_extent_t>
978  && __ext.static_extent(0) != 0
979  && __ext.static_extent(0) != dynamic_extent)
980  return false;
981  else
982  return __mdspan::__slice_begin(__slice) == __ext.extent(0);
983  };
984 
985  const auto& __exts = __mapping.extents();
986  return ((__is_past_the_end(__slices...[_Is],
987  __mdspan::__extract_extent<_Is>(__exts))) || ...);
988  };
989 
990  if constexpr ((same_as<_Slices, full_extent_t> && ...))
991  return __mdspan::__offset(__mapping);
992 
993  if (__any_past_the_end(std::make_index_sequence<sizeof...(__slices)>()))
994  return __mapping.required_span_size();
995  return __mapping(__mdspan::__slice_begin(__slices)...);
996  }
997 
998  template<typename _IndexType, size_t _Extent, typename _Slice>
999  consteval size_t
1000  __static_slice_extent()
1001  {
1002  if constexpr (same_as<_Slice, full_extent_t>)
1003  return _Extent;
1004  else if constexpr (same_as<_Slice, constant_wrapper<_IndexType(0)>>)
1005  return 0;
1006  else if constexpr (__is_constant_wrapper<typename _Slice::extent_type>)
1007  return _Slice::extent_type::value;
1008  else
1009  return dynamic_extent;
1010  }
1011 
1012  template<size_t _K, typename _Extents, typename _Slice>
1013  constexpr typename _Extents::index_type
1014  __dynamic_slice_extent(const _Extents& __exts, _Slice __slice)
1015  {
1016  if constexpr (__is_extent_slice<_Slice>)
1017  return __slice.extent;
1018  else
1019  return __exts.extent(_K);
1020  }
1021 
1022  template<typename _IndexType, size_t... _Extents, typename... _Slices>
1023  requires (sizeof...(_Slices) == sizeof...(_Extents))
1024  constexpr auto
1025  __subextents(const extents<_IndexType, _Extents...>& __exts,
1026  _Slices... __slices)
1027  {
1028  constexpr auto __inv_map = __mdspan::__inv_map_rank<_IndexType, _Slices...>();
1029  auto __impl = [&]<size_t... _Indices>(std::index_sequence<_Indices...>)
1030  {
1031  using _SubExts = extents<_IndexType,
1032  __mdspan::__static_slice_extent<_IndexType,
1033  _Extents...[__inv_map[_Indices]],
1034  _Slices...[__inv_map[_Indices]]>()...>;
1035  if constexpr (_SubExts::rank_dynamic() == 0)
1036  return _SubExts{};
1037  else
1038  {
1039  using _StaticSubExtents = __mdspan::_StaticExtents<
1040  __mdspan::__static_extents<_SubExts>()>;
1041  auto __create = [&]<size_t... _Is>(std::index_sequence<_Is...>)
1042  {
1043  constexpr auto __slice_idx = [__inv_map](size_t __i) consteval
1044  {
1045  return __inv_map[_StaticSubExtents::_S_dynamic_index_inv(__i)];
1046  };
1047 
1048  return _SubExts{__mdspan::__dynamic_slice_extent<__slice_idx(_Is)>(
1049  __exts, __slices...[__slice_idx(_Is)])...};
1050  };
1051  constexpr auto __dyn_subrank = _SubExts::rank_dynamic();
1052  return __create(std::make_index_sequence<__dyn_subrank>());
1053  }
1054  };
1055 
1056  return __impl(std::make_index_sequence<__inv_map.size()>());
1057  }
1058 
1059  enum class _LayoutSide
1060  {
1061  __left,
1062  __right,
1063  __unknown
1064  };
1065 
1066  template<typename _Mapping>
1067  consteval _LayoutSide
1068  __mapping_side()
1069  {
1070  if constexpr (__is_left_padded_mapping<_Mapping>
1071  || __mapping_of<layout_left, _Mapping>)
1072  return _LayoutSide::__left;
1073  if constexpr (__is_right_padded_mapping<_Mapping>
1074  || __mapping_of<layout_right, _Mapping>)
1075  return _LayoutSide::__right;
1076  else
1077  return _LayoutSide::__unknown;
1078  }
1079 
1080  template<_LayoutSide _Side, size_t _Rank>
1081  struct _StridesTrait
1082  {
1083  static constexpr const _LayoutSide _S_side = _Side;
1084 
1085  static constexpr size_t
1086  _S_idx(size_t __k) noexcept
1087  {
1088  if constexpr (_Side == _LayoutSide::__left)
1089  return __k;
1090  else
1091  return _Rank - 1 - __k;
1092  }
1093 
1094  // Unifies the formulas for computing strides for padded and unpadded
1095  // layouts.
1096  template<typename _Mapping>
1097  static constexpr typename _Mapping::index_type
1098  _S_padded_extent(const _Mapping& __mapping, size_t __k)
1099  {
1100  if (__k == 0)
1101  return __mapping.stride(_S_idx(1));
1102  else
1103  return __mapping.extents().extent(_S_idx(__k));
1104  }
1105 
1106  template<typename _IndexType, typename... _Slices>
1107  static consteval auto
1108  _S_inv_map()
1109  {
1110  static_assert(_Side != _LayoutSide::__unknown);
1111  auto __impl = [&]<size_t... _Is>(std::index_sequence<_Is...>)
1112  {
1113  return __mdspan::__inv_map_rank<_IndexType, _Slices...[_S_idx(_Is)]...>();
1114  };
1115  return __impl(std::make_index_sequence<_Rank>());
1116  }
1117  };
1118 
1119  template<typename _SubExts, typename _Mapping, typename... _Slices>
1120  constexpr auto
1121  __substrides_generic(const _Mapping& __mapping, const _Slices&... __slices)
1122  {
1123  using _IndexType = typename _Mapping::index_type;
1124  if constexpr (_SubExts::rank() == 0)
1125  return array<_IndexType, _SubExts::rank()>{};
1126  else
1127  {
1128  auto __stride = [&__mapping](size_t __k, auto __slice) -> _IndexType
1129  {
1130  if constexpr (__is_extent_slice<decltype(__slice)>)
1131  if (__slice.extent > 1)
1132  return __mapping.stride(__k) * __slice.stride;
1133  return __mapping.stride(__k);
1134  };
1135 
1136  auto __impl = [&]<size_t... _Is>(std::index_sequence<_Is...>)
1137  {
1138  constexpr auto __inv_map
1139  = __mdspan::__inv_map_rank<_IndexType, _Slices...>();
1140  return array<_IndexType, _SubExts::rank()>{
1141  __stride(__inv_map[_Is], __slices...[__inv_map[_Is]])...};
1142  };
1143  return __impl(std::make_index_sequence<_SubExts::rank()>());
1144  }
1145  };
1146 
1147  template<typename _SubExts, typename _Mapping, typename... _Slices>
1148  constexpr auto
1149  __substrides_standardized(const _Mapping& __mapping,
1150  const _Slices&... __slices)
1151  {
1152  using _IndexType = typename _Mapping::index_type;
1153  using _Trait = _StridesTrait<__mapping_side<_Mapping>(),
1154  _Mapping::extents_type::rank()>;
1155  using _SubTrait = _StridesTrait<__mapping_side<_Mapping>(), _SubExts::rank()>;
1156 
1157  constexpr size_t __sub_rank = _SubExts::rank();
1158 
1159  std::array<_IndexType, __sub_rank> __ret;
1160  if constexpr (__sub_rank > 0)
1161  {
1162  constexpr auto __inv_map
1163  = _Trait::template _S_inv_map<_IndexType, _Slices...>();
1164  auto __loop = [&]<size_t... _Ks>(std::index_sequence<_Ks...>)
1165  {
1166  size_t __i0 = 0;
1167  size_t __stride = 1;
1168  auto __body = [&](size_t __k, auto __slice)
1169  {
1170  for (size_t __i = __i0; __i < __inv_map[__k]; ++__i)
1171  __stride *= _Trait::_S_padded_extent(__mapping, __i);
1172 
1173  size_t __krev = _SubTrait::_S_idx(__k);
1174  if constexpr (__is_extent_slice<decltype(__slice)>)
1175  {
1176  if (__slice.extent > 1)
1177  __ret[__krev] = __stride * __slice.stride;
1178  else
1179  __ret[__krev] = __stride;
1180  }
1181  else
1182  __ret[__krev] = __stride;
1183 
1184  __i0 = __inv_map[__k];
1185  };
1186 
1187  ((__body(_Ks, __slices...[_Trait::_S_idx(__inv_map[_Ks])])),...);
1188  };
1189  __loop(std::make_index_sequence<__sub_rank>());
1190  }
1191  return __ret;
1192  }
1193 
1194 
1195  template<typename _SubExts, typename _Mapping, typename... _Slices>
1196  constexpr auto
1197  __substrides(const _Mapping& __mapping, const _Slices&... __slices)
1198  {
1199  if constexpr (__mdspan::__mapping_side<_Mapping>() == _LayoutSide::__unknown)
1200  return __mdspan::__substrides_generic<_SubExts>(__mapping, __slices...);
1201  else
1202  return __mdspan::__substrides_standardized<_SubExts>(__mapping, __slices...);
1203  }
1204 
1205  template<typename _Slice>
1206  concept __is_unit_stride_slice = (__mdspan::__is_extent_slice<_Slice>
1207  && __mdspan::__is_constant_wrapper<typename _Slice::stride_type>
1208  && _Slice::stride_type::value == 1)
1209  || std::same_as<_Slice, full_extent_t>;
1210 
1211  // These are (forced) exclusive categories:
1212  // - full & collapsing: obvious,
1213  // - unit_extent_slice: extent_slice{a, b, cw<1>}, but not `full`,
1214  // - extent_slice: extent_slice{a, b, c} with c != cw<1>.
1215  enum class _SliceKind
1216  {
1217  __extent_slice,
1218  __unit_stride_slice,
1219  __full,
1220  __collapsing
1221  };
1222 
1223  template<typename _Slice>
1224  consteval _SliceKind
1225  __make_slice_kind()
1226  {
1227  if constexpr (std::same_as<_Slice, full_extent_t>)
1228  return _SliceKind::__full;
1229  else if constexpr (__mdspan::__is_extent_slice<_Slice>)
1230  {
1231  if constexpr (__mdspan::__is_unit_stride_slice<_Slice>)
1232  return _SliceKind::__unit_stride_slice;
1233  else
1234  return _SliceKind::__extent_slice;
1235  }
1236  else
1237  return _SliceKind::__collapsing;
1238  }
1239 
1240  template<typename... _Slices>
1241  consteval array<_SliceKind, sizeof...(_Slices)>
1242  __make_slice_kind_array()
1243  {
1244  return array<_SliceKind, sizeof...(_Slices)>{
1245  __mdspan::__make_slice_kind<_Slices>()...};
1246  }
1247 
1248  // __block_size - 1
1249  // [full, ..., full, unit_slice , *]
1250  consteval bool
1251  __is_block(span<const _SliceKind> __slice_kinds, size_t __block_size)
1252  {
1253  if (__block_size == 0)
1254  return false;
1255 
1256  if (__block_size > __slice_kinds.size())
1257  return false;
1258 
1259  for (size_t __i = 0; __i < __block_size - 1; ++__i)
1260  if (__slice_kinds[__i] != _SliceKind::__full)
1261  return false;
1262 
1263  auto __last = __slice_kinds[__block_size - 1];
1264  return __last == _SliceKind::__full
1265  || __last == _SliceKind::__unit_stride_slice;
1266  }
1267 
1268  // __u __u + __sub_rank-2
1269  // [unit_slice, i, ..., k, full, ..., full, unit_slice, *]
1270  static consteval size_t
1271  __padded_block_begin_generic(span<const _SliceKind> __slice_kinds,
1272  size_t __sub_rank)
1273  {
1274  if (__slice_kinds[0] != _SliceKind::__full
1275  && __slice_kinds[0] != _SliceKind::__unit_stride_slice)
1276  return dynamic_extent;
1277  else if (__slice_kinds.size() == 1)
1278  return dynamic_extent;
1279  else
1280  {
1281  size_t __u = 1;
1282  while(__u < __slice_kinds.size()
1283  && __slice_kinds[__u] == _SliceKind::__collapsing)
1284  ++__u;
1285 
1286  if (__mdspan::__is_block(__slice_kinds.subspan(__u), __sub_rank -1))
1287  return __u;
1288  return dynamic_extent;
1289  }
1290  }
1291 
1292  template<_LayoutSide _Side, size_t _Nm>
1293  static consteval size_t
1294  __padded_block_begin(span<const _SliceKind, _Nm> __slice_kinds, size_t __sub_rank)
1295  {
1296  if constexpr (_Side == _LayoutSide::__left)
1297  return __mdspan::__padded_block_begin_generic(__slice_kinds, __sub_rank);
1298  else
1299  {
1300  std::array<_SliceKind, _Nm> __rev_slices;
1301  for(size_t __i = 0; __i < _Nm; ++__i)
1302  __rev_slices[__i] = __slice_kinds[_Nm - 1 - __i];
1303  auto __rev_slice_kinds = span<const _SliceKind>(__rev_slices);
1304 
1305  auto __u = __mdspan::__padded_block_begin_generic(__rev_slice_kinds,
1306  __sub_rank);
1307  return __u == dynamic_extent ? dynamic_extent : _Nm - 1 - __u;
1308  }
1309  }
1310 
1311  template<_LayoutSide _Side, bool _Padded>
1312  struct _SubMdspanMapping;
1313 
1314  template<>
1315  struct _SubMdspanMapping<_LayoutSide::__left, false>
1316  {
1317  using _Layout = layout_left;
1318  template<size_t _Pad> using _PaddedLayout = layout_left_padded<_Pad>;
1319 
1320  template<typename _Mapping, size_t _Us>
1321  static consteval size_t
1322  _S_pad()
1323  {
1324  using _Extents = typename _Mapping::extents_type;
1325  constexpr auto __sta_exts = __mdspan::__static_extents<_Extents>(0, _Us);
1326  if constexpr (!__mdspan::__all_static(__sta_exts))
1327  return dynamic_extent;
1328  else
1329  return __mdspan::__fwd_prod(__sta_exts);
1330  }
1331 
1332  template<size_t _Nm>
1333  static consteval bool
1334  _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds, size_t __sub_rank)
1335  { return __mdspan::__is_block(__slice_kinds, __sub_rank); }
1336  };
1337 
1338  template<>
1339  struct _SubMdspanMapping<_LayoutSide::__left, true>
1340  {
1341  using _Layout = layout_left;
1342  template<size_t _Pad> using _PaddedLayout = layout_left_padded<_Pad>;
1343 
1344  template<typename _Mapping, size_t _Us>
1345  static consteval size_t
1346  _S_pad()
1347  {
1348  using _Extents = typename _Mapping::extents_type;
1349  constexpr auto __sta_exts
1350  = __mdspan::__static_extents<_Extents>(1, _Us);
1351  constexpr auto __sta_padstride
1352  = __mdspan::__get_static_stride<_Mapping>();
1353  if constexpr (__sta_padstride == dynamic_extent
1354  || !__mdspan::__all_static(__sta_exts))
1355  return dynamic_extent;
1356  else
1357  return __sta_padstride * __mdspan::__fwd_prod(__sta_exts);
1358  }
1359 
1360  template<size_t _Nm>
1361  static consteval bool
1362  _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
1363  size_t __sub_rank)
1364  {
1365  if (__sub_rank == 1)
1366  return __slice_kinds[0] == _SliceKind::__unit_stride_slice
1367  || __slice_kinds[0] == _SliceKind::__full;
1368  else
1369  return false;
1370  }
1371  };
1372 
1373  template<>
1374  struct _SubMdspanMapping<_LayoutSide::__right, false>
1375  {
1376  using _Layout = layout_right;
1377  template<size_t _Pad> using _PaddedLayout = layout_right_padded<_Pad>;
1378 
1379  template<typename _Mapping, size_t _Us>
1380  static consteval size_t
1381  _S_pad()
1382  {
1383  using _Extents = typename _Mapping::extents_type;
1384  constexpr auto __rank = _Extents::rank();
1385  constexpr auto __sta_exts
1386  = __mdspan::__static_extents<_Extents>(_Us + 1, __rank);
1387  if constexpr (!__mdspan::__all_static(__sta_exts))
1388  return dynamic_extent;
1389  else
1390  return __fwd_prod(__sta_exts);
1391  }
1392 
1393  template<size_t _Nm>
1394  static consteval bool
1395  _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
1396  size_t __sub_rank)
1397  {
1398  auto __rev_slice_kinds = array<_SliceKind, _Nm>{};
1399  for(size_t __i = 0; __i < _Nm; ++__i)
1400  __rev_slice_kinds[__i] = __slice_kinds[_Nm - 1 - __i];
1401  return __mdspan::__is_block(span(__rev_slice_kinds), __sub_rank);
1402  }
1403  };
1404 
1405  template<>
1406  struct _SubMdspanMapping<_LayoutSide::__right, true>
1407  {
1408  using _Layout = layout_right;
1409  template<size_t _Pad> using _PaddedLayout = layout_right_padded<_Pad>;
1410 
1411  template<typename _Mapping, size_t _Us>
1412  static consteval size_t
1413  _S_pad()
1414  {
1415  using _Extents = typename _Mapping::extents_type;
1416  constexpr auto __rank = _Extents::rank();
1417  constexpr auto __sta_exts
1418  = __mdspan::__static_extents<_Extents>(_Us + 1, __rank - 1);
1419  constexpr auto __sta_padstride
1420  = __mdspan::__get_static_stride<_Mapping>();
1421  if constexpr (__sta_padstride == dynamic_extent
1422  || !__mdspan::__all_static(__sta_exts))
1423  return dynamic_extent;
1424  else
1425  return __sta_padstride * __mdspan::__fwd_prod(__sta_exts);
1426  }
1427 
1428  template<size_t _Nm>
1429  static consteval bool
1430  _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
1431  size_t __sub_rank)
1432  {
1433  if (__sub_rank == 1)
1434  return __slice_kinds[_Nm - 1] == _SliceKind::__unit_stride_slice
1435  || __slice_kinds[_Nm - 1] == _SliceKind::__full;
1436  else
1437  return false;
1438  }
1439  };
1440 
1441 
1442  template<typename _Mapping>
1443  constexpr auto
1444  __submdspan_mapping_impl(const _Mapping& __mapping)
1445  { return submdspan_mapping_result{__mapping, 0}; }
1446 
1447  template<typename _Mapping, typename... _Slices>
1448  requires (sizeof...(_Slices) > 0)
1449  constexpr auto
1450  __submdspan_mapping_impl(const _Mapping& __mapping, _Slices... __slices)
1451  {
1452  using _IndexType = typename _Mapping::index_type;
1453  static_assert((__acceptable_slice_type<_Slices, _IndexType> && ...));
1454 
1455  constexpr auto __side = __mdspan::__mapping_side<_Mapping>();
1456  constexpr auto __rank = sizeof...(_Slices);
1457  using _Trait = _SubMdspanMapping<__side, __is_padded_mapping<_Mapping>>;
1458  using _SliceView = span<const _SliceKind, __rank>;
1459 
1460  constexpr auto __slice_kinds = __mdspan::__make_slice_kind_array<_Slices...>();
1461  auto __offset = __mdspan::__suboffset(__mapping, __slices...);
1462  auto __sub_exts = __mdspan::__subextents(__mapping.extents(), __slices...);
1463  using _SubExts = decltype(__sub_exts);
1464  constexpr auto __sub_rank = _SubExts::rank();
1465  if constexpr (__sub_rank == 0)
1466  return submdspan_mapping_result{
1467  typename _Trait::_Layout::mapping(__sub_exts), __offset};
1468  else if constexpr (_Trait::_S_is_unpadded_submdspan(
1469  _SliceView(__slice_kinds), __sub_rank))
1470  return submdspan_mapping_result{
1471  typename _Trait::_Layout::mapping(__sub_exts), __offset};
1472  else if constexpr (
1473  constexpr auto __u = __padded_block_begin<__side>(
1474  _SliceView(__slice_kinds), __sub_rank);
1475  __u != dynamic_extent)
1476  {
1477  constexpr auto __pad = _Trait::template _S_pad<_Mapping, __u>();
1478  using _Layout = typename _Trait::template _PaddedLayout<__pad>;
1479  return submdspan_mapping_result{
1480  typename _Layout::mapping(__sub_exts, __mapping.stride(__u)),
1481  __offset};
1482  }
1483  else
1484  {
1485  auto __sub_strides
1486  = __mdspan::__substrides<_SubExts>(__mapping, __slices...);
1487  return submdspan_mapping_result{
1488  layout_stride::mapping(__sub_exts, __sub_strides), __offset};
1489  }
1490  }
1491 #endif // __glibcxx_submdspan
1492  }
1493 
1494  template<typename _Extents>
1495  class layout_left::mapping
1496  {
1497  public:
1498  using extents_type = _Extents;
1499  using index_type = typename extents_type::index_type;
1500  using size_type = typename extents_type::size_type;
1501  using rank_type = typename extents_type::rank_type;
1502  using layout_type = layout_left;
1503 
1504  static_assert(__mdspan::__representable_size<extents_type, index_type>,
1505  "The size of extents_type must be representable as index_type");
1506 
1507  constexpr
1508  mapping() noexcept = default;
1509 
1510  constexpr
1511  mapping(const mapping&) noexcept = default;
1512 
1513  constexpr
1514  mapping(const extents_type& __extents) noexcept
1515  : _M_extents(__extents)
1516  { __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); }
1517 
1518  template<typename _OExtents>
1519  requires is_constructible_v<extents_type, _OExtents>
1520  constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
1521  mapping(const mapping<_OExtents>& __other) noexcept
1522  : mapping(__other.extents(), __mdspan::__internal_ctor{})
1523  { }
1524 
1525  template<typename _OExtents>
1526  requires (extents_type::rank() <= 1)
1527  && is_constructible_v<extents_type, _OExtents>
1528  constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
1529  mapping(const layout_right::mapping<_OExtents>& __other) noexcept
1530  : mapping(__other.extents(), __mdspan::__internal_ctor{})
1531  { }
1532 
1533  // noexcept for consistency with other layouts.
1534  template<typename _OExtents>
1535  requires is_constructible_v<extents_type, _OExtents>
1536  constexpr explicit(!(extents_type::rank() == 0
1537  && is_convertible_v<_OExtents, extents_type>))
1538  mapping(const layout_stride::mapping<_OExtents>& __other) noexcept
1539  : mapping(__other.extents(), __mdspan::__internal_ctor{})
1540  { __glibcxx_assert(*this == __other); }
1541 
1542 #if __glibcxx_padded_layouts
1543  template<typename _LeftpadMapping>
1544  requires __mdspan::__is_left_padded_mapping<_LeftpadMapping>
1545  && is_constructible_v<extents_type,
1546  typename _LeftpadMapping::extents_type>
1547  constexpr
1548  explicit(!is_convertible_v<typename _LeftpadMapping::extents_type,
1549  extents_type>)
1550  mapping(const _LeftpadMapping& __other) noexcept
1551  : mapping(__other.extents(), __mdspan::__internal_ctor{})
1552  {
1553  constexpr size_t __ostride_sta
1554  = __mdspan::__get_static_stride<_LeftpadMapping>();
1555 
1556  if constexpr (extents_type::rank() > 1)
1557  {
1558  if constexpr (extents_type::static_extent(0) != dynamic_extent
1559  && __ostride_sta != dynamic_extent)
1560  static_assert(extents_type::static_extent(0) == __ostride_sta);
1561  else
1562  __glibcxx_assert(__other.stride(1)
1563  == __other.extents().extent(0));
1564  }
1565  }
1566 #endif // __glibcxx_padded_layouts
1567 
1568  constexpr mapping&
1569  operator=(const mapping&) noexcept = default;
1570 
1571  constexpr const extents_type&
1572  extents() const noexcept { return _M_extents; }
1573 
1574  constexpr index_type
1575  required_span_size() const noexcept
1576  { return __mdspan::__size(_M_extents); }
1577 
1578  // _GLIBCXX_RESOLVE_LIB_DEFECTS
1579  // 4314. Missing move in mdspan layout mapping::operator()
1580  template<__mdspan::__valid_index_type<index_type>... _Indices>
1581  requires (sizeof...(_Indices) == extents_type::rank())
1582  constexpr index_type
1583  operator()(_Indices... __indices) const noexcept
1584  {
1585  return __mdspan::__linear_index_left(_M_extents,
1586  static_cast<index_type>(std::move(__indices))...);
1587  }
1588 
1589  static constexpr bool
1590  is_always_unique() noexcept { return true; }
1591 
1592  static constexpr bool
1593  is_always_exhaustive() noexcept { return true; }
1594 
1595  static constexpr bool
1596  is_always_strided() noexcept { return true; }
1597 
1598  static constexpr bool
1599  is_unique() noexcept { return true; }
1600 
1601  static constexpr bool
1602  is_exhaustive() noexcept { return true; }
1603 
1604  static constexpr bool
1605  is_strided() noexcept { return true; }
1606 
1607  constexpr index_type
1608  stride(rank_type __i) const noexcept
1609  requires (extents_type::rank() > 0)
1610  {
1611  __glibcxx_assert(__i < extents_type::rank());
1612  return __mdspan::__fwd_prod(_M_extents, __i);
1613  }
1614 
1615  template<typename _OExtents>
1616  requires (extents_type::rank() == _OExtents::rank())
1617  friend constexpr bool
1618  operator==(const mapping& __self, const mapping<_OExtents>& __other)
1619  noexcept
1620  { return __self.extents() == __other.extents(); }
1621 
1622  private:
1623  template<typename _OExtents>
1624  constexpr explicit
1625  mapping(const _OExtents& __oexts, __mdspan::__internal_ctor) noexcept
1626  : _M_extents(__oexts)
1627  {
1628  static_assert(__mdspan::__representable_size<_OExtents, index_type>,
1629  "The size of OtherExtents must be representable as index_type");
1630  __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents));
1631  }
1632 
1633 #if __glibcxx_submdspan
1634  template<typename... _Slices>
1635  requires (extents_type::rank() == sizeof...(_Slices))
1636  friend constexpr auto
1637  submdspan_mapping(const mapping& __mapping, _Slices... __slices)
1638  { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
1639 #endif // __glibcxx_submdspan
1640 
1641  [[no_unique_address]] extents_type _M_extents{};
1642  };
1643 
1644  namespace __mdspan
1645  {
1646  template<typename _Extents, typename... _Indices>
1647  constexpr typename _Extents::index_type
1648  __linear_index_right(const _Extents& __exts, _Indices... __indices)
1649  noexcept
1650  {
1651  using _IndexType = typename _Extents::index_type;
1652  array<_IndexType, sizeof...(__indices)> __ind_arr{__indices...};
1653  _IndexType __res = 0;
1654  if constexpr (sizeof...(__indices) > 0)
1655  {
1656  _IndexType __mult = 1;
1657  auto __update = [&, __pos = __exts.rank()](_IndexType) mutable
1658  {
1659  --__pos;
1660  _GLIBCXX_DEBUG_ASSERT(cmp_less(__ind_arr[__pos],
1661  __exts.extent(__pos)));
1662  __res += __ind_arr[__pos] * __mult;
1663  __mult *= __exts.extent(__pos);
1664  };
1665  (__update(__indices), ...);
1666  }
1667  return __res;
1668  }
1669  }
1670 
1671  template<typename _Extents>
1672  class layout_right::mapping
1673  {
1674  public:
1675  using extents_type = _Extents;
1676  using index_type = typename extents_type::index_type;
1677  using size_type = typename extents_type::size_type;
1678  using rank_type = typename extents_type::rank_type;
1679  using layout_type = layout_right;
1680 
1681  static_assert(__mdspan::__representable_size<extents_type, index_type>,
1682  "The size of extents_type must be representable as index_type");
1683 
1684  constexpr
1685  mapping() noexcept = default;
1686 
1687  constexpr
1688  mapping(const mapping&) noexcept = default;
1689 
1690  constexpr
1691  mapping(const extents_type& __extents) noexcept
1692  : _M_extents(__extents)
1693  { __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); }
1694 
1695  template<typename _OExtents>
1696  requires is_constructible_v<extents_type, _OExtents>
1697  constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
1698  mapping(const mapping<_OExtents>& __other) noexcept
1699  : mapping(__other.extents(), __mdspan::__internal_ctor{})
1700  { }
1701 
1702  template<typename _OExtents>
1703  requires (extents_type::rank() <= 1)
1704  && is_constructible_v<extents_type, _OExtents>
1705  constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
1706  mapping(const layout_left::mapping<_OExtents>& __other) noexcept
1707  : mapping(__other.extents(), __mdspan::__internal_ctor{})
1708  { }
1709 
1710  template<typename _OExtents>
1711  requires is_constructible_v<extents_type, _OExtents>
1712  constexpr explicit(!(extents_type::rank() == 0
1713  && is_convertible_v<_OExtents, extents_type>))
1714  mapping(const layout_stride::mapping<_OExtents>& __other) noexcept
1715  : mapping(__other.extents(), __mdspan::__internal_ctor{})
1716  { __glibcxx_assert(*this == __other); }
1717 
1718 #if __glibcxx_padded_layouts
1719  template<typename _RightPaddedMapping>
1720  requires __mdspan::__is_right_padded_mapping<_RightPaddedMapping>
1721  && is_constructible_v<extents_type,
1722  typename _RightPaddedMapping::extents_type>
1723  constexpr
1724  explicit(!is_convertible_v<typename _RightPaddedMapping::extents_type,
1725  extents_type>)
1726  mapping(const _RightPaddedMapping& __other) noexcept
1727  : mapping(__other.extents(), __mdspan::__internal_ctor{})
1728  {
1729  constexpr size_t __rank = extents_type::rank();
1730  constexpr size_t __ostride_sta
1731  = __mdspan::__get_static_stride<_RightPaddedMapping>();
1732 
1733  if constexpr (__rank > 1)
1734  {
1735  if constexpr (extents_type::static_extent(__rank - 1) != dynamic_extent
1736  && __ostride_sta != dynamic_extent)
1737  static_assert(extents_type::static_extent(__rank - 1)
1738  == __ostride_sta);
1739  else
1740  __glibcxx_assert(__other.stride(__rank - 2)
1741  == __other.extents().extent(__rank - 1));
1742  }
1743  }
1744 #endif
1745 
1746  constexpr mapping&
1747  operator=(const mapping&) noexcept = default;
1748 
1749  constexpr const extents_type&
1750  extents() const noexcept { return _M_extents; }
1751 
1752  constexpr index_type
1753  required_span_size() const noexcept
1754  { return __mdspan::__size(_M_extents); }
1755 
1756  // _GLIBCXX_RESOLVE_LIB_DEFECTS
1757  // 4314. Missing move in mdspan layout mapping::operator()
1758  template<__mdspan::__valid_index_type<index_type>... _Indices>
1759  requires (sizeof...(_Indices) == extents_type::rank())
1760  constexpr index_type
1761  operator()(_Indices... __indices) const noexcept
1762  {
1763  return __mdspan::__linear_index_right(
1764  _M_extents, static_cast<index_type>(std::move(__indices))...);
1765  }
1766 
1767  static constexpr bool
1768  is_always_unique() noexcept
1769  { return true; }
1770 
1771  static constexpr bool
1772  is_always_exhaustive() noexcept
1773  { return true; }
1774 
1775  static constexpr bool
1776  is_always_strided() noexcept
1777  { return true; }
1778 
1779  static constexpr bool
1780  is_unique() noexcept
1781  { return true; }
1782 
1783  static constexpr bool
1784  is_exhaustive() noexcept
1785  { return true; }
1786 
1787  static constexpr bool
1788  is_strided() noexcept
1789  { return true; }
1790 
1791  constexpr index_type
1792  stride(rank_type __i) const noexcept
1793  requires (extents_type::rank() > 0)
1794  {
1795  __glibcxx_assert(__i < extents_type::rank());
1796  return __mdspan::__rev_prod(_M_extents, __i);
1797  }
1798 
1799  template<typename _OExtents>
1800  requires (extents_type::rank() == _OExtents::rank())
1801  friend constexpr bool
1802  operator==(const mapping& __self, const mapping<_OExtents>& __other)
1803  noexcept
1804  { return __self.extents() == __other.extents(); }
1805 
1806  private:
1807  template<typename _OExtents>
1808  constexpr explicit
1809  mapping(const _OExtents& __oexts, __mdspan::__internal_ctor) noexcept
1810  : _M_extents(__oexts)
1811  {
1812  static_assert(__mdspan::__representable_size<_OExtents, index_type>,
1813  "The size of OtherExtents must be representable as index_type");
1814  __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents));
1815  }
1816 
1817 #if __glibcxx_submdspan
1818  template<typename... _Slices>
1819  requires (extents_type::rank() == sizeof...(_Slices))
1820  friend constexpr auto
1821  submdspan_mapping(const mapping& __mapping, _Slices... __slices)
1822  { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
1823 #endif // __glibcxx_submdspan
1824 
1825  [[no_unique_address]] extents_type _M_extents{};
1826  };
1827 
1828  namespace __mdspan
1829  {
1830  template<typename _Mp>
1831  concept __mapping_alike = requires
1832  {
1833  requires __is_extents<typename _Mp::extents_type>;
1834  { _Mp::is_always_strided() } -> same_as<bool>;
1835  { _Mp::is_always_exhaustive() } -> same_as<bool>;
1836  { _Mp::is_always_unique() } -> same_as<bool>;
1837  bool_constant<_Mp::is_always_strided()>::value;
1838  bool_constant<_Mp::is_always_exhaustive()>::value;
1839  bool_constant<_Mp::is_always_unique()>::value;
1840  };
1841 
1842  template<typename _Mapping, typename... _Indices>
1843  constexpr typename _Mapping::index_type
1844  __linear_index_strides(const _Mapping& __m, _Indices... __indices)
1845  noexcept
1846  {
1847  using _IndexType = typename _Mapping::index_type;
1848  _IndexType __res = 0;
1849  if constexpr (sizeof...(__indices) > 0)
1850  {
1851  auto __update = [&, __pos = 0u](_IndexType __idx) mutable
1852  {
1853  _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx,
1854  __m.extents().extent(__pos)));
1855  __res += __idx * __m.stride(__pos++);
1856  };
1857  (__update(__indices), ...);
1858  }
1859  return __res;
1860  }
1861  }
1862 
1863  template<typename _Extents>
1864  class layout_stride::mapping
1865  {
1866  public:
1867  using extents_type = _Extents;
1868  using index_type = typename extents_type::index_type;
1869  using size_type = typename extents_type::size_type;
1870  using rank_type = typename extents_type::rank_type;
1871  using layout_type = layout_stride;
1872 
1873  static_assert(__mdspan::__representable_size<extents_type, index_type>,
1874  "The size of extents_type must be representable as index_type");
1875 
1876  constexpr
1877  mapping() noexcept
1878  {
1879  // The precondition is either statically asserted, or automatically
1880  // satisfied because dynamic extents are zero-initialized.
1881  size_t __stride = 1;
1882  for (size_t __i = extents_type::rank(); __i > 0; --__i)
1883  {
1884  _M_strides[__i - 1] = index_type(__stride);
1885  __stride *= size_t(_M_extents.extent(__i - 1));
1886  }
1887  }
1888 
1889  constexpr
1890  mapping(const mapping&) noexcept = default;
1891 
1892  template<typename _OIndexType>
1893  requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
1894  constexpr
1895  mapping(const extents_type& __exts,
1896  span<_OIndexType, extents_type::rank()> __strides) noexcept
1897  : _M_extents(__exts)
1898  {
1899  for (size_t __i = 0; __i < extents_type::rank(); ++__i)
1900  _M_strides[__i] = index_type(as_const(__strides[__i]));
1901  }
1902 
1903  template<typename _OIndexType>
1904  requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
1905  constexpr
1906  mapping(const extents_type& __exts,
1907  const array<_OIndexType, extents_type::rank()>& __strides)
1908  noexcept
1909  : mapping(__exts,
1910  span<const _OIndexType, extents_type::rank()>(__strides))
1911  { }
1912 
1913  template<__mdspan::__mapping_alike _StridedMapping>
1914  requires (is_constructible_v<extents_type,
1915  typename _StridedMapping::extents_type>
1916  && _StridedMapping::is_always_unique()
1917  && _StridedMapping::is_always_strided())
1918  constexpr explicit(!(
1919  is_convertible_v<typename _StridedMapping::extents_type, extents_type>
1920  && __mdspan::__standardized_mapping<_StridedMapping>))
1921  mapping(const _StridedMapping& __other) noexcept
1922  : _M_extents(__other.extents())
1923  {
1924  using _OIndexType = _StridedMapping::index_type;
1925  using _OExtents = _StridedMapping::extents_type;
1926 
1927  __glibcxx_assert(__mdspan::__offset(__other) == 0);
1928  static_assert(__mdspan::__representable_size<_OExtents, index_type>,
1929  "The size of StridedMapping::extents_type must be representable as"
1930  " index_type");
1931  if constexpr (cmp_greater(__gnu_cxx::__int_traits<_OIndexType>::__max,
1932  __gnu_cxx::__int_traits<index_type>::__max))
1933  __glibcxx_assert(!cmp_less(
1934  __gnu_cxx::__int_traits<index_type>::__max,
1935  __other.required_span_size())
1936  && "other.required_span_size() must be representable"
1937  " as index_type");
1938  if constexpr (extents_type::rank() > 0)
1939  for (size_t __i = 0; __i < extents_type::rank(); ++__i)
1940  _M_strides[__i] = index_type(__other.stride(__i));
1941  }
1942 
1943  constexpr mapping&
1944  operator=(const mapping&) noexcept = default;
1945 
1946  constexpr const extents_type&
1947  extents() const noexcept { return _M_extents; }
1948 
1949  constexpr array<index_type, extents_type::rank()>
1950  strides() const noexcept
1951  {
1952  array<index_type, extents_type::rank()> __ret;
1953  for (size_t __i = 0; __i < extents_type::rank(); ++__i)
1954  __ret[__i] = _M_strides[__i];
1955  return __ret;
1956  }
1957 
1958  constexpr index_type
1959  required_span_size() const noexcept
1960  {
1961  if (__mdspan::__empty(_M_extents))
1962  return 0;
1963 
1964  index_type __ret = 1;
1965  for (size_t __i = 0; __i < extents_type::rank(); ++__i)
1966  __ret += (_M_extents.extent(__i) - 1) * _M_strides[__i];
1967  return __ret;
1968  }
1969 
1970  // _GLIBCXX_RESOLVE_LIB_DEFECTS
1971  // 4314. Missing move in mdspan layout mapping::operator()
1972  template<__mdspan::__valid_index_type<index_type>... _Indices>
1973  requires (sizeof...(_Indices) == extents_type::rank())
1974  constexpr index_type
1975  operator()(_Indices... __indices) const noexcept
1976  {
1977  return __mdspan::__linear_index_strides(*this,
1978  static_cast<index_type>(std::move(__indices))...);
1979  }
1980 
1981  static constexpr bool
1982  is_always_unique() noexcept { return true; }
1983 
1984  // _GLIBCXX_RESOLVE_LIB_DEFECTS
1985  // 4266. layout_stride::mapping should treat empty mappings as exhaustive
1986  static constexpr bool
1987  is_always_exhaustive() noexcept
1988  {
1989  return (_Extents::rank() == 0) || __mdspan::__contains_zero(
1990  __mdspan::__static_extents<extents_type>());
1991  }
1992 
1993  static constexpr bool
1994  is_always_strided() noexcept { return true; }
1995 
1996  static constexpr bool
1997  is_unique() noexcept { return true; }
1998 
1999  // _GLIBCXX_RESOLVE_LIB_DEFECTS
2000  // 4266. layout_stride::mapping should treat empty mappings as exhaustive
2001  constexpr bool
2002  is_exhaustive() const noexcept
2003  {
2004  if constexpr (!is_always_exhaustive())
2005  {
2006  auto __size = __mdspan::__size(_M_extents);
2007  if(__size > 0)
2008  return __size == required_span_size();
2009  }
2010  return true;
2011  }
2012 
2013  static constexpr bool
2014  is_strided() noexcept { return true; }
2015 
2016  constexpr index_type
2017  stride(rank_type __r) const noexcept { return _M_strides[__r]; }
2018 
2019  template<__mdspan::__mapping_alike _OMapping>
2020  requires ((extents_type::rank() == _OMapping::extents_type::rank())
2021  && _OMapping::is_always_strided())
2022  friend constexpr bool
2023  operator==(const mapping& __self, const _OMapping& __other) noexcept
2024  {
2025  if (__self.extents() != __other.extents())
2026  return false;
2027  if constexpr (extents_type::rank() > 0)
2028  for (size_t __i = 0; __i < extents_type::rank(); ++__i)
2029  if (!cmp_equal(__self.stride(__i), __other.stride(__i)))
2030  return false;
2031  return __mdspan::__offset(__other) == 0;
2032  }
2033 
2034  private:
2035 #if __glibcxx_submdspan
2036  template<typename... _Slices>
2037  requires (extents_type::rank() == sizeof...(_Slices))
2038  friend constexpr auto
2039  submdspan_mapping(const mapping& __mapping, _Slices... __slices)
2040  {
2041  if constexpr (sizeof...(_Slices) == 0)
2042  return submdspan_mapping_result{__mapping, 0};
2043  else
2044  {
2045  auto __offset = __mdspan::__suboffset(__mapping, __slices...);
2046  auto __sub_exts = __mdspan::__subextents(__mapping.extents(), __slices...);
2047  auto __sub_strides
2048  = __mdspan::__substrides<decltype(__sub_exts)>(__mapping, __slices...);
2049  return submdspan_mapping_result{
2050  layout_stride::mapping(__sub_exts, __sub_strides), __offset};
2051  }
2052  }
2053 #endif
2054 
2055  using _Strides = typename __array_traits<index_type,
2056  extents_type::rank()>::_Type;
2057  [[no_unique_address]] extents_type _M_extents;
2058  [[no_unique_address]] _Strides _M_strides;
2059  };
2060 
2061 #ifdef __glibcxx_padded_layouts
2062  namespace __mdspan
2063  {
2064  constexpr size_t
2065  __least_multiple(size_t __x, size_t __y)
2066  {
2067  if (__x <= 1)
2068  return __y;
2069  return (__y / __x + (__y % __x != 0)) * __x ;
2070  }
2071 
2072  template<typename _IndexType>
2073  constexpr bool
2074  __is_representable_least_multiple(size_t __x, size_t __y)
2075  {
2076  constexpr auto __y_max = __gnu_cxx::__int_traits<_IndexType>::__max;
2077  if(std::cmp_greater(__y, __y_max))
2078  return false;
2079 
2080  if(__x <= 1)
2081  return true;
2082 
2083  auto __max_delta = __y_max - static_cast<_IndexType>(__y);
2084  auto __y_mod_x = __y % __x;
2085  auto __delta = (__y_mod_x == 0) ? size_t(0) : (__x - __y_mod_x);
2086  return std::cmp_less_equal(__delta, __max_delta);
2087  }
2088 
2089  template<typename _Extents, size_t _PaddingValue, typename _LayoutTraits,
2090  size_t _Rank = _Extents::rank()>
2091  concept __valid_static_stride = (_Extents::rank() <= 1)
2092  || (_PaddingValue == dynamic_extent)
2093  || (_Extents::static_extent(_LayoutTraits::_S_ext_idx) == dynamic_extent)
2094  || (__is_representable_least_multiple<size_t>(
2095  _PaddingValue, _Extents::static_extent(_LayoutTraits::_S_ext_idx)));
2096 
2097  template<size_t _PaddedStride, typename _Extents,
2098  typename _LayoutTraits>
2099  consteval bool
2100  __is_representable_padded_size()
2101  {
2102  using _IndexType = typename _Extents::index_type;
2103  auto __sta_exts = __static_extents<_Extents>(
2104  _LayoutTraits::_S_unpad_begin, _LayoutTraits::_S_unpad_end);
2105  size_t __max = __gnu_cxx::__int_traits<_IndexType>::__max;
2106  return __static_quotient(__sta_exts, __max / _PaddedStride) != 0;
2107  }
2108 
2109  template<typename _Extents, size_t _PaddedStride, typename _LayoutTraits,
2110  size_t _Rank = _Extents::rank()>
2111  concept __valid_padded_size = (_Rank <= 1)
2112  || (_PaddedStride == dynamic_extent)
2113  || (!__all_static(__static_extents<_Extents>()))
2114  || (__contains_zero(__static_extents<_Extents>()))
2115  || (__is_representable_padded_size<_PaddedStride, _Extents,
2116  _LayoutTraits>());
2117 
2118  template<typename _Extents, typename _Stride, typename... _Indices>
2119  constexpr typename _Extents::index_type
2120  __linear_index_leftpad(const _Extents& __exts, _Stride __stride,
2121  _Indices... __indices)
2122  {
2123  // i0 + stride*(i1 + extents.extent(1)*...)
2124  using _IndexType = typename _Extents::index_type;
2125  _IndexType __res = 0;
2126  if constexpr (sizeof...(__indices) > 0)
2127  {
2128  _IndexType __mult = 1;
2129 
2130  auto __update_rest = [&, __pos = 1u](_IndexType __idx) mutable
2131  {
2132  __res += __idx * __mult;
2133  __mult *= __exts.extent(__pos);
2134  ++__pos;
2135  };
2136 
2137  auto __update = [&](_IndexType __idx, auto... __rest)
2138  {
2139  __res += __idx;
2140  __mult = __stride.extent(0);
2141  (__update_rest(__rest), ...);
2142  };
2143  __update(__indices...);
2144  }
2145  return __res;
2146  }
2147 
2148  template<typename _Extents, typename _Stride, typename... _Indices>
2149  constexpr typename _Extents::index_type
2150  __linear_index_rightpad(const _Extents& __exts, _Stride __stride,
2151  _Indices... __indices)
2152  {
2153  // i[n-1] + stride*(i[n-2] + extents.extent(n-2])*...)
2154  using _IndexType = typename _Extents::index_type;
2155  _IndexType __res = 0;
2156  if constexpr (sizeof...(__indices) > 0)
2157  {
2158  _IndexType __mult = 1;
2159  array<_IndexType, sizeof...(__indices)> __ind_arr{__indices...};
2160 
2161  auto __update_rest = [&, __pos = __exts.rank()-1](_IndexType) mutable
2162  {
2163  --__pos;
2164  __res += __ind_arr[__pos] * __mult;
2165  __mult *= __exts.extent(__pos);
2166  };
2167 
2168  auto __update = [&](_IndexType, auto... __rest)
2169  {
2170  __res += __ind_arr[__exts.rank() - 1];
2171  __mult = __stride.extent(0);
2172  (__update_rest(__rest), ...);
2173  };
2174  __update(__indices...);
2175  }
2176  return __res;
2177  }
2178 
2179  template<size_t _Rank>
2180  struct _LeftPaddedLayoutTraits
2181  {
2182  using _LayoutSame = layout_left;
2183  using _LayoutOther = layout_right;
2184 
2185  constexpr static const size_t _S_ext_idx = 0;
2186  constexpr static const size_t _S_stride_idx = 1;
2187  constexpr static const size_t _S_unpad_begin = 1;
2188  constexpr static const size_t _S_unpad_end = _Rank;
2189 
2190  template<typename _IndexType, size_t _StaticStride, size_t..._Extents>
2191  constexpr static auto
2192  _S_make_padded_extent(
2193  extents<_IndexType, _StaticStride> __stride,
2194  const extents<_IndexType, _Extents...>& __exts)
2195  {
2196  auto __impl = [&]<size_t... _Is>(integer_sequence<size_t, _Is...>)
2197  {
2198  return extents<_IndexType, _StaticStride,
2199  (_Extents...[_Is + 1])...>{
2200  __stride.extent(0), __exts.extent(_Is + 1)...};
2201  };
2202  return __impl(make_index_sequence<sizeof...(_Extents) - 1>());
2203  }
2204  };
2205 
2206  template<size_t _Rank>
2207  struct _RightPaddedLayoutTraits
2208  {
2209  using _LayoutSame = layout_right;
2210  using _LayoutOther = layout_left;
2211 
2212  constexpr static size_t _S_ext_idx = _Rank - 1;
2213  constexpr static size_t _S_stride_idx = _Rank - 2;
2214  constexpr static size_t _S_unpad_begin = 0;
2215  constexpr static size_t _S_unpad_end = _Rank - 1;
2216 
2217  template<typename _IndexType, size_t _StaticStride, size_t..._Extents>
2218  constexpr static auto
2219  _S_make_padded_extent(
2220  extents<_IndexType, _StaticStride> __stride,
2221  const extents<_IndexType, _Extents...>& __exts)
2222  {
2223  auto __impl = [&]<size_t... _Is>(integer_sequence<size_t, _Is...>)
2224  {
2225  return extents<_IndexType, (_Extents...[_Is])..., _StaticStride>{
2226  __exts.extent(_Is)..., __stride.extent(0)};
2227  };
2228  return __impl(make_index_sequence<sizeof...(_Extents) - 1>());
2229  }
2230  };
2231 
2232  template<size_t _PaddingValue, typename _Extents, typename _LayoutTraits>
2233  class _PaddedStorage
2234  {
2235  using _LayoutSame = typename _LayoutTraits::_LayoutSame;
2236 
2237  public:
2238  using _IndexType = typename _Extents::index_type;
2239  constexpr static size_t _S_rank = _Extents::rank();
2240 
2241  // _GLIBCXX_RESOLVE_LIB_DEFECTS
2242  // 4372. Weaken Mandates: for dynamic padding values in padded layouts
2243  static_assert((_PaddingValue == dynamic_extent)
2244  || (cmp_less_equal(_PaddingValue,
2245  __gnu_cxx::__int_traits<_IndexType>::__max)),
2246  "padding_value must be representable as index_type");
2247 
2248  static_assert(__representable_size<_Extents, _IndexType>,
2249  "The size of extents_type must be representable as index_type");
2250 
2251  static_assert(__valid_static_stride<_Extents, _PaddingValue,
2252  _LayoutTraits>,
2253  "The padded stride must be representable as size_t");
2254 
2255  static constexpr size_t _S_static_stride = [] consteval
2256  {
2257  constexpr size_t __rank = _Extents::rank();
2258  if constexpr (__rank <= 1)
2259  return 0;
2260  else
2261  {
2262  constexpr size_t __ext_idx = _LayoutTraits::_S_ext_idx;
2263  constexpr size_t __sta_ext = _Extents::static_extent(__ext_idx);
2264  if constexpr (__sta_ext == 0)
2265  return size_t(0);
2266  else if constexpr (_PaddingValue == dynamic_extent
2267  || __sta_ext == dynamic_extent)
2268  return dynamic_extent;
2269  else
2270  return __least_multiple(_PaddingValue, __sta_ext);
2271  }
2272  }();
2273 
2274  static_assert(_S_static_stride == dynamic_extent
2275  || cmp_less_equal(_S_static_stride,
2276  __gnu_cxx::__int_traits<_IndexType>::__max),
2277  "Padded stride must be representable as index_type");
2278 
2279  static_assert(__valid_padded_size<_Extents, _S_static_stride,
2280  _LayoutTraits>);
2281 
2282  constexpr
2283  _PaddedStorage() noexcept
2284  {
2285  if constexpr (_S_rank > 1)
2286  if constexpr (_S_static_stride == dynamic_extent
2287  && _S_static_padextent() != dynamic_extent)
2288  _M_stride = _Stride{_S_static_padextent()};
2289  }
2290 
2291  constexpr explicit
2292  _PaddedStorage(const _Extents& __exts)
2293  : _M_extents(__exts)
2294  {
2295  if constexpr (!__all_static(__static_extents<_Extents>()))
2296  __glibcxx_assert(__is_representable_extents(_M_extents));
2297 
2298  if constexpr (_S_rank > 1)
2299  {
2300  _IndexType __stride;
2301  if constexpr (_PaddingValue == dynamic_extent)
2302  __stride = _M_padextent();
2303  else if constexpr (_S_static_padextent() != dynamic_extent)
2304  return;
2305  else
2306  {
2307  __glibcxx_assert(
2308  __is_representable_least_multiple<_IndexType>(
2309  _PaddingValue, _M_padextent()));
2310 
2311  __stride = static_cast<_IndexType>(
2312  __least_multiple(_PaddingValue, _M_padextent()));
2313 
2314  __glibcxx_assert(__is_representable_extents(
2315  _LayoutTraits::_S_make_padded_extent(
2316  std::dextents<_IndexType, 1>{__stride},
2317  _M_extents)));
2318  }
2319  _M_stride = _Stride{__stride};
2320  }
2321  }
2322 
2323  constexpr explicit
2324  _PaddedStorage(const _Extents& __exts, _IndexType __pad)
2325  : _M_extents(__exts)
2326  {
2327  if constexpr (_PaddingValue != dynamic_extent)
2328  __glibcxx_assert(cmp_equal(_PaddingValue, __pad));
2329  if constexpr (_S_rank > 1 && _S_static_stride == dynamic_extent)
2330  {
2331  __glibcxx_assert(
2332  __is_representable_least_multiple<_IndexType>(
2333  __pad, _M_padextent()));
2334 
2335  _M_stride = _Stride{static_cast<_IndexType>(
2336  __least_multiple(__pad, _M_padextent()))};
2337 
2338  __glibcxx_assert(__is_representable_extents(
2339  _LayoutTraits::_S_make_padded_extent(
2340  _M_stride, _M_extents)));
2341  }
2342  }
2343 
2344  template<typename _OExtents>
2345  constexpr explicit
2346  _PaddedStorage(
2347  const typename _LayoutSame::template mapping<_OExtents>& __other)
2348  : _PaddedStorage(_Extents(__other.extents()))
2349  {
2350  constexpr size_t __stride_idx = _LayoutTraits::_S_stride_idx;
2351  constexpr size_t __ext_idx = _LayoutTraits::_S_ext_idx;
2352  if constexpr (_S_rank > 1 && _PaddingValue != dynamic_extent)
2353  {
2354  static_assert(_S_static_stride == dynamic_extent
2355  || _OExtents::static_extent(__ext_idx) == dynamic_extent
2356  || _S_static_stride == _OExtents::static_extent(__ext_idx),
2357  "The padded stride must be compatible with other");
2358 
2359  if constexpr (_S_static_stride == dynamic_extent
2360  || _OExtents::static_extent(__stride_idx) == dynamic_extent)
2361  __glibcxx_assert(std::cmp_equal(_M_padstride(),
2362  _M_padextent()));
2363  }
2364  }
2365 
2366  template<typename _OExtents>
2367  constexpr explicit
2368  _PaddedStorage(const typename layout_stride::mapping<_OExtents>&
2369  __other)
2370  : _M_extents(__other.extents())
2371  {
2372  __glibcxx_assert(cmp_less_equal(__other.required_span_size(),
2373  __gnu_cxx::__int_traits<_IndexType>
2374  ::__max));
2375 
2376  constexpr size_t __stride_idx = _LayoutTraits::_S_stride_idx;
2377  if constexpr (_S_rank > 1)
2378  {
2379  if constexpr (_PaddingValue != dynamic_extent)
2380  __glibcxx_assert(cmp_equal(__other.stride(__stride_idx),
2381  _M_calc_padstride())
2382  && "The padded stride must be compatible with other");
2383  if constexpr (_S_static_stride == dynamic_extent)
2384  _M_stride = _Stride{__other.stride(__stride_idx)};
2385  }
2386  }
2387 
2388  template<typename _SamePaddedMapping>
2389  constexpr explicit
2390  _PaddedStorage(_LayoutTraits::_LayoutSame,
2391  const _SamePaddedMapping& __other)
2392  : _M_extents(__other.extents())
2393  {
2394  if constexpr (_S_rank > 1)
2395  {
2396  static_assert(_PaddingValue == dynamic_extent
2397  || _SamePaddedMapping::padding_value == dynamic_extent
2398  || _PaddingValue == _SamePaddedMapping::padding_value,
2399  "If neither PaddingValue is dynamic_extent, then they must "
2400  "be equal");
2401 
2402  constexpr size_t __stride_idx = _LayoutTraits::_S_stride_idx;
2403  if constexpr (_PaddingValue != dynamic_extent)
2404  __glibcxx_assert(cmp_equal(__other.stride(__stride_idx),
2405  _M_calc_padstride())
2406  && "The padded stride must be compatible with other");
2407  if constexpr (_S_static_stride == dynamic_extent)
2408  _M_stride = _Stride{__other.stride(__stride_idx)};
2409  }
2410  __glibcxx_assert(cmp_less_equal(__other.required_span_size(),
2411  __gnu_cxx::__int_traits<_IndexType>::__max));
2412  }
2413 
2414  template<typename _OtherPaddedMapping>
2415  constexpr explicit
2416  _PaddedStorage(_LayoutTraits::_LayoutOther,
2417  const _OtherPaddedMapping& __other) noexcept
2418  : _M_extents(__other.extents())
2419  {
2420  __glibcxx_assert(cmp_less_equal(__other.required_span_size(),
2421  __gnu_cxx::__int_traits<_IndexType>::__max));
2422  }
2423 
2424  static constexpr bool
2425  _M_is_always_exhaustive() noexcept
2426  {
2427  if constexpr (_S_rank <= 1)
2428  return true;
2429  else
2430  return _S_static_padextent() != dynamic_extent
2431  && _S_static_stride != dynamic_extent
2432  && _S_static_padextent() == _S_static_stride;
2433  }
2434 
2435  constexpr bool
2436  _M_is_exhaustive() const noexcept
2437  {
2438  if constexpr (_M_is_always_exhaustive())
2439  return true;
2440  else
2441  return cmp_equal(_M_padextent(), _M_padstride());
2442  }
2443 
2444  constexpr static size_t
2445  _S_static_padextent() noexcept
2446  { return _Extents::static_extent(_LayoutTraits::_S_ext_idx); }
2447 
2448  constexpr _IndexType
2449  _M_padextent() const noexcept
2450  { return _M_extents.extent(_LayoutTraits::_S_ext_idx); }
2451 
2452  constexpr _IndexType
2453  _M_calc_padstride() const noexcept
2454  {
2455  if constexpr (_S_static_stride != dynamic_extent)
2456  return _S_static_stride;
2457  else if constexpr (_PaddingValue != dynamic_extent)
2458  return __least_multiple(_PaddingValue, _M_padextent());
2459  else
2460  return _M_padextent();
2461  }
2462 
2463  constexpr _IndexType
2464  _M_padstride() const noexcept
2465  { return _M_stride.extent(0); }
2466 
2467  constexpr _IndexType
2468  _M_required_span_size() const noexcept
2469  {
2470  if constexpr (_S_rank == 0)
2471  return 1;
2472  else if (__mdspan::__empty(_M_extents))
2473  return 0;
2474  else
2475  {
2476  size_t __stride = static_cast<size_t>(_M_padstride());
2477  size_t __prod_rest = __mdspan::__fwd_prod(_M_extents,
2478  _LayoutTraits::_S_unpad_begin, _LayoutTraits::_S_unpad_end);
2479  size_t __delta = _M_padstride() - _M_padextent();
2480  return static_cast<_IndexType>(__stride * __prod_rest - __delta);
2481  }
2482  }
2483 
2484  template<typename _SamePaddedMapping>
2485  constexpr bool
2486  _M_equal(const _SamePaddedMapping& __other) const noexcept
2487  {
2488  return _M_extents == __other.extents()
2489  && (_S_rank < 2
2490  || cmp_equal(_M_stride.extent(0),
2491  __other.stride(_LayoutTraits::_S_stride_idx)));
2492  }
2493 
2494  using _Stride = std::extents<_IndexType, _S_static_stride>;
2495  [[no_unique_address]] _Stride _M_stride;
2496  [[no_unique_address]] _Extents _M_extents;
2497  };
2498  }
2499 
2500  template<size_t _PaddingValue>
2501  template<typename _Extents>
2502  class layout_left_padded<_PaddingValue>::mapping
2503  {
2504  public:
2505  static constexpr size_t padding_value = _PaddingValue;
2506 
2507  using extents_type = _Extents;
2508  using index_type = typename extents_type::index_type;
2509  using size_type = typename extents_type::size_type;
2510  using rank_type = typename extents_type::rank_type;
2511  using layout_type = layout_left_padded<padding_value>;
2512 
2513  private:
2514  static constexpr size_t _S_rank = extents_type::rank();
2515  using _PaddedStorage = __mdspan::_PaddedStorage<_PaddingValue,
2516  _Extents, __mdspan::_LeftPaddedLayoutTraits<_S_rank>>;
2517  [[no_unique_address]] _PaddedStorage _M_storage;
2518 
2519  consteval friend size_t
2520  __mdspan::__get_static_stride<mapping>();
2521 
2522  constexpr index_type
2523  _M_extent(size_t __r) const noexcept
2524  { return _M_storage._M_extents.extent(__r); }
2525 
2526  constexpr index_type
2527  _M_padstride() const noexcept
2528  { return _M_storage._M_stride.extent(0); }
2529 
2530  public:
2531  constexpr
2532  mapping() noexcept
2533  { }
2534 
2535  constexpr
2536  mapping(const mapping&) noexcept = default;
2537 
2538  constexpr
2539  mapping(const extents_type& __exts)
2540  : _M_storage(__exts)
2541  { }
2542 
2543  template<__mdspan::__valid_index_type<index_type> _OIndexType>
2544  constexpr
2545  mapping(const extents_type& __exts, _OIndexType __pad)
2546  : _M_storage(__exts,
2547  __mdspan::__index_type_cast<index_type>(std::move(__pad)))
2548  { }
2549 
2550  template<typename _OExtents>
2551  requires is_constructible_v<extents_type, _OExtents>
2552  constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
2553  mapping(const layout_left::mapping<_OExtents>& __other)
2554  : _M_storage(__other)
2555  { }
2556 
2557  template<typename _OExtents>
2558  requires is_constructible_v<_OExtents, extents_type>
2559  constexpr explicit(!(_OExtents::rank() == 0
2560  && is_convertible_v<_OExtents, extents_type>))
2561  mapping(const typename layout_stride::mapping<_OExtents>& __other)
2562  : _M_storage(__other)
2563  { __glibcxx_assert(*this == __other); }
2564 
2565  template<typename _LeftPaddedMapping>
2566  requires __mdspan::__is_left_padded_mapping<_LeftPaddedMapping>
2567  && is_constructible_v<extents_type,
2568  typename _LeftPaddedMapping::extents_type>
2569  constexpr explicit(
2570  !is_convertible_v<typename _LeftPaddedMapping::extents_type,
2571  extents_type>
2572  || _S_rank > 1 && (padding_value != dynamic_extent
2573  || _LeftPaddedMapping::padding_value == dynamic_extent))
2574  mapping(const _LeftPaddedMapping& __other)
2575  : _M_storage(layout_left{}, __other)
2576  { }
2577 
2578  template<typename _RightPaddedMapping>
2579  requires (__mdspan::__is_right_padded_mapping<_RightPaddedMapping>
2580  || __mdspan::__mapping_of<layout_right, _RightPaddedMapping>)
2581  && (_S_rank <= 1)
2582  && is_constructible_v<extents_type,
2583  typename _RightPaddedMapping::extents_type>
2584  constexpr explicit(!is_convertible_v<
2585  typename _RightPaddedMapping::extents_type, extents_type>)
2586  mapping(const _RightPaddedMapping& __other) noexcept
2587  : _M_storage(layout_right{}, __other)
2588  { }
2589 
2590  constexpr mapping&
2591  operator=(const mapping&) noexcept = default;
2592 
2593  constexpr const extents_type&
2594  extents() const noexcept { return _M_storage._M_extents; }
2595 
2596  constexpr array<index_type, _S_rank>
2597  strides() const noexcept
2598  {
2599  array<index_type, _S_rank> __ret;
2600  if constexpr (_S_rank > 0)
2601  __ret[0] = 1;
2602  if constexpr (_S_rank > 1)
2603  __ret[1] = _M_padstride();
2604  if constexpr (_S_rank > 2)
2605  for(size_t __i = 2; __i < _S_rank; ++__i)
2606  __ret[__i] = __ret[__i - 1] * _M_extent(__i - 1);
2607  return __ret;
2608  }
2609 
2610  constexpr index_type
2611  required_span_size() const noexcept
2612  { return _M_storage._M_required_span_size(); }
2613 
2614  // _GLIBCXX_RESOLVE_LIB_DEFECTS
2615  // 4314. Missing move in mdspan layout mapping::operator()
2616  template<__mdspan::__valid_index_type<index_type>... _Indices>
2617  requires (sizeof...(_Indices) == _S_rank)
2618  constexpr index_type
2619  operator()(_Indices... __indices) const noexcept
2620  {
2621  return __mdspan::__linear_index_leftpad(
2622  extents(), _M_storage._M_stride,
2623  static_cast<index_type>(std::move(__indices))...);
2624  }
2625 
2626  static constexpr bool
2627  is_always_exhaustive() noexcept
2628  { return _PaddedStorage::_M_is_always_exhaustive(); }
2629 
2630  constexpr bool
2631  is_exhaustive() const noexcept
2632  { return _M_storage._M_is_exhaustive(); }
2633 
2634  static constexpr bool
2635  is_always_unique() noexcept { return true; }
2636 
2637  static constexpr bool
2638  is_unique() noexcept { return true; }
2639 
2640  static constexpr bool
2641  is_always_strided() noexcept { return true; }
2642 
2643  static constexpr bool
2644  is_strided() noexcept { return true; }
2645 
2646  constexpr index_type
2647  stride(rank_type __r) const noexcept
2648  {
2649  __glibcxx_assert(__r < _S_rank);
2650  if (__r == 0)
2651  return 1;
2652  else
2653  return static_cast<index_type>(
2654  static_cast<size_t>(_M_padstride()) *
2655  static_cast<size_t>(__mdspan::__fwd_prod(extents(), 1, __r)));
2656  }
2657 
2658  template<typename _LeftpadMapping>
2659  requires(__mdspan::__is_left_padded_mapping<_LeftpadMapping>
2660  && _LeftpadMapping::extents_type::rank() == _S_rank)
2661  friend constexpr bool
2662  operator==(const mapping& __self, const _LeftpadMapping& __other)
2663  noexcept
2664  { return __self._M_storage._M_equal(__other); }
2665 
2666  private:
2667 #if __glibcxx_submdspan
2668  template<typename... _Slices>
2669  requires (extents_type::rank() == sizeof...(_Slices))
2670  friend constexpr auto
2671  submdspan_mapping(const mapping& __mapping, _Slices... __slices)
2672  { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
2673 #endif // __glibcxx_submdspan
2674  };
2675 
2676  template<size_t _PaddingValue>
2677  template<typename _Extents>
2678  class layout_right_padded<_PaddingValue>::mapping {
2679  public:
2680  static constexpr size_t padding_value = _PaddingValue;
2681  using extents_type = _Extents;
2682  using index_type = typename extents_type::index_type;
2683  using size_type = typename extents_type::size_type;
2684  using rank_type = typename extents_type::rank_type;
2685  using layout_type = layout_right_padded<_PaddingValue>;
2686 
2687  private:
2688  static constexpr size_t _S_rank = extents_type::rank();
2689  using _PaddedStorage = __mdspan::_PaddedStorage<_PaddingValue,
2690  _Extents, __mdspan::_RightPaddedLayoutTraits<_S_rank>>;
2691  [[no_unique_address]] _PaddedStorage _M_storage;
2692 
2693  consteval friend size_t
2694  __mdspan::__get_static_stride<mapping>();
2695 
2696  constexpr index_type
2697  _M_extent(size_t __r) const noexcept
2698  { return _M_storage._M_extents.extent(__r); }
2699 
2700  constexpr index_type
2701  _M_padstride() const noexcept
2702  { return _M_storage._M_stride.extent(0); }
2703 
2704  public:
2705  constexpr
2706  mapping() noexcept
2707  { }
2708 
2709  constexpr
2710  mapping(const mapping&) noexcept = default;
2711 
2712  constexpr
2713  mapping(const extents_type& __exts)
2714  : _M_storage(__exts)
2715  { }
2716 
2717  template<__mdspan::__valid_index_type<index_type> _OIndexType>
2718  constexpr
2719  mapping(const extents_type& __exts, _OIndexType __pad)
2720  : _M_storage(__exts,
2721  __mdspan::__index_type_cast<index_type>(std::move(__pad)))
2722  { }
2723 
2724  template<typename _OExtents>
2725  requires is_constructible_v<extents_type, _OExtents>
2726  constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
2727  mapping(const layout_right::mapping<_OExtents>& __other)
2728  : _M_storage(__other)
2729  { }
2730 
2731  template<typename _OExtents>
2732  requires is_constructible_v<_OExtents, extents_type>
2733  constexpr explicit(!(_OExtents::rank() == 0
2734  && is_convertible_v<_OExtents, extents_type>))
2735  mapping(const typename layout_stride::mapping<_OExtents>& __other)
2736  : _M_storage(__other)
2737  { __glibcxx_assert(*this == __other); }
2738 
2739  template<typename _RightPaddedMapping>
2740  requires __mdspan::__is_right_padded_mapping<_RightPaddedMapping>
2741  && is_constructible_v<extents_type,
2742  typename _RightPaddedMapping::extents_type>
2743  constexpr explicit(
2744  !is_convertible_v<typename _RightPaddedMapping::extents_type,
2745  extents_type>
2746  || _S_rank > 1 && (padding_value != dynamic_extent
2747  || _RightPaddedMapping::padding_value == dynamic_extent))
2748  mapping(const _RightPaddedMapping& __other)
2749  : _M_storage(layout_right{}, __other)
2750  { }
2751 
2752  template<typename _LeftPaddedMapping>
2753  requires (__mdspan::__is_left_padded_mapping<_LeftPaddedMapping>
2754  || __mdspan::__mapping_of<layout_left, _LeftPaddedMapping>)
2755  && (_S_rank <= 1)
2756  && is_constructible_v<extents_type,
2757  typename _LeftPaddedMapping::extents_type>
2758  constexpr explicit(!is_convertible_v<
2759  typename _LeftPaddedMapping::extents_type, extents_type>)
2760  mapping(const _LeftPaddedMapping& __other) noexcept
2761  : _M_storage(layout_left{}, __other)
2762  { }
2763 
2764  constexpr mapping& operator=(const mapping&) noexcept = default;
2765 
2766  constexpr const extents_type&
2767  extents() const noexcept { return _M_storage._M_extents; }
2768 
2769  constexpr array<index_type, _S_rank>
2770  strides() const noexcept
2771  {
2772  array<index_type, _S_rank> __ret;
2773  if constexpr (_S_rank > 0)
2774  __ret[_S_rank - 1] = 1;
2775  if constexpr (_S_rank > 1)
2776  __ret[_S_rank - 2] = _M_padstride();
2777  if constexpr (_S_rank > 2)
2778  for(size_t __i = _S_rank - 2; __i > 0; --__i)
2779  __ret[__i - 1] = __ret[__i] * _M_extent(__i);
2780  return __ret;
2781  }
2782 
2783  constexpr index_type
2784  required_span_size() const noexcept
2785  { return _M_storage._M_required_span_size(); }
2786 
2787  // _GLIBCXX_RESOLVE_LIB_DEFECTS
2788  // 4314. Missing move in mdspan layout mapping::operator()
2789  template<__mdspan::__valid_index_type<index_type>... _Indices>
2790  requires (sizeof...(_Indices) == _S_rank)
2791  constexpr index_type
2792  operator()(_Indices... __indices) const noexcept
2793  {
2794  return __mdspan::__linear_index_rightpad(
2795  extents(), _M_storage._M_stride,
2796  static_cast<index_type>(std::move(__indices))...);
2797  }
2798 
2799  static constexpr bool
2800  is_always_exhaustive() noexcept
2801  { return _PaddedStorage::_M_is_always_exhaustive(); }
2802 
2803  constexpr bool
2804  is_exhaustive() const noexcept
2805  { return _M_storage._M_is_exhaustive(); }
2806 
2807  static constexpr bool
2808  is_always_unique() noexcept { return true; }
2809 
2810  static constexpr bool
2811  is_unique() noexcept { return true; }
2812 
2813  static constexpr bool
2814  is_always_strided() noexcept { return true; }
2815 
2816  static constexpr bool
2817  is_strided() noexcept { return true; }
2818 
2819  constexpr index_type
2820  stride(rank_type __r) const noexcept
2821  {
2822  __glibcxx_assert(__r < _S_rank);
2823  if constexpr (_S_rank <= 1)
2824  return 1;
2825  else if (__r == _S_rank - 1)
2826  return 1;
2827  else if (__r == _S_rank - 2)
2828  return _M_padstride();
2829  else
2830  return static_cast<index_type>(
2831  static_cast<size_t>(_M_padstride()) *
2832  static_cast<size_t>(__mdspan::__fwd_prod(
2833  extents(), __r + 1, _S_rank - 1)));
2834  }
2835 
2836  template<typename _RightPaddedMapping>
2837  requires(__mdspan::__is_right_padded_mapping<_RightPaddedMapping>
2838  && _RightPaddedMapping::extents_type::rank() == _S_rank)
2839  friend constexpr bool
2840  operator==(const mapping& __self, const _RightPaddedMapping& __other)
2841  noexcept
2842  { return __self._M_storage._M_equal(__other); }
2843 
2844 #if __glibcxx_submdspan
2845  private:
2846  template<typename... _Slices>
2847  requires (extents_type::rank() == sizeof...(_Slices))
2848  friend constexpr auto
2849  submdspan_mapping(const mapping& __mapping, _Slices... __slices)
2850  { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
2851 #endif // __glibcxx_submdspan
2852  };
2853 #endif // __glibcxx_padded_layouts
2854 
2855  template<typename _ElementType>
2856  struct default_accessor
2857  {
2858  static_assert(!is_array_v<_ElementType>,
2859  "ElementType must not be an array type");
2860  static_assert(!is_abstract_v<_ElementType>,
2861  "ElementType must not be an abstract class type");
2862 
2863  using offset_policy = default_accessor;
2864  using element_type = _ElementType;
2865  using reference = element_type&;
2866  using data_handle_type = element_type*;
2867 
2868  constexpr
2869  default_accessor() noexcept = default;
2870 
2871  template<typename _OElementType>
2872  requires is_convertible_v<_OElementType(*)[], element_type(*)[]>
2873  constexpr
2874  default_accessor(default_accessor<_OElementType>) noexcept
2875  { }
2876 
2877  constexpr reference
2878  access(data_handle_type __p, size_t __i) const noexcept
2879  { return __p[__i]; }
2880 
2881  constexpr data_handle_type
2882  offset(data_handle_type __p, size_t __i) const noexcept
2883  { return __p + __i; }
2884  };
2885 
2886 #ifdef __glibcxx_aligned_accessor
2887  template<typename _ElementType, size_t _ByteAlignment>
2888  struct aligned_accessor
2889  {
2890  static_assert(has_single_bit(_ByteAlignment),
2891  "ByteAlignment must be a power of two");
2892  static_assert(_ByteAlignment >= alignof(_ElementType));
2893 
2894  using offset_policy = default_accessor<_ElementType>;
2895  using element_type = _ElementType;
2896  using reference = element_type&;
2897  using data_handle_type = element_type*;
2898 
2899  static constexpr size_t byte_alignment = _ByteAlignment;
2900 
2901  constexpr
2902  aligned_accessor() noexcept = default;
2903 
2904  template<typename _OElementType, size_t _OByteAlignment>
2905  requires (_OByteAlignment >= byte_alignment)
2906  && is_convertible_v<_OElementType(*)[], element_type(*)[]>
2907  constexpr
2908  aligned_accessor(aligned_accessor<_OElementType, _OByteAlignment>)
2909  noexcept
2910  { }
2911 
2912  template<typename _OElementType>
2913  requires is_convertible_v<_OElementType(*)[], element_type(*)[]>
2914  constexpr explicit
2915  aligned_accessor(default_accessor<_OElementType>) noexcept
2916  { }
2917 
2918  template<typename _OElementType>
2919  requires is_convertible_v<element_type(*)[], _OElementType(*)[]>
2920  constexpr
2921  operator default_accessor<_OElementType>() const noexcept
2922  { return {}; }
2923 
2924  constexpr reference
2925  access(data_handle_type __p, size_t __i) const noexcept
2926  { return std::assume_aligned<byte_alignment>(__p)[__i]; }
2927 
2928  constexpr typename offset_policy::data_handle_type
2929  offset(data_handle_type __p, size_t __i) const noexcept
2930  { return std::assume_aligned<byte_alignment>(__p) + __i; }
2931  };
2932 #endif
2933 
2934  template<typename _ElementType, typename _Extents,
2935  typename _LayoutPolicy = layout_right,
2936  typename _AccessorPolicy = default_accessor<_ElementType>>
2937  class mdspan
2938  {
2939  static_assert(!is_array_v<_ElementType>,
2940  "ElementType must not be an array type");
2941  static_assert(!is_abstract_v<_ElementType>,
2942  "ElementType must not be an abstract class type");
2943  static_assert(__mdspan::__is_extents<_Extents>,
2944  "Extents must be a specialization of std::extents");
2945  static_assert(is_same_v<_ElementType,
2946  typename _AccessorPolicy::element_type>);
2947 
2948  public:
2949  using extents_type = _Extents;
2950  using layout_type = _LayoutPolicy;
2951  using accessor_type = _AccessorPolicy;
2952  using mapping_type = typename layout_type::template mapping<extents_type>;
2953  using element_type = _ElementType;
2954  using value_type = remove_cv_t<element_type>;
2955  using index_type = typename extents_type::index_type;
2956  using size_type = typename extents_type::size_type;
2957  using rank_type = typename extents_type::rank_type;
2958  using data_handle_type = typename accessor_type::data_handle_type;
2959  using reference = typename accessor_type::reference;
2960 
2961  static constexpr rank_type
2962  rank() noexcept { return extents_type::rank(); }
2963 
2964  static constexpr rank_type
2965  rank_dynamic() noexcept { return extents_type::rank_dynamic(); }
2966 
2967  static constexpr size_t
2968  static_extent(rank_type __r) noexcept
2969  { return extents_type::static_extent(__r); }
2970 
2971  constexpr index_type
2972  extent(rank_type __r) const noexcept { return extents().extent(__r); }
2973 
2974  constexpr
2975  mdspan()
2976  requires (rank_dynamic() > 0)
2977  && is_default_constructible_v<data_handle_type>
2978  && is_default_constructible_v<mapping_type>
2979  && is_default_constructible_v<accessor_type> = default;
2980 
2981  constexpr
2982  mdspan(const mdspan& __other) = default;
2983 
2984  constexpr
2985  mdspan(mdspan&& __other) = default;
2986 
2987  template<__mdspan::__valid_index_type<index_type>... _OIndexTypes>
2988  requires (sizeof...(_OIndexTypes) == rank()
2989  || sizeof...(_OIndexTypes) == rank_dynamic())
2990  && is_constructible_v<mapping_type, extents_type>
2991  && is_default_constructible_v<accessor_type>
2992  constexpr explicit
2993  mdspan(data_handle_type __handle, _OIndexTypes... __exts)
2994  : _M_accessor(),
2995  _M_mapping(_Extents(static_cast<index_type>(std::move(__exts))...)),
2996  _M_handle(std::move(__handle))
2997  { }
2998 
2999  template<typename _OIndexType, size_t _Nm>
3000  requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3001  && (_Nm == rank() || _Nm == rank_dynamic())
3002  && is_constructible_v<mapping_type, extents_type>
3003  && is_default_constructible_v<accessor_type>
3004  constexpr explicit(_Nm != rank_dynamic())
3005  mdspan(data_handle_type __handle, span<_OIndexType, _Nm> __exts)
3006  : _M_accessor(), _M_mapping(extents_type(__exts)),
3007  _M_handle(std::move(__handle))
3008  { }
3009 
3010  template<typename _OIndexType, size_t _Nm>
3011  requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3012  && (_Nm == rank() || _Nm == rank_dynamic())
3013  && is_constructible_v<mapping_type, extents_type>
3014  && is_default_constructible_v<accessor_type>
3015  constexpr explicit(_Nm != rank_dynamic())
3016  mdspan(data_handle_type __handle, const array<_OIndexType, _Nm>& __exts)
3017  : _M_accessor(), _M_mapping(extents_type(__exts)),
3018  _M_handle(std::move(__handle))
3019  { }
3020 
3021  constexpr
3022  mdspan(data_handle_type __handle, const extents_type& __exts)
3023  requires is_constructible_v<mapping_type, const extents_type&>
3024  && is_default_constructible_v<accessor_type>
3025  : _M_accessor(), _M_mapping(__exts), _M_handle(std::move(__handle))
3026  { }
3027 
3028  constexpr
3029  mdspan(data_handle_type __handle, const mapping_type& __mapping)
3030  requires is_default_constructible_v<accessor_type>
3031  : _M_accessor(), _M_mapping(__mapping), _M_handle(std::move(__handle))
3032  { }
3033 
3034  constexpr
3035  mdspan(data_handle_type __handle, const mapping_type& __mapping,
3036  const accessor_type& __accessor)
3037  : _M_accessor(__accessor), _M_mapping(__mapping),
3038  _M_handle(std::move(__handle))
3039  { }
3040 
3041  template<typename _OElementType, typename _OExtents, typename _OLayout,
3042  typename _OAccessor>
3043  requires is_constructible_v<mapping_type,
3044  const typename _OLayout::template mapping<_OExtents>&>
3045  && is_constructible_v<accessor_type, const _OAccessor&>
3046  constexpr explicit(!is_convertible_v<
3047  const typename _OLayout::template mapping<_OExtents>&, mapping_type>
3048  || !is_convertible_v<const _OAccessor&, accessor_type>)
3049  mdspan(const mdspan<_OElementType, _OExtents, _OLayout, _OAccessor>&
3050  __other)
3051  : _M_accessor(__other.accessor()), _M_mapping(__other.mapping()),
3052  _M_handle(__other.data_handle())
3053  {
3054  static_assert(is_constructible_v<data_handle_type,
3055  const typename _OAccessor::data_handle_type&>);
3056  static_assert(is_constructible_v<extents_type, _OExtents>);
3057  }
3058 
3059  constexpr mdspan&
3060  operator=(const mdspan& __other) = default;
3061 
3062  constexpr mdspan&
3063  operator=(mdspan&& __other) = default;
3064 
3065  template<__mdspan::__valid_index_type<index_type>... _OIndexTypes>
3066  requires (sizeof...(_OIndexTypes) == rank())
3067  constexpr reference
3068  operator[](_OIndexTypes... __indices) const
3069  {
3070  if constexpr (rank() == 0)
3071  return _M_accessor.access(_M_handle, _M_mapping());
3072  else if constexpr (!(is_same_v<_OIndexTypes, index_type> && ...))
3073  return operator[](
3074  __mdspan::__index_type_cast<index_type>(std::move(__indices))...);
3075  else
3076  {
3077  auto __is_multi_index = [&]<size_t... _Counts>(index_sequence<_Counts...>)
3078  { return ((__indices < extents().extent(_Counts)) && ...); };
3079 
3080  __glibcxx_assert(__is_multi_index(make_index_sequence<rank()>()));
3081  return _M_accessor.access(_M_handle, _M_mapping(__indices...));
3082  }
3083  }
3084 
3085  template<typename _OIndexType>
3086  requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3087  constexpr reference
3088  operator[](span<_OIndexType, rank()> __indices) const
3089  {
3090  auto __call = [&]<size_t... _Counts>(index_sequence<_Counts...>)
3091  -> reference
3092  {
3093  return operator[](
3094  __mdspan::__index_type_cast<index_type>(as_const(__indices[_Counts]))...);
3095  };
3096  return __call(make_index_sequence<rank()>());
3097  }
3098 
3099  template<typename _OIndexType>
3100  requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3101  constexpr reference
3102  operator[](const array<_OIndexType, rank()>& __indices) const
3103  { return operator[](span<const _OIndexType, rank()>(__indices)); }
3104 
3105 #if __cplusplus > 202302L
3106  template<__mdspan::__valid_index_type<index_type>... _OIndexTypes>
3107  requires (sizeof...(_OIndexTypes) == rank())
3108  constexpr reference
3109  at(_OIndexTypes... __indices) const
3110  {
3111  if constexpr (rank() == 0)
3112  return _M_accessor.access(_M_handle, _M_mapping());
3113  else if constexpr (!(is_integral_v<_OIndexTypes> && ...))
3114  return at(__index_int_t<_OIndexTypes>(std::move(__indices))...);
3115  else
3116  {
3117  auto __check_bound = [&]<typename _OIntType>(size_t __dim, _OIntType __index)
3118  {
3119  if constexpr (is_signed_v<_OIntType>)
3120  if (__index < 0)
3121  std::__throw_out_of_range_fmt(
3122  __N("mdspan::at: %zuth index is negative"), __dim);
3123 
3124  const auto __ext = extents().extent(__dim);
3125  if (std::cmp_greater_equal(__index, __ext))
3126  std::__throw_out_of_range_fmt(
3127  __N("mdspan::at: %zuth index (which is %zu)"
3128  " >= extent(%zu) (which is %zu)"),
3129  __dim, size_t(__index), __dim, size_t(__ext));
3130  };
3131  auto __check_bounds = [&]<size_t... _Counts>(index_sequence<_Counts...>)
3132  { (__check_bound(_Counts, __indices), ...); };
3133 
3134  __check_bounds(make_index_sequence<rank()>());
3135  auto __index = _M_mapping(static_cast<index_type>(__indices)...);
3136  return _M_accessor.access(_M_handle, __index);
3137  }
3138  }
3139 
3140  template<typename _OIndexType>
3141  requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3142  constexpr reference
3143  at(span<_OIndexType, rank()> __indices) const
3144  {
3145  auto __call = [&]<size_t... _Counts>(index_sequence<_Counts...>)
3146  -> reference
3147  {
3148  return at(
3149  __index_int_t<_OIndexType>(as_const(__indices[_Counts]))...);
3150  };
3151  return __call(make_index_sequence<rank()>());
3152  }
3153 
3154  template<typename _OIndexType>
3155  requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
3156  constexpr reference
3157  at(const array<_OIndexType, rank()>& __indices) const
3158  { return at(span<const _OIndexType, rank()>(__indices)); }
3159 #endif // C++26
3160 
3161  constexpr size_type
3162  size() const noexcept
3163  {
3164  __glibcxx_assert(cmp_less_equal(_M_mapping.required_span_size(),
3165  __gnu_cxx::__int_traits<size_t>
3166  ::__max));
3167  return size_type(__mdspan::__size(extents()));
3168  }
3169 
3170  [[nodiscard]]
3171  constexpr bool
3172  empty() const noexcept
3173  { return __mdspan::__empty(extents()); }
3174 
3175  friend constexpr void
3176  swap(mdspan& __x, mdspan& __y) noexcept
3177  {
3178  using std::swap;
3179  swap(__x._M_mapping, __y._M_mapping);
3180  swap(__x._M_accessor, __y._M_accessor);
3181  swap(__x._M_handle, __y._M_handle);
3182  }
3183 
3184  constexpr const extents_type&
3185  extents() const noexcept { return _M_mapping.extents(); }
3186 
3187  constexpr const data_handle_type&
3188  data_handle() const noexcept { return _M_handle; }
3189 
3190  constexpr const mapping_type&
3191  mapping() const noexcept { return _M_mapping; }
3192 
3193  constexpr const accessor_type&
3194  accessor() const noexcept { return _M_accessor; }
3195 
3196  // Strengthened noexcept for all `is_*` methods.
3197 
3198  static constexpr bool
3199  is_always_unique() noexcept(noexcept(mapping_type::is_always_unique()))
3200  { return mapping_type::is_always_unique(); }
3201 
3202  static constexpr bool
3203  is_always_exhaustive()
3204  noexcept(noexcept(mapping_type::is_always_exhaustive()))
3205  { return mapping_type::is_always_exhaustive(); }
3206 
3207  static constexpr bool
3208  is_always_strided()
3209  noexcept(noexcept(mapping_type::is_always_strided()))
3210  { return mapping_type::is_always_strided(); }
3211 
3212  constexpr bool
3213  is_unique() const noexcept(noexcept(_M_mapping.is_unique()))
3214  { return _M_mapping.is_unique(); }
3215 
3216  constexpr bool
3217  is_exhaustive() const noexcept(noexcept(_M_mapping.is_exhaustive()))
3218  { return _M_mapping.is_exhaustive(); }
3219 
3220  constexpr bool
3221  is_strided() const noexcept(noexcept(_M_mapping.is_strided()))
3222  { return _M_mapping.is_strided(); }
3223 
3224  constexpr index_type
3225  stride(rank_type __r) const { return _M_mapping.stride(__r); }
3226 
3227  private:
3228  template<typename _OIndexType>
3229  using __index_int_t = std::__conditional_t<
3230  is_integral_v<_OIndexType>, _OIndexType, index_type>;
3231 
3232  [[no_unique_address]] accessor_type _M_accessor = accessor_type();
3233  [[no_unique_address]] mapping_type _M_mapping = mapping_type();
3234  [[no_unique_address]] data_handle_type _M_handle = data_handle_type();
3235  };
3236 
3237  template<typename _CArray>
3238  requires is_array_v<_CArray> && (rank_v<_CArray> == 1)
3239  mdspan(_CArray&)
3240  -> mdspan<remove_all_extents_t<_CArray>,
3241  extents<size_t, extent_v<_CArray, 0>>>;
3242 
3243  template<typename _Pointer>
3244  requires is_pointer_v<remove_reference_t<_Pointer>>
3245  mdspan(_Pointer&&)
3246  -> mdspan<remove_pointer_t<remove_reference_t<_Pointer>>, extents<size_t>>;
3247 
3248  template<typename _ElementType, typename... _Integrals>
3249  requires (is_convertible_v<_Integrals, size_t> && ...)
3250  && (sizeof...(_Integrals) > 0)
3251  explicit mdspan(_ElementType*, _Integrals...)
3252  -> mdspan<_ElementType,
3253  extents<size_t, __detail::__maybe_static_ext<_Integrals>...>>;
3254 
3255  template<typename _ElementType, typename _OIndexType, size_t _Nm>
3256  mdspan(_ElementType*, span<_OIndexType, _Nm>)
3257  -> mdspan<_ElementType, dextents<size_t, _Nm>>;
3258 
3259  template<typename _ElementType, typename _OIndexType, size_t _Nm>
3260  mdspan(_ElementType*, const array<_OIndexType, _Nm>&)
3261  -> mdspan<_ElementType, dextents<size_t, _Nm>>;
3262 
3263  template<typename _ElementType, typename _IndexType, size_t... _ExtentsPack>
3264  mdspan(_ElementType*, const extents<_IndexType, _ExtentsPack...>&)
3265  -> mdspan<_ElementType, extents<_IndexType, _ExtentsPack...>>;
3266 
3267  template<typename _ElementType, typename _MappingType>
3268  mdspan(_ElementType*, const _MappingType&)
3269  -> mdspan<_ElementType, typename _MappingType::extents_type,
3270  typename _MappingType::layout_type>;
3271 
3272  // _GLIBCXX_RESOLVE_LIB_DEFECTS
3273  // 4511. Inconsistency between the deduction guide of std::mdspan taking...
3274  template<typename _MappingType, typename _AccessorType>
3275  mdspan(typename _AccessorType::data_handle_type, const _MappingType&,
3276  const _AccessorType&)
3277  -> mdspan<typename _AccessorType::element_type,
3278  typename _MappingType::extents_type,
3279  typename _MappingType::layout_type, _AccessorType>;
3280 
3281 #if __glibcxx_submdspan
3282  namespace __mdspan
3283  {
3284  template<typename _IndexType, typename _Slice>
3285  constexpr auto
3286  __canonical_index(_Slice&& __slice)
3287  {
3288  if constexpr (__detail::__integral_constant_like<_Slice>)
3289  {
3290  static_assert(__is_representable_integer<_IndexType>(_Slice::value));
3291  static_assert(_Slice::value >= 0);
3292  return std::cw<_IndexType(_Slice::value)>;
3293  }
3294  else
3295  return __mdspan::__index_type_cast<_IndexType>(std::move(__slice));
3296  }
3297 
3298  template<typename _IndexType,
3299  typename _OffsetType, typename _SpanType, typename _StrideType>
3300  constexpr auto
3301  __canonical_range_slice(_OffsetType __offset, _SpanType __span,
3302  _StrideType __stride)
3303  {
3304  if constexpr (is_same_v<_SpanType, constant_wrapper<_IndexType(0)>>
3305  || is_same_v<_StrideType, constant_wrapper<_IndexType(1)>>)
3306  return extent_slice{
3307  .offset = __offset,
3308  .extent = __span,
3309  .stride = cw<_IndexType(1)>
3310  };
3311  else if constexpr (__is_constant_wrapper<_StrideType>)
3312  {
3313  static_assert(_StrideType::value > 0);
3314  if constexpr (__is_constant_wrapper<_SpanType>)
3315  return extent_slice{
3316  .offset = __offset,
3317  .extent = cw<_IndexType(1 + (_SpanType::value - 1) / _StrideType::value)>,
3318  .stride = __stride
3319  };
3320  else
3321  return extent_slice{
3322  .offset = __offset,
3323  .extent = _IndexType(__span > 0 ? 1 + (__span - 1) / _StrideType::value : 0),
3324  .stride = __stride
3325  };
3326  }
3327  else if (__span == 0 || __stride == 1)
3328  return extent_slice{
3329  .offset = __offset,
3330  .extent = _IndexType(__span),
3331  .stride = _IndexType(1)
3332  };
3333  else
3334  {
3335  __glibcxx_assert(__stride > 0);
3336  return extent_slice{
3337  .offset = __offset,
3338  .extent = _IndexType(1 + (__span - 1) / __stride),
3339  .stride = __stride
3340  };
3341  }
3342  }
3343 
3344  template<typename _IndexType, typename _Slice>
3345  constexpr auto
3346  __slice_cast(_Slice&& __slice)
3347  {
3348  using _SliceType = remove_cvref_t<_Slice>;
3349  if constexpr (is_convertible_v<_SliceType, full_extent_t>)
3350  return static_cast<full_extent_t>(std::move(__slice));
3351  else if constexpr (is_convertible_v<_SliceType, _IndexType>)
3352  return __mdspan::__canonical_index<_IndexType>(std::move(__slice));
3353  else if constexpr (__is_extent_slice<_SliceType>)
3354  return extent_slice{
3355  .offset = __mdspan::__canonical_index<_IndexType>(std::move(__slice.offset)),
3356  .extent = __mdspan::__canonical_index<_IndexType>(std::move(__slice.extent)),
3357  .stride = __mdspan::__canonical_index<_IndexType>(std::move(__slice.stride))
3358  };
3359  else if constexpr (__is_range_slice<_SliceType>)
3360  {
3361  auto __first
3362  = __mdspan::__canonical_index<_IndexType>(std::move(__slice.first));
3363  auto __last
3364  = __mdspan::__canonical_index<_IndexType>(std::move(__slice.last));
3365  return __mdspan::__canonical_range_slice<_IndexType>(
3366  __first,
3367  __mdspan::__canonical_index<_IndexType>(__last - __first),
3368  __mdspan::__canonical_index<_IndexType>(std::move(__slice.stride)));
3369  }
3370  else
3371  {
3372  auto [__sbegin, __send] = std::move(__slice);
3373  auto __cbegin
3374  = __mdspan::__canonical_index<_IndexType>(std::move(__sbegin));
3375  auto __cend
3376  = __mdspan::__canonical_index<_IndexType>(std::move(__send));
3377  auto __cspan
3378  = __mdspan::__canonical_index<_IndexType>(__cend - __cbegin);
3379  return __mdspan::__canonical_range_slice<_IndexType>(
3380  __cbegin, __cspan, cw<_IndexType(1)>);
3381  }
3382  }
3383 
3384  template<typename _IndexType, size_t _Extent, typename _OIndexType>
3385  constexpr void
3386  __check_inrange_index(const extents<_IndexType, _Extent>& __ext,
3387  const _OIndexType& __idx)
3388  {
3389  if constexpr (__is_constant_wrapper<_OIndexType>
3390  && _Extent != dynamic_extent)
3391  {
3392  static_assert(_OIndexType::value >= 0);
3393  static_assert(std::cmp_less(_OIndexType::value, _Extent));
3394  }
3395  else
3396  __glibcxx_assert(__idx < __ext.extent(0));
3397  }
3398 
3399  template<typename _IndexType, size_t _Extent, typename _OIndexType>
3400  constexpr void
3401  __check_valid_index(const extents<_IndexType, _Extent>& __ext,
3402  const _OIndexType& __idx)
3403  {
3404  if constexpr (__is_constant_wrapper<_OIndexType>
3405  && _Extent != dynamic_extent)
3406  {
3407  static_assert(_OIndexType::value >= 0);
3408  static_assert(std::cmp_less_equal(_OIndexType::value, _Extent));
3409  }
3410  else
3411  __glibcxx_assert(__idx <= __ext.extent(0));
3412  }
3413 
3414  template<typename _IndexType, size_t _Extent, typename _Slice>
3415  constexpr void
3416  __check_valid_slice(const extents<_IndexType, _Extent>& __ext,
3417  const _Slice& __slice)
3418  {
3419  if constexpr (__is_extent_slice<_Slice>)
3420  {
3421  __mdspan::__check_valid_index(__ext, __slice.extent);
3422  // DEVIATION: For empty slices, P3663r3 does not allow us to check
3423  // that this is less than or equal to the k-th extent (at runtime).
3424  // We're only allowed to check if __slice.offset, __slice.extent
3425  // are constant wrappers and __ext is a static extent.
3426  if constexpr (is_same_v<typename _Slice::extent_type,
3427  constant_wrapper<_IndexType(0)>>)
3428  __mdspan::__check_valid_index(__ext, __slice.offset);
3429  else if constexpr (is_same_v<typename _Slice::extent_type,
3430  constant_wrapper<_IndexType(1)>>)
3431  __mdspan::__check_inrange_index(__ext, __slice.offset);
3432  else if constexpr (__is_constant_wrapper<typename _Slice::extent_type>)
3433  {
3434  __mdspan::__check_inrange_index(__ext, __slice.offset);
3435  if constexpr (__is_constant_wrapper<typename _Slice::stride_type>)
3436  static_assert(_Slice::stride_type::value > 0);
3437  else
3438  __glibcxx_assert(__slice.stride > 0);
3439 
3440  if constexpr (_Extent != dynamic_extent
3441  && __is_constant_wrapper<typename _Slice::offset_type>)
3442  static_assert(std::cmp_greater_equal(
3443  _Extent - _Slice::offset_type::value,
3444  _Slice::extent_type::value));
3445  if constexpr (_Extent != dynamic_extent
3446  && __is_constant_wrapper<typename _Slice::stride_type>)
3447  static_assert(std::cmp_greater(
3448  _Extent,
3449  (_Slice::extent_type::value - 1) * _Slice::stride_type::value));
3450 
3451  if constexpr (_Extent != dynamic_extent
3452  && __is_constant_wrapper<typename _Slice::offset_type>
3453  && __is_constant_wrapper<typename _Slice::stride_type>)
3454  static_assert(std::cmp_greater(
3455  _Extent - _Slice::offset_type::value,
3456  (_Slice::extent_type::value - 1) * _Slice::stride_type::value));
3457  else
3458  __glibcxx_assert(std::cmp_greater(
3459  __ext.extent(0) - __slice.offset,
3460  (_Slice::extent_type::value - 1) * __slice.stride));
3461  }
3462  else if constexpr (is_same_v<typename _Slice::stride_type,
3463  constant_wrapper<_IndexType(1)>>)
3464  {
3465  __mdspan::__check_valid_index(__ext, __slice.offset);
3466  __glibcxx_assert(std::cmp_greater_equal(
3467  __ext.extent(0) - __slice.offset,
3468  __slice.extent));
3469  }
3470  else if (__slice.extent == 0)
3471  __mdspan::__check_valid_index(__ext, __slice.offset);
3472  else
3473  {
3474  __glibcxx_assert(__slice.offset < __ext.extent(0));
3475  __glibcxx_assert(__slice.extent == 1 || __slice.stride > 0);
3476  __glibcxx_assert(__slice.extent == 1 || std::cmp_greater(
3477  __ext.extent(0) - __slice.offset,
3478  (__slice.extent - 1) * __slice.stride));
3479  }
3480  }
3481  else if constexpr (!is_same_v<_Slice, full_extent_t>)
3482  __mdspan::__check_inrange_index(__ext, __slice);
3483  }
3484 
3485  template<typename _Extents, typename... _Slices>
3486  constexpr void
3487  __check_valid_slices(const _Extents& __exts, const _Slices&... __slices)
3488  {
3489  constexpr auto __rank = _Extents::rank();
3490  auto __impl = [&]<size_t... _Is>(index_sequence<_Is...>)
3491  {
3492  ((__mdspan::__check_valid_slice(__extract_extent<_Is>(__exts),
3493  __slices...[_Is])),...);
3494  };
3495  __impl(make_index_sequence<__rank>());
3496  }
3497 
3498  template<typename _Slice>
3499  using __full_extent_t = std::full_extent_t;
3500 
3501  // Enables ADL-only calls from submdspan.
3502  void submdspan_mapping() = delete;
3503 
3504  template<typename _Mapping, typename... _Slices>
3505  concept __sliceable_mapping = requires(const _Mapping __m, _Slices... __slices)
3506  {
3507  { submdspan_mapping(__m, __slices...) } -> __submdspan_mapping_result;
3508  };
3509 
3510  template<typename _Mapping, typename... _Slices>
3511  constexpr auto
3512  __submapping(const _Mapping& __mapping, _Slices... __slices)
3513  {
3514  __mdspan::__check_valid_slices(__mapping.extents(), __slices...);
3515  return submdspan_mapping(__mapping, __slices...);
3516  }
3517  }
3518 
3519  template<typename _IndexType, size_t... _Extents, typename... _RawSlices>
3520  requires (sizeof...(_RawSlices) == sizeof...(_Extents))
3521  constexpr auto
3522  subextents(const extents<_IndexType, _Extents...>& __exts,
3523  _RawSlices... __raw_slices)
3524  {
3525  auto __impl = [&__exts](auto... __slices)
3526  {
3527  __mdspan::__check_valid_slices(__exts, __slices...);
3528  return __mdspan::__subextents(__exts, __slices...);
3529  };
3530  return __impl(__mdspan::__slice_cast<_IndexType>(__raw_slices)...);
3531  }
3532 
3533  template<typename _IndexType, size_t... _Extents, typename... _RawSlices>
3534  requires (sizeof...(_Extents) == sizeof...(_RawSlices))
3535  constexpr auto
3536  canonical_slices(const extents<_IndexType, _Extents...>& __exts,
3537  _RawSlices... __raw_slices)
3538  {
3539  auto __impl = [&__exts](auto... __slices)
3540  {
3541  __mdspan::__check_valid_slices(__exts, __slices...);
3542  return std::make_tuple(__slices...);
3543  };
3544  return __impl(__mdspan::__slice_cast<_IndexType>(__raw_slices)...);
3545  }
3546 
3547  template<typename _ElementType, typename _Extents, typename _Layout,
3548  typename _Accessor, typename... _RawSlices>
3549  requires (sizeof...(_RawSlices) == _Extents::rank()
3550  && __mdspan::__sliceable_mapping<typename _Layout::template mapping<_Extents>,
3551  __mdspan::__full_extent_t<_RawSlices>...>)
3552  constexpr auto
3553  submdspan(
3554  const mdspan<_ElementType, _Extents, _Layout, _Accessor>& __md,
3555  _RawSlices... __raw_slices)
3556  {
3557  using _IndexType = typename _Extents::index_type;
3558  auto [__mapping, __offset] = __mdspan::__submapping(
3559  __md.mapping(), __mdspan::__slice_cast<_IndexType>(__raw_slices)...);
3560  return std::mdspan(
3561  __md.accessor().offset(__md.data_handle(), __offset),
3562  std::move(__mapping),
3563  typename _Accessor::offset_policy(__md.accessor()));
3564  }
3565 #endif // __glibcxx_submdspan
3566 
3567 _GLIBCXX_END_NAMESPACE_VERSION
3568 }
3569 #endif
3570 #endif