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