aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3/include')
-rw-r--r--libstdc++-v3/include/Makefile.am1
-rw-r--r--libstdc++-v3/include/Makefile.in1
-rw-r--r--libstdc++-v3/include/bits/intcmp.h120
-rw-r--r--libstdc++-v3/include/bits/iterator_concepts.h4
-rw-r--r--libstdc++-v3/include/bits/max_size_type.h6
-rw-r--r--libstdc++-v3/include/bits/sat_arith.h12
-rw-r--r--libstdc++-v3/include/bits/version.def12
-rw-r--r--libstdc++-v3/include/bits/version.h15
-rw-r--r--libstdc++-v3/include/c_compatibility/stdckdint.h32
-rw-r--r--libstdc++-v3/include/ext/numeric_traits.h2
-rw-r--r--libstdc++-v3/include/std/charconv6
-rw-r--r--libstdc++-v3/include/std/concepts23
-rw-r--r--libstdc++-v3/include/std/latch2
-rw-r--r--libstdc++-v3/include/std/mdspan723
-rw-r--r--libstdc++-v3/include/std/type_traits13
-rw-r--r--libstdc++-v3/include/std/utility72
-rw-r--r--libstdc++-v3/include/std/variant34
17 files changed, 880 insertions, 198 deletions
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 7d65c6f..847fc13 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -134,6 +134,7 @@ bits_freestanding = \
${bits_srcdir}/enable_special_members.h \
${bits_srcdir}/functexcept.h \
${bits_srcdir}/functional_hash.h \
+ ${bits_srcdir}/intcmp.h \
${bits_srcdir}/invoke.h \
${bits_srcdir}/iterator_concepts.h \
${bits_srcdir}/max_size_type.h \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index acf8ae9..1d6171b 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -492,6 +492,7 @@ bits_freestanding = \
${bits_srcdir}/enable_special_members.h \
${bits_srcdir}/functexcept.h \
${bits_srcdir}/functional_hash.h \
+ ${bits_srcdir}/intcmp.h \
${bits_srcdir}/invoke.h \
${bits_srcdir}/iterator_concepts.h \
${bits_srcdir}/max_size_type.h \
diff --git a/libstdc++-v3/include/bits/intcmp.h b/libstdc++-v3/include/bits/intcmp.h
new file mode 100644
index 0000000..bb9c7f2
--- /dev/null
+++ b/libstdc++-v3/include/bits/intcmp.h
@@ -0,0 +1,120 @@
+// Integer comparison functions -*- C++ -*-
+
+// Copyright (C) 2020-2025 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/intcmp.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{utility}
+ */
+
+#ifndef _GLIBCXX_INTCMP_H
+#define _GLIBCXX_INTCMP_H 1
+
+#ifdef _GLIBCXX_SYSHDR
+#pragma GCC system_header
+#endif
+
+#include <bits/version.h>
+
+#ifdef __glibcxx_integer_comparison_functions // C++ >= 20
+
+#include <type_traits>
+#include <ext/numeric_traits.h> // __int_traits
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ cmp_equal(_Tp __t, _Up __u) noexcept
+ {
+ static_assert(__is_signed_or_unsigned_integer<_Tp>::value);
+ static_assert(__is_signed_or_unsigned_integer<_Up>::value);
+
+ if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
+ return __t == __u;
+ else if constexpr (is_signed_v<_Tp>)
+ return __t >= 0 && make_unsigned_t<_Tp>(__t) == __u;
+ else
+ return __u >= 0 && __t == make_unsigned_t<_Up>(__u);
+ }
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ cmp_not_equal(_Tp __t, _Up __u) noexcept
+ { return !std::cmp_equal(__t, __u); }
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ cmp_less(_Tp __t, _Up __u) noexcept
+ {
+ static_assert(__is_signed_or_unsigned_integer<_Tp>::value);
+ static_assert(__is_signed_or_unsigned_integer<_Up>::value);
+
+ if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
+ return __t < __u;
+ else if constexpr (is_signed_v<_Tp>)
+ return __t < 0 || make_unsigned_t<_Tp>(__t) < __u;
+ else
+ return __u >= 0 && __t < make_unsigned_t<_Up>(__u);
+ }
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ cmp_greater(_Tp __t, _Up __u) noexcept
+ { return std::cmp_less(__u, __t); }
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ cmp_less_equal(_Tp __t, _Up __u) noexcept
+ { return !std::cmp_less(__u, __t); }
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ cmp_greater_equal(_Tp __t, _Up __u) noexcept
+ { return !std::cmp_less(__t, __u); }
+
+ template<typename _Res, typename _Tp>
+ constexpr bool
+ in_range(_Tp __t) noexcept
+ {
+ static_assert(__is_signed_or_unsigned_integer<_Res>::value);
+ static_assert(__is_signed_or_unsigned_integer<_Tp>::value);
+ using __gnu_cxx::__int_traits;
+
+ if constexpr (is_signed_v<_Tp> == is_signed_v<_Res>)
+ return __int_traits<_Res>::__min <= __t
+ && __t <= __int_traits<_Res>::__max;
+ else if constexpr (is_signed_v<_Tp>)
+ return __t >= 0
+ && make_unsigned_t<_Tp>(__t) <= __int_traits<_Res>::__max;
+ else
+ return __t <= make_unsigned_t<_Res>(__int_traits<_Res>::__max);
+ }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#endif // __glibcxx_integer_comparison_functions
+#endif // _GLIBCXX_INTCMP_H
diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h
index fd91b22..40ac808 100644
--- a/libstdc++-v3/include/bits/iterator_concepts.h
+++ b/libstdc++-v3/include/bits/iterator_concepts.h
@@ -39,9 +39,6 @@
#include <bits/ptr_traits.h> // to_address
#include <bits/ranges_cmp.h> // identity, ranges::less
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpedantic" // __int128
-
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -1032,6 +1029,5 @@ namespace ranges
#endif // C++20 library concepts
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
-#pragma GCC diagnostic pop
#endif // C++20
#endif // _ITERATOR_CONCEPTS_H
diff --git a/libstdc++-v3/include/bits/max_size_type.h b/libstdc++-v3/include/bits/max_size_type.h
index a34b91a..537acee 100644
--- a/libstdc++-v3/include/bits/max_size_type.h
+++ b/libstdc++-v3/include/bits/max_size_type.h
@@ -44,10 +44,8 @@
// [iterator.concept.winc]) that are one bit wider than the widest supported
// integer type.
//
-// The set of integer types we consider includes __int128 and unsigned __int128
-// (when they exist), even though they are really integer types only in GNU
-// mode. This is to obtain a consistent ABI for these integer-class types
-// across strict mode and GNU mode.
+// The set of integer types we consider includes the extended integer types
+// __int128 and unsigned __int128 (when they exist).
namespace std _GLIBCXX_VISIBILITY(default)
{
diff --git a/libstdc++-v3/include/bits/sat_arith.h b/libstdc++-v3/include/bits/sat_arith.h
index e036fc8..bce86d9 100644
--- a/libstdc++-v3/include/bits/sat_arith.h
+++ b/libstdc++-v3/include/bits/sat_arith.h
@@ -46,7 +46,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
_GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Add two integers, with saturation in case of overflow.
- template<typename _Tp> requires __is_standard_integer<_Tp>::value
+ template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value
constexpr _Tp
add_sat(_Tp __x, _Tp __y) noexcept
{
@@ -62,7 +62,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
/// Subtract one integer from another, with saturation in case of overflow.
- template<typename _Tp> requires __is_standard_integer<_Tp>::value
+ template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value
constexpr _Tp
sub_sat(_Tp __x, _Tp __y) noexcept
{
@@ -78,7 +78,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
/// Multiply two integers, with saturation in case of overflow.
- template<typename _Tp> requires __is_standard_integer<_Tp>::value
+ template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value
constexpr _Tp
mul_sat(_Tp __x, _Tp __y) noexcept
{
@@ -94,7 +94,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
/// Divide one integer by another, with saturation in case of overflow.
- template<typename _Tp> requires __is_standard_integer<_Tp>::value
+ template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value
constexpr _Tp
div_sat(_Tp __x, _Tp __y) noexcept
{
@@ -107,8 +107,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Divide one integer by another, with saturation in case of overflow.
template<typename _Res, typename _Tp>
- requires __is_standard_integer<_Res>::value
- && __is_standard_integer<_Tp>::value
+ requires __is_signed_or_unsigned_integer<_Res>::value
+ && __is_signed_or_unsigned_integer<_Tp>::value
constexpr _Res
saturate_cast(_Tp __x) noexcept
{
diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index 412b9ce..5c010a4 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -879,8 +879,12 @@ ftms = {
ftms = {
name = concepts;
+ // 201806 P0898R3 Standard Library Concepts
+ // 201907 P1754R1 Rename concepts to standard_case for C++20
+ // 202002 P1964R2 Wording for boolean-testable
+ // 202207 P2404R3 Move-only types for equality_comparable_with, etc.
values = {
- v = 202002;
+ v = 202207;
cxxmin = 20;
extra_cond = "__cpp_concepts >= 201907L";
};
@@ -1090,17 +1094,17 @@ ftms = {
name = padded_layouts;
no_stdname = true; // internal
values = {
- v = 1;
+ v = 202403;
cxxmin = 26;
};
};
ftms = {
name = submdspan;
- no_stdname = true; // TODO: change once complete
values = {
- v = 1;
+ v = 202411;
cxxmin = 26;
+ extra_cond = "__glibcxx_constant_wrapper >= 202506L";
};
};
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index 2b96934..26d0689 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -985,9 +985,9 @@
#if !defined(__cpp_lib_concepts)
# if (__cplusplus >= 202002L) && (__cpp_concepts >= 201907L)
-# define __glibcxx_concepts 202002L
+# define __glibcxx_concepts 202207L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_concepts)
-# define __cpp_lib_concepts 202002L
+# define __cpp_lib_concepts 202207L
# endif
# endif
#endif /* !defined(__cpp_lib_concepts) */
@@ -1214,7 +1214,7 @@
#if !defined(__cpp_lib_padded_layouts)
# if (__cplusplus > 202302L)
-# define __glibcxx_padded_layouts 1L
+# define __glibcxx_padded_layouts 202403L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_padded_layouts)
# endif
# endif
@@ -1222,9 +1222,10 @@
#undef __glibcxx_want_padded_layouts
#if !defined(__cpp_lib_submdspan)
-# if (__cplusplus > 202302L)
-# define __glibcxx_submdspan 1L
+# if (__cplusplus > 202302L) && (__glibcxx_constant_wrapper >= 202506L)
+# define __glibcxx_submdspan 202411L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_submdspan)
+# define __cpp_lib_submdspan 202411L
# endif
# endif
#endif /* !defined(__cpp_lib_submdspan) */
@@ -2037,7 +2038,7 @@
# define __cpp_lib_common_reference 202302L
# endif
# endif
-#endif /* !defined(__cpp_lib_common_reference) && defined(__glibcxx_want_common_reference) */
+#endif /* !defined(__cpp_lib_common_reference) */
#undef __glibcxx_want_common_reference
#if !defined(__cpp_lib_common_reference_wrapper)
@@ -2047,7 +2048,7 @@
# define __cpp_lib_common_reference_wrapper 202302L
# endif
# endif
-#endif /* !defined(__cpp_lib_common_reference_wrapper) && defined(__glibcxx_want_common_reference_wrapper) */
+#endif /* !defined(__cpp_lib_common_reference_wrapper) */
#undef __glibcxx_want_common_reference_wrapper
#if !defined(__cpp_lib_formatters)
diff --git a/libstdc++-v3/include/c_compatibility/stdckdint.h b/libstdc++-v3/include/c_compatibility/stdckdint.h
index 1de2d18..5bdf4dc 100644
--- a/libstdc++-v3/include/c_compatibility/stdckdint.h
+++ b/libstdc++-v3/include/c_compatibility/stdckdint.h
@@ -40,15 +40,6 @@
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
#endif
-/// @cond undocumented
-namespace __detail
-{
- template<typename _Tp>
- concept __cv_unqual_signed_or_unsigned_integer_type
- = std::same_as<_Tp, std::remove_cv_t<_Tp>>
- && std::__is_standard_integer<_Tp>::value;
-}
-/// @endcond
/** Checked integer arithmetic
*
@@ -71,10 +62,9 @@ template<typename _Tp1, typename _Tp2, typename _Tp3>
inline bool
ckd_add(_Tp1* __result, _Tp2 __a, _Tp3 __b)
{
- using __gnu_cxx::__detail::__cv_unqual_signed_or_unsigned_integer_type;
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp1>);
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp2>);
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp3>);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp1>::value);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp2>::value);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp3>::value);
return __builtin_add_overflow(__a, __b, __result);
}
@@ -82,10 +72,9 @@ template<typename _Tp1, typename _Tp2, typename _Tp3>
inline bool
ckd_sub(_Tp1* __result, _Tp2 __a, _Tp3 __b)
{
- using __gnu_cxx::__detail::__cv_unqual_signed_or_unsigned_integer_type;
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp1>);
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp2>);
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp3>);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp1>::value);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp2>::value);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp3>::value);
return __builtin_sub_overflow(__a, __b, __result);
}
@@ -93,15 +82,14 @@ template<typename _Tp1, typename _Tp2, typename _Tp3>
inline bool
ckd_mul(_Tp1* __result, _Tp2 __a, _Tp3 __b)
{
- using __gnu_cxx::__detail::__cv_unqual_signed_or_unsigned_integer_type;
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp1>);
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp2>);
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp3>);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp1>::value);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp2>::value);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp3>::value);
return __builtin_mul_overflow(__a, __b, __result);
}
/// @}
#ifndef _GLIBCXX_DOXYGEN
-}
+} // namespace __gnu_cxx
using __gnu_cxx::ckd_add;
using __gnu_cxx::ckd_sub;
diff --git a/libstdc++-v3/include/ext/numeric_traits.h b/libstdc++-v3/include/ext/numeric_traits.h
index 6786dc6..78cb8e3 100644
--- a/libstdc++-v3/include/ext/numeric_traits.h
+++ b/libstdc++-v3/include/ext/numeric_traits.h
@@ -48,7 +48,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// or is_signed, digits10, max_digits10, or max_exponent10 for floats.
// Unlike __is_integer (and std::is_integral) this trait is true for
- // non-standard built-in integer types such as __int128 and __int20.
+ // non-standard built-in integer types such as __int20.
template<typename _Tp>
struct __is_integer_nonstrict
: public std::__is_integer<_Tp>
diff --git a/libstdc++-v3/include/std/charconv b/libstdc++-v3/include/std/charconv
index 8cf2c0b..47f5aaa 100644
--- a/libstdc++-v3/include/std/charconv
+++ b/libstdc++-v3/include/std/charconv
@@ -554,10 +554,10 @@ namespace __detail
} // namespace __detail
- /// std::from_chars for integral types.
+ /// std::from_chars for integer types.
template<typename _Tp,
- enable_if_t<__or_<__is_standard_integer<_Tp>,
- is_same<char, remove_cv_t<_Tp>>>::value, int> = 0>
+ enable_if_t<__or_<__is_signed_or_unsigned_integer<_Tp>,
+ is_same<char, _Tp>>::value, int> = 0>
_GLIBCXX23_CONSTEXPR from_chars_result
from_chars(const char* __first, const char* __last, _Tp& __value,
int __base = 10)
diff --git a/libstdc++-v3/include/std/concepts b/libstdc++-v3/include/std/concepts
index d9920a8..870b0a4 100644
--- a/libstdc++-v3/include/std/concepts
+++ b/libstdc++-v3/include/std/concepts
@@ -296,6 +296,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ { !static_cast<_Tp&&>(__t) } -> __boolean_testable_impl; };
} // namespace __detail
+ // [concept.comparisoncommontype], helpers for comparison common types
+ namespace __detail
+ {
+ template<typename _Tp, typename _Up,
+ typename _Cref = common_reference_t<const _Tp&, const _Up&>>
+ concept __comparison_common_type_with_impl
+ = same_as<common_reference_t<const _Tp&, const _Up&>,
+ common_reference_t<const _Up&, const _Tp&>>
+ && requires {
+ requires convertible_to<const _Tp&, const _Cref&>
+ || convertible_to<_Tp, const _Cref&>;
+ requires convertible_to<const _Up&, const _Cref&>
+ || convertible_to<_Up, const _Cref&>;
+ };
+
+ template<typename _Tp, typename _Up>
+ concept __comparison_common_type_with
+ = __comparison_common_type_with_impl<remove_cvref_t<_Tp>,
+ remove_cvref_t<_Up>>;
+ } // namespace __detail
+
// [concept.equalitycomparable], concept equality_comparable
namespace __detail
@@ -316,7 +337,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename _Up>
concept equality_comparable_with
= equality_comparable<_Tp> && equality_comparable<_Up>
- && common_reference_with<__detail::__cref<_Tp>, __detail::__cref<_Up>>
+ && __detail::__comparison_common_type_with<_Tp, _Up>
&& equality_comparable<common_reference_t<__detail::__cref<_Tp>,
__detail::__cref<_Up>>>
&& __detail::__weakly_eq_cmp_with<_Tp, _Up>;
diff --git a/libstdc++-v3/include/std/latch b/libstdc++-v3/include/std/latch
index 9504df0..df126c6 100644
--- a/libstdc++-v3/include/std/latch
+++ b/libstdc++-v3/include/std/latch
@@ -41,7 +41,7 @@
#ifdef __cpp_lib_latch // C++ >= 20 && atomic_wait
#include <bits/atomic_base.h>
#include <ext/numeric_traits.h>
-#include <utility> // cmp_equal, cmp_less_equal, etc.
+#include <bits/intcmp.h> // cmp_equal, cmp_less_equal, etc.
namespace std _GLIBCXX_VISIBILITY(default)
{
diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
index 03cc4f0..dc0aa4f 100644
--- a/libstdc++-v3/include/std/mdspan
+++ b/libstdc++-v3/include/std/mdspan
@@ -271,7 +271,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
requires (_Extents.size() > 0)
{
return {_M_dyn_exts + _S_dynamic_index(__begin),
- _M_dyn_exts + _S_dynamic_index(__end)};
+ _S_dynamic_index(__end) - _S_dynamic_index(__begin)};
}
private:
@@ -352,11 +352,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _OffsetType, typename _ExtentType, typename _StrideType>
struct strided_slice
{
- static_assert(__is_standard_integer<_OffsetType>::value
+ static_assert(__is_signed_or_unsigned_integer<_OffsetType>::value
|| __detail::__integral_constant_like<_OffsetType>);
- static_assert(__is_standard_integer<_ExtentType>::value
+ static_assert(__is_signed_or_unsigned_integer<_ExtentType>::value
|| __detail::__integral_constant_like<_ExtentType>);
- static_assert(__is_standard_integer<_StrideType>::value
+ static_assert(__is_signed_or_unsigned_integer<_StrideType>::value
|| __detail::__integral_constant_like<_StrideType>);
using offset_type = _OffsetType;
@@ -374,12 +374,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
[[no_unique_address]] _Mapping mapping = _Mapping();
size_t offset{};
};
+
+ template<typename _Tp>
+ constexpr bool __is_submdspan_mapping_result = false;
+
+ template<typename _Mapping>
+ constexpr bool __is_submdspan_mapping_result<submdspan_mapping_result<_Mapping>> = true;
+
+ template<typename _Mapping>
+ concept __submdspan_mapping_result = __is_submdspan_mapping_result<_Mapping>;
+
#endif // __glibcxx_submdspan
template<typename _IndexType, size_t... _Extents>
class extents
{
- static_assert(__is_standard_integer<_IndexType>::value,
+ static_assert(__is_signed_or_unsigned_integer<_IndexType>::value,
"IndexType must be a signed or unsigned integer type");
static_assert(
(__mdspan::__valid_static_extent<_Extents, _IndexType> && ...),
@@ -589,6 +599,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
}
+ template<typename _IndexType, size_t _Nm>
+ consteval _IndexType
+ __fwd_prod(span<const _IndexType, _Nm> __values)
+ {
+ _IndexType __ret = 1;
+ for(auto __value : __values)
+ __ret *= __value;
+ return __ret;
+ }
+
// Preconditions: _r < _Extents::rank()
template<typename _Extents>
constexpr typename _Extents::index_type
@@ -792,6 +812,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Mapping>
constexpr bool __is_right_padded_mapping = __padded_mapping_of<
layout_right_padded, _Mapping>;
+
+ template<typename _Mapping>
+ constexpr bool __is_padded_mapping = __is_left_padded_mapping<_Mapping>
+ || __is_right_padded_mapping<_Mapping>;
#endif
template<typename _PaddedMapping>
@@ -866,6 +890,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__exts.extent(_Index)};
}
+ template<typename _Slice, typename _IndexType>
+ concept __acceptable_slice_type = same_as<_Slice, full_extent_t>
+ || same_as<_Slice, _IndexType> || __is_constant_wrapper<_Slice>
+ || __is_strided_slice<_Slice>;
+
template<typename _IndexType, typename... _Slices>
consteval auto
__subrank()
@@ -890,6 +919,547 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__map[__i++] = __k;
return __map;
}
+
+ template<typename _Slice>
+ constexpr auto
+ __slice_begin(_Slice __slice)
+ {
+ if constexpr (same_as<_Slice, full_extent_t>)
+ return 0;
+ else if constexpr (__is_strided_slice<_Slice>)
+ return __slice.offset;
+ else
+ return __slice; // collapsing slice
+ }
+
+ template<typename _Mapping, typename... _Slices>
+ constexpr size_t
+ __suboffset(const _Mapping& __mapping, const _Slices&... __slices)
+ {
+ using _IndexType = typename _Mapping::index_type;
+ auto __any_past_the_end = [&]<size_t... _Is>(index_sequence<_Is...>)
+ {
+ auto __is_past_the_end = [](const auto& __slice, const auto& __ext)
+ {
+ using _Slice = remove_cvref_t<decltype(__slice)>;
+ if constexpr (is_convertible_v<_Slice, _IndexType>)
+ return false;
+ else if constexpr (same_as<_Slice, full_extent_t>
+ && __ext.static_extent(0) != 0
+ && __ext.static_extent(0) != dynamic_extent)
+ return false;
+ else
+ return __mdspan::__slice_begin(__slice) == __ext.extent(0);
+ };
+
+ const auto& __exts = __mapping.extents();
+ return ((__is_past_the_end(__slices...[_Is],
+ __mdspan::__extract_extent<_Is>(__exts))) || ...);
+ };
+
+ if constexpr ((same_as<_Slices, full_extent_t> && ...))
+ return __mdspan::__offset(__mapping);
+
+ if (__any_past_the_end(std::make_index_sequence<sizeof...(__slices)>()))
+ return __mapping.required_span_size();
+ return __mapping(__mdspan::__slice_begin(__slices)...);
+ }
+
+ template<typename _IndexType, size_t _Extent, typename _Slice>
+ consteval size_t
+ __static_slice_extent()
+ {
+ if constexpr (same_as<_Slice, full_extent_t>)
+ return _Extent;
+ else if constexpr (same_as<_Slice, constant_wrapper<_IndexType(0)>>)
+ return 0;
+ else if constexpr (__is_constant_wrapper<typename _Slice::extent_type>
+ && __is_constant_wrapper<typename _Slice::stride_type>)
+ return 1 + ((typename _Slice::extent_type{}) - 1)
+ / (typename _Slice::stride_type{});
+ else
+ return dynamic_extent;
+ }
+
+ template<size_t _K, typename _Extents, typename _Slice>
+ constexpr typename _Extents::index_type
+ __dynamic_slice_extent(const _Extents& __exts, _Slice __slice)
+ {
+ if constexpr (__is_strided_slice<_Slice>)
+ return __slice.extent == 0 ? 0 : 1 + (__slice.extent - 1) / __slice.stride;
+ else
+ return __exts.extent(_K);
+ }
+
+ template<typename _IndexType, size_t... _Extents, typename... _Slices>
+ requires (sizeof...(_Slices) == sizeof...(_Extents))
+ constexpr auto
+ __subextents(const extents<_IndexType, _Extents...>& __exts,
+ _Slices... __slices)
+ {
+ constexpr auto __inv_map = __mdspan::__inv_map_rank<_IndexType, _Slices...>();
+ auto __impl = [&]<size_t... _Indices>(std::index_sequence<_Indices...>)
+ {
+ using _SubExts = extents<_IndexType,
+ __mdspan::__static_slice_extent<_IndexType,
+ _Extents...[__inv_map[_Indices]],
+ _Slices...[__inv_map[_Indices]]>()...>;
+ if constexpr (_SubExts::rank_dynamic() == 0)
+ return _SubExts{};
+ else
+ {
+ using _StaticSubExtents = __mdspan::_StaticExtents<
+ __mdspan::__static_extents<_SubExts>()>;
+ auto __create = [&]<size_t... _Is>(std::index_sequence<_Is...>)
+ {
+ constexpr auto __slice_idx = [__inv_map](size_t __i) consteval
+ {
+ return __inv_map[_StaticSubExtents::_S_dynamic_index_inv(__i)];
+ };
+
+ return _SubExts{__mdspan::__dynamic_slice_extent<__slice_idx(_Is)>(
+ __exts, __slices...[__slice_idx(_Is)])...};
+ };
+ constexpr auto __dyn_subrank = _SubExts::rank_dynamic();
+ return __create(std::make_index_sequence<__dyn_subrank>());
+ }
+ };
+
+ return __impl(std::make_index_sequence<__inv_map.size()>());
+ }
+
+ enum class _LayoutSide
+ {
+ __left,
+ __right,
+ __unknown
+ };
+
+ template<typename _Mapping>
+ consteval _LayoutSide
+ __mapping_side()
+ {
+ if constexpr (__is_left_padded_mapping<_Mapping>
+ || __mapping_of<layout_left, _Mapping>)
+ return _LayoutSide::__left;
+ if constexpr (__is_right_padded_mapping<_Mapping>
+ || __mapping_of<layout_right, _Mapping>)
+ return _LayoutSide::__right;
+ else
+ return _LayoutSide::__unknown;
+ }
+
+ template<_LayoutSide _Side, size_t _Rank>
+ struct _StridesTrait
+ {
+ static constexpr const _LayoutSide _S_side = _Side;
+
+ static constexpr size_t
+ _S_idx(size_t __k) noexcept
+ {
+ if constexpr (_Side == _LayoutSide::__left)
+ return __k;
+ else
+ return _Rank - 1 - __k;
+ }
+
+ // Unifies the formulas for computing strides for padded and unpadded
+ // layouts.
+ template<typename _Mapping>
+ static constexpr typename _Mapping::index_type
+ _S_padded_extent(const _Mapping& __mapping, size_t __k)
+ {
+ if (__k == 0)
+ return __mapping.stride(_S_idx(1));
+ else
+ return __mapping.extents().extent(_S_idx(__k));
+ }
+
+ template<typename _IndexType, typename... _Slices>
+ static consteval auto
+ _S_inv_map()
+ {
+ static_assert(_Side != _LayoutSide::__unknown);
+ auto __impl = [&]<size_t... _Is>(std::index_sequence<_Is...>)
+ {
+ return __mdspan::__inv_map_rank<_IndexType, _Slices...[_S_idx(_Is)]...>();
+ };
+ return __impl(std::make_index_sequence<_Rank>());
+ }
+ };
+
+ template<typename _SubExts, typename _Mapping, typename... _Slices>
+ constexpr auto
+ __substrides_generic(const _Mapping& __mapping, const _Slices&... __slices)
+ {
+ using _IndexType = typename _Mapping::index_type;
+ if constexpr (_SubExts::rank() == 0)
+ return array<_IndexType, _SubExts::rank()>{};
+ else
+ {
+ auto __stride = [&__mapping](size_t __k, auto __slice) -> _IndexType
+ {
+ if constexpr (__is_strided_slice<decltype(__slice)>)
+ if (__slice.stride < __slice.extent)
+ return __mapping.stride(__k) * __slice.stride;
+ return __mapping.stride(__k);
+ };
+
+ auto __impl = [&]<size_t... _Is>(std::index_sequence<_Is...>)
+ {
+ constexpr auto __inv_map
+ = __mdspan::__inv_map_rank<_IndexType, _Slices...>();
+ return array<_IndexType, _SubExts::rank()>{
+ __stride(__inv_map[_Is], __slices...[__inv_map[_Is]])...};
+ };
+ return __impl(std::make_index_sequence<_SubExts::rank()>());
+ }
+ };
+
+ template<typename _SubExts, typename _Mapping, typename... _Slices>
+ constexpr auto
+ __substrides_standardized(const _Mapping& __mapping,
+ const _Slices&... __slices)
+ {
+ using _IndexType = typename _Mapping::index_type;
+ using _Trait = _StridesTrait<__mapping_side<_Mapping>(),
+ _Mapping::extents_type::rank()>;
+ using _SubTrait = _StridesTrait<__mapping_side<_Mapping>(), _SubExts::rank()>;
+
+ constexpr size_t __sub_rank = _SubExts::rank();
+
+ std::array<_IndexType, __sub_rank> __ret;
+ if constexpr (__sub_rank > 0)
+ {
+ constexpr auto __inv_map
+ = _Trait::template _S_inv_map<_IndexType, _Slices...>();
+ auto __loop = [&]<size_t... _Ks>(std::index_sequence<_Ks...>)
+ {
+ size_t __i0 = 0;
+ size_t __stride = 1;
+ auto __body = [&](size_t __k, auto __slice)
+ {
+ for (size_t __i = __i0; __i < __inv_map[__k]; ++__i)
+ __stride *= _Trait::_S_padded_extent(__mapping, __i);
+
+ size_t __krev = _SubTrait::_S_idx(__k);
+ if constexpr (__is_strided_slice<decltype(__slice)>)
+ {
+ if (__slice.stride < __slice.extent)
+ __ret[__krev] = __stride * __slice.stride;
+ else
+ __ret[__krev] = __stride;
+ }
+ else
+ __ret[__krev] = __stride;
+
+ __i0 = __inv_map[__k];
+ };
+
+ ((__body(_Ks, __slices...[_Trait::_S_idx(__inv_map[_Ks])])),...);
+ };
+ __loop(std::make_index_sequence<__sub_rank>());
+ }
+ return __ret;
+ }
+
+
+ template<typename _SubExts, typename _Mapping, typename... _Slices>
+ constexpr auto
+ __substrides(const _Mapping& __mapping, const _Slices&... __slices)
+ {
+ if constexpr (__mdspan::__mapping_side<_Mapping>() == _LayoutSide::__unknown)
+ return __mdspan::__substrides_generic<_SubExts>(__mapping, __slices...);
+ else
+ return __mdspan::__substrides_standardized<_SubExts>(__mapping, __slices...);
+ }
+
+ template<typename _Slice>
+ concept __is_unit_stride_slice = (__mdspan::__is_strided_slice<_Slice>
+ && __mdspan::__is_constant_wrapper<typename _Slice::stride_type>
+ && _Slice::stride_type::value == 1)
+ || std::same_as<_Slice, full_extent_t>;
+
+ // These are (forced) exclusive categories:
+ // - full & collapsing: obvious,
+ // - unit_strided_slice: strided_slice{a, b, cw<1>}, but not `full`,
+ // - strided_slice: strided_slice{a, b, c} with c != cw<1>.
+ enum class _SliceKind
+ {
+ __strided_slice,
+ __unit_strided_slice,
+ __full,
+ __collapsing
+ };
+
+ template<typename _Slice>
+ consteval _SliceKind
+ __make_slice_kind()
+ {
+ if constexpr (std::same_as<_Slice, full_extent_t>)
+ return _SliceKind::__full;
+ else if constexpr (__mdspan::__is_strided_slice<_Slice>)
+ {
+ if constexpr (__mdspan::__is_unit_stride_slice<_Slice>)
+ return _SliceKind::__unit_strided_slice;
+ else
+ return _SliceKind::__strided_slice;
+ }
+ else
+ return _SliceKind::__collapsing;
+ }
+
+ template<typename... _Slices>
+ consteval array<_SliceKind, sizeof...(_Slices)>
+ __make_slice_kind_array()
+ {
+ return array<_SliceKind, sizeof...(_Slices)>{
+ __mdspan::__make_slice_kind<_Slices>()...};
+ }
+
+ // __block_size - 1
+ // [full, ..., full, unit_slice , *]
+ consteval bool
+ __is_block(span<const _SliceKind> __slice_kinds, size_t __block_size)
+ {
+ if (__block_size == 0)
+ return false;
+
+ if (__block_size > __slice_kinds.size())
+ return false;
+
+ for (size_t __i = 0; __i < __block_size - 1; ++__i)
+ if (__slice_kinds[__i] != _SliceKind::__full)
+ return false;
+
+ auto __last = __slice_kinds[__block_size - 1];
+ return __last == _SliceKind::__full
+ || __last == _SliceKind::__unit_strided_slice;
+ }
+
+ // __u __u + __sub_rank-2
+ // [unit_slice, i, ..., k, full, ..., full, unit_slice, *]
+ static consteval size_t
+ __padded_block_begin_generic(span<const _SliceKind> __slice_kinds,
+ size_t __sub_rank)
+ {
+ if (__slice_kinds[0] != _SliceKind::__full
+ && __slice_kinds[0] != _SliceKind::__unit_strided_slice)
+ return dynamic_extent;
+ else if (__slice_kinds.size() == 1)
+ return dynamic_extent;
+ else
+ {
+ size_t __u = 1;
+ while(__u < __slice_kinds.size()
+ && __slice_kinds[__u] == _SliceKind::__collapsing)
+ ++__u;
+
+ if (__mdspan::__is_block(__slice_kinds.subspan(__u), __sub_rank -1))
+ return __u;
+ return dynamic_extent;
+ }
+ }
+
+ template<_LayoutSide _Side, size_t _Nm>
+ static consteval size_t
+ __padded_block_begin(span<const _SliceKind, _Nm> __slice_kinds, size_t __sub_rank)
+ {
+ if constexpr (_Side == _LayoutSide::__left)
+ return __mdspan::__padded_block_begin_generic(__slice_kinds, __sub_rank);
+ else
+ {
+ std::array<_SliceKind, _Nm> __rev_slices;
+ for(size_t __i = 0; __i < _Nm; ++__i)
+ __rev_slices[__i] = __slice_kinds[_Nm - 1 - __i];
+ auto __rev_slice_kinds = span<const _SliceKind>(__rev_slices);
+
+ auto __u = __mdspan::__padded_block_begin_generic(__rev_slice_kinds,
+ __sub_rank);
+ return __u == dynamic_extent ? dynamic_extent : _Nm - 1 - __u;
+ }
+ }
+
+ template<_LayoutSide _Side, bool _Padded>
+ struct _SubMdspanMapping;
+
+ template<>
+ struct _SubMdspanMapping<_LayoutSide::__left, false>
+ {
+ using _Layout = layout_left;
+ template<size_t _Pad> using _PaddedLayout = layout_left_padded<_Pad>;
+
+ template<typename _Mapping, size_t _Us>
+ static consteval size_t
+ _S_pad()
+ {
+ using _Extents = typename _Mapping::extents_type;
+ constexpr auto __sta_exts = __mdspan::__static_extents<_Extents>(0, _Us);
+ if constexpr (!__mdspan::__all_static(__sta_exts))
+ return dynamic_extent;
+ else
+ return __mdspan::__fwd_prod(__sta_exts);
+ }
+
+ template<size_t _Nm>
+ static consteval bool
+ _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds, size_t __sub_rank)
+ { return __mdspan::__is_block(__slice_kinds, __sub_rank); }
+ };
+
+ template<>
+ struct _SubMdspanMapping<_LayoutSide::__left, true>
+ {
+ using _Layout = layout_left;
+ template<size_t _Pad> using _PaddedLayout = layout_left_padded<_Pad>;
+
+ template<typename _Mapping, size_t _Us>
+ static consteval size_t
+ _S_pad()
+ {
+ using _Extents = typename _Mapping::extents_type;
+ constexpr auto __sta_exts
+ = __mdspan::__static_extents<_Extents>(1, _Us);
+ constexpr auto __sta_padstride
+ = __mdspan::__get_static_stride<_Mapping>();
+ if constexpr (__sta_padstride == dynamic_extent
+ || !__mdspan::__all_static(__sta_exts))
+ return dynamic_extent;
+ else
+ return __sta_padstride * __mdspan::__fwd_prod(__sta_exts);
+ }
+
+ template<size_t _Nm>
+ static consteval bool
+ _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
+ size_t __sub_rank)
+ {
+ if (__sub_rank == 1)
+ return __slice_kinds[0] == _SliceKind::__unit_strided_slice
+ || __slice_kinds[0] == _SliceKind::__full;
+ else
+ return false;
+ }
+ };
+
+ template<>
+ struct _SubMdspanMapping<_LayoutSide::__right, false>
+ {
+ using _Layout = layout_right;
+ template<size_t _Pad> using _PaddedLayout = layout_right_padded<_Pad>;
+
+ template<typename _Mapping, size_t _Us>
+ static consteval size_t
+ _S_pad()
+ {
+ using _Extents = typename _Mapping::extents_type;
+ constexpr auto __rank = _Extents::rank();
+ constexpr auto __sta_exts
+ = __mdspan::__static_extents<_Extents>(_Us + 1, __rank);
+ if constexpr (!__mdspan::__all_static(__sta_exts))
+ return dynamic_extent;
+ else
+ return __fwd_prod(__sta_exts);
+ }
+
+ template<size_t _Nm>
+ static consteval bool
+ _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
+ size_t __sub_rank)
+ {
+ auto __rev_slice_kinds = array<_SliceKind, _Nm>{};
+ for(size_t __i = 0; __i < _Nm; ++__i)
+ __rev_slice_kinds[__i] = __slice_kinds[_Nm - 1 - __i];
+ return __mdspan::__is_block(span(__rev_slice_kinds), __sub_rank);
+ }
+ };
+
+ template<>
+ struct _SubMdspanMapping<_LayoutSide::__right, true>
+ {
+ using _Layout = layout_right;
+ template<size_t _Pad> using _PaddedLayout = layout_right_padded<_Pad>;
+
+ template<typename _Mapping, size_t _Us>
+ static consteval size_t
+ _S_pad()
+ {
+ using _Extents = typename _Mapping::extents_type;
+ constexpr auto __rank = _Extents::rank();
+ constexpr auto __sta_exts
+ = __mdspan::__static_extents<_Extents>(_Us + 1, __rank - 1);
+ constexpr auto __sta_padstride
+ = __mdspan::__get_static_stride<_Mapping>();
+ if constexpr (__sta_padstride == dynamic_extent
+ || !__mdspan::__all_static(__sta_exts))
+ return dynamic_extent;
+ else
+ return __sta_padstride * __mdspan::__fwd_prod(__sta_exts);
+ }
+
+ template<size_t _Nm>
+ static consteval bool
+ _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
+ size_t __sub_rank)
+ {
+ if (__sub_rank == 1)
+ return __slice_kinds[_Nm - 1] == _SliceKind::__unit_strided_slice
+ || __slice_kinds[_Nm - 1] == _SliceKind::__full;
+ else
+ return false;
+ }
+ };
+
+
+ template<typename _Mapping>
+ constexpr auto
+ __submdspan_mapping_impl(const _Mapping& __mapping)
+ { return submdspan_mapping_result{__mapping, 0}; }
+
+ template<typename _Mapping, typename... _Slices>
+ requires (sizeof...(_Slices) > 0)
+ constexpr auto
+ __submdspan_mapping_impl(const _Mapping& __mapping, _Slices... __slices)
+ {
+ using _IndexType = typename _Mapping::index_type;
+ static_assert((__acceptable_slice_type<_Slices, _IndexType> && ...));
+
+ constexpr auto __side = __mdspan::__mapping_side<_Mapping>();
+ constexpr auto __rank = sizeof...(_Slices);
+ using _Trait = _SubMdspanMapping<__side, __is_padded_mapping<_Mapping>>;
+ using _SliceView = span<const _SliceKind, __rank>;
+
+ constexpr auto __slice_kinds = __mdspan::__make_slice_kind_array<_Slices...>();
+ auto __offset = __mdspan::__suboffset(__mapping, __slices...);
+ auto __sub_exts = __mdspan::__subextents(__mapping.extents(), __slices...);
+ using _SubExts = decltype(__sub_exts);
+ constexpr auto __sub_rank = _SubExts::rank();
+ if constexpr (__sub_rank == 0)
+ return submdspan_mapping_result{
+ typename _Trait::_Layout::mapping(__sub_exts), __offset};
+ else if constexpr (_Trait::_S_is_unpadded_submdspan(
+ _SliceView(__slice_kinds), __sub_rank))
+ return submdspan_mapping_result{
+ typename _Trait::_Layout::mapping(__sub_exts), __offset};
+ else if constexpr (
+ constexpr auto __u = __padded_block_begin<__side>(
+ _SliceView(__slice_kinds), __sub_rank);
+ __u != dynamic_extent)
+ {
+ constexpr auto __pad = _Trait::template _S_pad<_Mapping, __u>();
+ using _Layout = typename _Trait::template _PaddedLayout<__pad>;
+ return submdspan_mapping_result{
+ typename _Layout::mapping(__sub_exts, __mapping.stride(__u)),
+ __offset};
+ }
+ else
+ {
+ auto __sub_strides
+ = __mdspan::__substrides<_SubExts>(__mapping, __slices...);
+ return submdspan_mapping_result{
+ layout_stride::mapping(__sub_exts, __sub_strides), __offset};
+ }
+ }
#endif // __glibcxx_submdspan
}
@@ -1032,6 +1602,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_assert(__mdspan::__is_representable_extents(_M_extents));
}
+#if __glibcxx_submdspan
+ template<typename... _Slices>
+ requires (extents_type::rank() == sizeof...(_Slices))
+ friend constexpr auto
+ submdspan_mapping(const mapping& __mapping, _Slices... __slices)
+ { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
+#endif // __glibcxx_submdspan
+
[[no_unique_address]] extents_type _M_extents{};
};
@@ -1208,6 +1786,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_assert(__mdspan::__is_representable_extents(_M_extents));
}
+#if __glibcxx_submdspan
+ template<typename... _Slices>
+ requires (extents_type::rank() == sizeof...(_Slices))
+ friend constexpr auto
+ submdspan_mapping(const mapping& __mapping, _Slices... __slices)
+ { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
+#endif // __glibcxx_submdspan
+
[[no_unique_address]] extents_type _M_extents{};
};
@@ -1418,6 +2004,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
private:
+#if __glibcxx_submdspan
+ template<typename... _Slices>
+ requires (extents_type::rank() == sizeof...(_Slices))
+ friend constexpr auto
+ submdspan_mapping(const mapping& __mapping, _Slices... __slices)
+ {
+ if constexpr (sizeof...(_Slices) == 0)
+ return submdspan_mapping_result{__mapping, 0};
+ else
+ {
+ auto __offset = __mdspan::__suboffset(__mapping, __slices...);
+ auto __sub_exts = __mdspan::__subextents(__mapping.extents(), __slices...);
+ auto __sub_strides
+ = __mdspan::__substrides<decltype(__sub_exts)>(__mapping, __slices...);
+ return submdspan_mapping_result{
+ layout_stride::mapping(__sub_exts, __sub_strides), __offset};
+ }
+ }
+#endif
+
using _Strides = typename __array_traits<index_type,
extents_type::rank()>::_Type;
[[no_unique_address]] extents_type _M_extents;
@@ -2028,6 +2634,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator==(const mapping& __self, const _LeftpadMapping& __other)
noexcept
{ return __self._M_storage._M_equal(__other); }
+
+ private:
+#if __glibcxx_submdspan
+ template<typename... _Slices>
+ requires (extents_type::rank() == sizeof...(_Slices))
+ friend constexpr auto
+ submdspan_mapping(const mapping& __mapping, _Slices... __slices)
+ { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
+#endif // __glibcxx_submdspan
};
template<size_t _PaddingValue>
@@ -2197,6 +2812,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator==(const mapping& __self, const _RightPaddedMapping& __other)
noexcept
{ return __self._M_storage._M_equal(__other); }
+
+#if __glibcxx_submdspan
+ private:
+ template<typename... _Slices>
+ requires (extents_type::rank() == sizeof...(_Slices))
+ friend constexpr auto
+ submdspan_mapping(const mapping& __mapping, _Slices... __slices)
+ { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
+#endif // __glibcxx_submdspan
};
#endif // __glibcxx_padded_layouts
@@ -2700,68 +3324,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__impl(make_index_sequence<__rank>());
}
- template<typename _IndexType, size_t _Extent, typename _Slice>
- consteval size_t
- __static_slice_extent()
- {
- if constexpr (same_as<_Slice, full_extent_t>)
- return _Extent;
- else if constexpr (same_as<_Slice, constant_wrapper<_IndexType(0)>>)
- return 0;
- else if constexpr (__is_constant_wrapper<typename _Slice::extent_type>
- && __is_constant_wrapper<typename _Slice::stride_type>)
- return 1 + ((typename _Slice::extent_type{}) - 1)
- / (typename _Slice::stride_type{});
- else
- return dynamic_extent;
- }
+ template<typename _Slice>
+ using __full_extent_t = std::full_extent_t;
- template<size_t _K, typename _Extents, typename _Slice>
- constexpr typename _Extents::index_type
- __dynamic_slice_extent(const _Extents& __exts, _Slice __slice)
+ // Enables ADL-only calls from submdspan.
+ void submdspan_mapping() = delete;
+
+ template<typename _Mapping, typename... _Slices>
+ concept __sliceable_mapping = requires(const _Mapping __m, _Slices... __slices)
{
- if constexpr (__is_strided_slice<_Slice>)
- return __slice.extent == 0 ? 0 : 1 + (__slice.extent - 1) / __slice.stride;
- else
- return __exts.extent(_K);
- }
+ { submdspan_mapping(__m, __slices...) } -> __submdspan_mapping_result;
+ };
- template<typename _IndexType, size_t... _Extents, typename... _Slices>
- requires (sizeof...(_Slices) == sizeof...(_Extents))
+ template<typename _Mapping, typename... _Slices>
constexpr auto
- __subextents(const extents<_IndexType, _Extents...>& __exts,
- _Slices... __slices)
+ __submapping(const _Mapping& __mapping, _Slices... __slices)
{
- constexpr auto __inv_map = __mdspan::__inv_map_rank<_IndexType, _Slices...>();
- auto __impl = [&]<size_t... _Indices>(index_sequence<_Indices...>)
- {
- using _SubExtents = extents<_IndexType,
- (__mdspan::__static_slice_extent<_IndexType,
- _Extents...[__inv_map[_Indices]],
- _Slices...[__inv_map[_Indices]]>())...>;
- if constexpr (_SubExtents::rank_dynamic() == 0)
- return _SubExtents{};
- else
- {
- using _StaticSubExtents = __mdspan::_StaticExtents<
- __mdspan::__static_extents<_SubExtents>()>;
- auto __create = [&]<size_t... _Is>(index_sequence<_Is...>)
- {
- constexpr auto __slice_idx = [__inv_map](size_t __i) consteval
- {
- return __inv_map[_StaticSubExtents::_S_dynamic_index_inv(__i)];
- };
-
- return _SubExtents{
- (__mdspan::__dynamic_slice_extent<__slice_idx(_Is)>(
- __exts, __slices...[__slice_idx(_Is)]))...};
- };
- constexpr auto __dyn_subrank = _SubExtents::rank_dynamic();
- return __create(make_index_sequence<__dyn_subrank>());
- }
- };
-
- return __impl(make_index_sequence<__inv_map.size()>());
+ __mdspan::__check_valid_slices(__mapping.extents(), __slices...);
+ return submdspan_mapping(__mapping, __slices...);
}
}
@@ -2792,6 +3372,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
return __impl(__mdspan::__slice_cast<_IndexType>(__raw_slices)...);
}
+
+ template<typename _ElementType, typename _Extents, typename _Layout,
+ typename _Accessor, typename... _RawSlices>
+ requires (sizeof...(_RawSlices) == _Extents::rank()
+ && __mdspan::__sliceable_mapping<typename _Layout::mapping<_Extents>,
+ __mdspan::__full_extent_t<_RawSlices>...>)
+ constexpr auto
+ submdspan(
+ const mdspan<_ElementType, _Extents, _Layout, _Accessor>& __md,
+ _RawSlices... __raw_slices)
+ {
+ using _IndexType = typename _Extents::index_type;
+ auto [__mapping, __offset] = __mdspan::__submapping(
+ __md.mapping(), __mdspan::__slice_cast<_IndexType>(__raw_slices)...);
+ return std::mdspan(
+ __md.accessor().offset(__md.data_handle(), __offset),
+ std::move(__mapping),
+ typename _Accessor::offset_policy(__md.accessor()));
+ }
#endif // __glibcxx_submdspan
_GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 7c157ea..3f0bcc4e 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -826,7 +826,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Check if a type is one of the signed integer types.
__extension__
template<typename _Tp>
- using __is_signed_integer = __is_one_of<__remove_cv_t<_Tp>,
+ using __is_signed_integer = __is_one_of<_Tp,
signed char, signed short, signed int, signed long,
signed long long
#if defined(__GLIBCXX_TYPE_INT_N_0)
@@ -841,12 +841,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if defined(__GLIBCXX_TYPE_INT_N_3)
, signed __GLIBCXX_TYPE_INT_N_3
#endif
+#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
+ , signed __int128
+#endif
>;
// Check if a type is one of the unsigned integer types.
__extension__
template<typename _Tp>
- using __is_unsigned_integer = __is_one_of<__remove_cv_t<_Tp>,
+ using __is_unsigned_integer = __is_one_of<_Tp,
unsigned char, unsigned short, unsigned int, unsigned long,
unsigned long long
#if defined(__GLIBCXX_TYPE_INT_N_0)
@@ -861,11 +864,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if defined(__GLIBCXX_TYPE_INT_N_3)
, unsigned __GLIBCXX_TYPE_INT_N_3
#endif
+#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
+ , unsigned __int128
+#endif
>;
// Check if a type is one of the signed or unsigned integer types.
+ // i.e. an integral type except bool, char, wchar_t, and charN_t.
template<typename _Tp>
- using __is_standard_integer
+ using __is_signed_or_unsigned_integer
= __or_<__is_signed_integer<_Tp>, __is_unsigned_integer<_Tp>>;
// __void_t (std::void_t for C++11)
diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility
index 3ae1852..0f6dd82 100644
--- a/libstdc++-v3/include/std/utility
+++ b/libstdc++-v3/include/std/utility
@@ -78,7 +78,7 @@
#include <bits/utility.h>
#if __cplusplus >= 202002L
-#include <ext/numeric_traits.h> // __is_standard_integer, __int_traits
+#include <bits/intcmp.h>
#endif
#if __cplusplus > 202302L
@@ -129,76 +129,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void as_const(const _Tp&&) = delete;
#endif
-#ifdef __cpp_lib_integer_comparison_functions // C++ >= 20
- template<typename _Tp, typename _Up>
- constexpr bool
- cmp_equal(_Tp __t, _Up __u) noexcept
- {
- static_assert(__is_standard_integer<_Tp>::value);
- static_assert(__is_standard_integer<_Up>::value);
-
- if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
- return __t == __u;
- else if constexpr (is_signed_v<_Tp>)
- return __t >= 0 && make_unsigned_t<_Tp>(__t) == __u;
- else
- return __u >= 0 && __t == make_unsigned_t<_Up>(__u);
- }
-
- template<typename _Tp, typename _Up>
- constexpr bool
- cmp_not_equal(_Tp __t, _Up __u) noexcept
- { return !std::cmp_equal(__t, __u); }
-
- template<typename _Tp, typename _Up>
- constexpr bool
- cmp_less(_Tp __t, _Up __u) noexcept
- {
- static_assert(__is_standard_integer<_Tp>::value);
- static_assert(__is_standard_integer<_Up>::value);
-
- if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
- return __t < __u;
- else if constexpr (is_signed_v<_Tp>)
- return __t < 0 || make_unsigned_t<_Tp>(__t) < __u;
- else
- return __u >= 0 && __t < make_unsigned_t<_Up>(__u);
- }
-
- template<typename _Tp, typename _Up>
- constexpr bool
- cmp_greater(_Tp __t, _Up __u) noexcept
- { return std::cmp_less(__u, __t); }
-
- template<typename _Tp, typename _Up>
- constexpr bool
- cmp_less_equal(_Tp __t, _Up __u) noexcept
- { return !std::cmp_less(__u, __t); }
-
- template<typename _Tp, typename _Up>
- constexpr bool
- cmp_greater_equal(_Tp __t, _Up __u) noexcept
- { return !std::cmp_less(__t, __u); }
-
- template<typename _Res, typename _Tp>
- constexpr bool
- in_range(_Tp __t) noexcept
- {
- static_assert(__is_standard_integer<_Res>::value);
- static_assert(__is_standard_integer<_Tp>::value);
- using __gnu_cxx::__int_traits;
-
- if constexpr (is_signed_v<_Tp> == is_signed_v<_Res>)
- return __int_traits<_Res>::__min <= __t
- && __t <= __int_traits<_Res>::__max;
- else if constexpr (is_signed_v<_Tp>)
- return __t >= 0
- && make_unsigned_t<_Tp>(__t) <= __int_traits<_Res>::__max;
- else
- return __t <= make_unsigned_t<_Res>(__int_traits<_Res>::__max);
- }
-#endif // __cpp_lib_integer_comparison_functions
-
#ifdef __cpp_lib_to_underlying // C++ >= 23
/// Convert an object of enumeration type to its underlying type.
template<typename _Tp>
diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant
index 2f44f97..f2f5583 100644
--- a/libstdc++-v3/include/std/variant
+++ b/libstdc++-v3/include/std/variant
@@ -393,8 +393,29 @@ namespace __variant
_Variadic_union(in_place_index_t<_Np>, _Args&&...) = delete;
};
- template<bool __trivially_destructible, typename _First, typename... _Rest>
- union _Variadic_union<__trivially_destructible, _First, _Rest...>
+ template<typename _First, typename... _Rest>
+ union _Variadic_union<true, _First, _Rest...>
+ {
+ constexpr _Variadic_union() : _M_rest() { }
+
+ template<typename... _Args>
+ constexpr
+ _Variadic_union(in_place_index_t<0>, _Args&&... __args)
+ : _M_first(in_place_index<0>, std::forward<_Args>(__args)...)
+ { }
+
+ template<size_t _Np, typename... _Args>
+ constexpr
+ _Variadic_union(in_place_index_t<_Np>, _Args&&... __args)
+ : _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...)
+ { }
+
+ _Uninitialized<_First> _M_first;
+ _Variadic_union<true, _Rest...> _M_rest;
+ };
+
+ template<typename _First, typename... _Rest>
+ union _Variadic_union<false, _First, _Rest...>
{
constexpr _Variadic_union() : _M_rest() { }
@@ -410,24 +431,19 @@ namespace __variant
: _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...)
{ }
-#if __cpp_lib_variant >= 202106L
_Variadic_union(const _Variadic_union&) = default;
_Variadic_union(_Variadic_union&&) = default;
_Variadic_union& operator=(const _Variadic_union&) = default;
_Variadic_union& operator=(_Variadic_union&&) = default;
- ~_Variadic_union() = default;
-
// If any alternative type is not trivially destructible then we need a
// user-provided destructor that does nothing. The active alternative
// will be destroyed by _Variant_storage::_M_reset() instead of here.
- constexpr ~_Variadic_union()
- requires (!__trivially_destructible)
+ _GLIBCXX20_CONSTEXPR ~_Variadic_union()
{ }
-#endif
_Uninitialized<_First> _M_first;
- _Variadic_union<__trivially_destructible, _Rest...> _M_rest;
+ _Variadic_union<(is_trivially_destructible_v<_Rest> && ...), _Rest...> _M_rest;
};
// _Never_valueless_alt is true for variant alternatives that can