public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
* [RFC PATCH] libstdc++: Partial library support for std::float{16,32,64,128}_t
@ 2022-09-27  8:45 Jakub Jelinek
  2022-10-16 10:20 ` [RFC PATCH] libstdc++, v2: " Jakub Jelinek
  0 siblings, 1 reply; 8+ messages in thread
From: Jakub Jelinek @ 2022-09-27  8:45 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: gcc-patches, libstdc++

Hi!

The following patch is partial support for std::float{16,32,64,128}_t
in libstdc++.
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1467r9.html
says that <ostream>, <istream>, <charconv>, <cmath> and <complex>
need changes too, but before doing that, it would be nice to get an
agreement on what macros to use etc.
The support for cmath/complex is possible in multiple ways:
1) glibc >= 2.26 support whatever{f32,f64,f128} APIs next to
   whatever{f,,l} APIs, so I think we can use
   __builtin_sin{f32,f64,f128} etc. to support _Float{32,64,128}
   overloads
2) if not, pretty much everywhere float is actually the same mode as
   _Float32 and double as _Float64, I guess one could use guards like
   #if __FLT32_MANT_DIG__ == __FLT_MANT_DIG__ \
       && __FLT32_MAX_EXP__ == __FLT_MAX_EXP__
   or
   #if __FLT64_MANT_DIG__ == __DBL_MANT_DIG__ \
       && __FLT64_MAX_EXP__ == __DBL_MAX_EXP__
   or even
   #if __FLT128_MANT_DIG__ == __LDBL_MANT_DIG__ \
       && __FLT128_MAX_EXP__ == __LDBL_MAX_EXP__
   for the few arches like aarch64 where long double and _Float128
   has the same mode.  Then we can use
   __builtin_sin{f,,l} etc. to support _Float{32,64,128} overloads
3) not sure what to do as fallback if neither 1) nor 2) work out,
   not provide the overloads, or even undef __STDCPP_FLOAT32_T__
   etc. in the library?
4) AFAIK glibc doesn't have _Float16 APIs, so we need to widen and
   use __builtin_sinf32 1) or __builtin_sinf 2) for _Float16
   and explicitly do narrowing cast
5) bfloat16_t needs more work even on the compiler side, but once
   the support is there and in stdfloat and other headers touched
   by the patch below (testcases already include bfloat16_t though),
   it will need something like 4) too.

The patch also doesn't include any testcases to cover the <type_traits>
changes, it isn't clear to me where to put that.

Tested on x86_64-linux.

2022-09-27  Jakub Jelinek  <jakub@redhat.com>

	* include/std/stdfloat: New file.
	* include/std/numbers (__glibcxx_numbers): Define and use it
	for __float128 explicit instantiations as well as
	_Float{16,32,64,128}.
	* include/std/atomic (atomic<_Float16>, atomic<_Float32>,
	atomic<_Float64>, atomic<_Float128>): New explicit instantiations.
	* include/std/type_traits (__is_floating_point_helper<_Float16>,
	__is_floating_point_helper<_Float32>,
	__is_floating_point_helper<_Float64>,
	__is_floating_point_helper<_Float128>): Likewise.
	* include/std/limits (__glibcxx_concat3_, __glibcxx_concat3,
	__glibcxx_float_n): Define.
	(numeric_limits<_Float16>, numeric_limits<_Float32>,
	numeric_limits<_Float64>, numeric_limits<_Float128>): New explicit
	instantiations.
	* include/Makefile.am (std_headers): Add stdfloat.
	* include/Makefile.in: Regenerated.
	* include/precompiled/stdc++.h: Include stdfloat.
	* testsuite/18_support/headers/stdfloat/types_std.cc: New test.
	* testsuite/18_support/headers/limits/synopsis_cxx23.cc: New test.
	* testsuite/26_numerics/numbers/4.cc: New test.
	* testsuite/29_atomics/atomic_float/requirements_cxx23.cc: New test.

--- libstdc++-v3/include/std/stdfloat.jj	2022-09-27 08:49:45.932769534 +0200
+++ libstdc++-v3/include/std/stdfloat	2022-09-27 08:49:45.932769534 +0200
@@ -0,0 +1,58 @@
+// <stdfloat> -*- C++ -*-
+
+// Copyright (C) 2022 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 include/stdfloat
+ *  This is a Standard C++ Library header.
+ */
+
+#ifndef _GLIBCXX_STDFLOAT
+#define _GLIBCXX_STDFLOAT 1
+
+#if __cplusplus > 202002L
+#include <bits/c++config.h>
+
+namespace std
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  #ifdef __STDCPP_FLOAT16_T__
+  using float16_t = _Float16;
+  #endif
+
+  #ifdef __STDCPP_FLOAT32_T__
+  using float32_t = _Float32;
+  #endif
+
+  #ifdef __STDCPP_FLOAT64_T__
+  using float64_t = _Float64;
+  #endif
+
+  #ifdef __STDCPP_FLOAT128_T__
+  using float128_t = _Float128;
+  #endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // C++23
+#endif // _GLIBCXX_STDFLOAT
--- libstdc++-v3/include/std/numbers.jj	2022-01-11 22:31:41.525756652 +0100
+++ libstdc++-v3/include/std/numbers	2022-09-27 08:49:45.933769521 +0200
@@ -133,72 +133,94 @@ namespace numbers
   inline constexpr double egamma = egamma_v<double>;
   inline constexpr double phi = phi_v<double>;
 
+#define __glibcxx_numbers(TYPE, SUFFIX) \
+  /* e */						\
+  template<>						\
+    inline constexpr TYPE e_v<TYPE>			\
+      = 2.718281828459045235360287471352662498##SUFFIX;	\
+							\
+  /* log_2 e */						\
+  template<>						\
+    inline constexpr TYPE log2e_v<TYPE>			\
+      = 1.442695040888963407359924681001892137##SUFFIX;	\
+							\
+  /* log_10 e */					\
+  template<>						\
+    inline constexpr TYPE log10e_v<TYPE>		\
+      = 0.434294481903251827651128918916605082##SUFFIX;	\
+							\
+  /* pi */						\
+  template<>						\
+    inline constexpr TYPE pi_v<TYPE>			\
+      = 3.141592653589793238462643383279502884##SUFFIX;	\
+							\
+  /* 1/pi */						\
+  template<>						\
+    inline constexpr TYPE inv_pi_v<TYPE>		\
+      = 0.318309886183790671537767526745028724##SUFFIX;	\
+							\
+  /* 1/sqrt(pi) */					\
+  template<>						\
+    inline constexpr TYPE inv_sqrtpi_v<TYPE>		\
+      = 0.564189583547756286948079451560772586##SUFFIX;	\
+							\
+  /* log_e 2 */						\
+  template<>						\
+    inline constexpr TYPE ln2_v<TYPE>			\
+      = 0.693147180559945309417232121458176568##SUFFIX;	\
+							\
+  /* log_e 10 */					\
+  template<>						\
+    inline constexpr TYPE ln10_v<TYPE>			\
+      = 2.302585092994045684017991454684364208##SUFFIX;	\
+							\
+  /* sqrt(2) */						\
+  template<>						\
+    inline constexpr TYPE sqrt2_v<TYPE>			\
+      = 1.414213562373095048801688724209698079##SUFFIX;	\
+							\
+  /* sqrt(3) */						\
+  template<>						\
+    inline constexpr TYPE sqrt3_v<TYPE>			\
+      = 1.732050807568877293527446341505872367##SUFFIX;	\
+							\
+  /* 1/sqrt(3) */					\
+  template<>						\
+    inline constexpr TYPE inv_sqrt3_v<TYPE>		\
+      = 0.577350269189625764509148780501957456##SUFFIX;	\
+							\
+  /* The Euler-Mascheroni constant */			\
+  template<>						\
+    inline constexpr TYPE egamma_v<TYPE>		\
+      = 0.577215664901532860606512090082402431##SUFFIX;	\
+							\
+  /* The golden ratio, (1+sqrt(5))/2 */			\
+  template<>						\
+    inline constexpr TYPE phi_v<TYPE>			\
+      = 1.618033988749894848204586834365638118##SUFFIX
+
+#ifdef __STDCPP_FLOAT16_T__
+__glibcxx_numbers (_Float16, F16);
+#endif
+
+#ifdef __STDCPP_FLOAT32_T__
+__glibcxx_numbers (_Float32, F32);
+#endif
+
+#ifdef __STDCPP_FLOAT64_T__
+__glibcxx_numbers (_Float64, F64);
+#endif
+
+#ifdef __STDCPP_FLOAT128_T__
+__glibcxx_numbers (_Float128, F128);
+#endif
+
 #if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
-  template<>
-    inline constexpr __float128 e_v<__float128>
-      = 2.718281828459045235360287471352662498Q;
-
-  /// log_2 e
-  template<>
-    inline constexpr __float128 log2e_v<__float128>
-      = 1.442695040888963407359924681001892137Q;
-
-  /// log_10 e
-  template<>
-    inline constexpr __float128 log10e_v<__float128>
-      = 0.434294481903251827651128918916605082Q;
-
-  /// pi
-  template<>
-    inline constexpr __float128 pi_v<__float128>
-      = 3.141592653589793238462643383279502884Q;
-
-  /// 1/pi
-  template<>
-    inline constexpr __float128 inv_pi_v<__float128>
-      = 0.318309886183790671537767526745028724Q;
-
-  /// 1/sqrt(pi)
-  template<>
-    inline constexpr __float128 inv_sqrtpi_v<__float128>
-      = 0.564189583547756286948079451560772586Q;
-
-  /// log_e 2
-  template<>
-    inline constexpr __float128 ln2_v<__float128>
-      = 0.693147180559945309417232121458176568Q;
-
-  /// log_e 10
-  template<>
-    inline constexpr __float128 ln10_v<__float128>
-      = 2.302585092994045684017991454684364208Q;
-
-  /// sqrt(2)
-  template<>
-    inline constexpr __float128 sqrt2_v<__float128>
-      = 1.414213562373095048801688724209698079Q;
-
-  /// sqrt(3)
-  template<>
-    inline constexpr __float128 sqrt3_v<__float128>
-      = 1.732050807568877293527446341505872367Q;
-
-  /// 1/sqrt(3)
-  template<>
-    inline constexpr __float128 inv_sqrt3_v<__float128>
-      = 0.577350269189625764509148780501957456Q;
-
-  /// The Euler-Mascheroni constant
-  template<>
-    inline constexpr __float128 egamma_v<__float128>
-      = 0.577215664901532860606512090082402431Q;
-
-  /// The golden ratio, (1+sqrt(5))/2
-  template<>
-    inline constexpr __float128 phi_v<__float128>
-      = 1.618033988749894848204586834365638118Q;
+__glibcxx_numbers (__float128, Q);
 #endif // USE_FLOAT128
 
+#undef __glibcxx_numbers
+
 } // namespace numbers
 /// @}
 _GLIBCXX_END_NAMESPACE_VERSION
--- libstdc++-v3/include/std/atomic.jj	2022-09-11 22:28:56.375164180 +0200
+++ libstdc++-v3/include/std/atomic	2022-09-27 08:49:45.934769507 +0200
@@ -1625,6 +1625,74 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using __atomic_float<long double>::operator=;
     };
 
+#ifdef __STDCPP_FLOAT16_T__
+  template<>
+    struct atomic<_Float16> : __atomic_float<_Float16>
+    {
+      atomic() noexcept = default;
+
+      constexpr
+      atomic(_Float16 __fp) noexcept : __atomic_float<_Float16>(__fp)
+      { }
+
+      atomic& operator=(const atomic&) volatile = delete;
+      atomic& operator=(const atomic&) = delete;
+
+      using __atomic_float<_Float16>::operator=;
+    };
+#endif
+
+#ifdef __STDCPP_FLOAT32_T__
+  template<>
+    struct atomic<_Float32> : __atomic_float<_Float32>
+    {
+      atomic() noexcept = default;
+
+      constexpr
+      atomic(_Float32 __fp) noexcept : __atomic_float<_Float32>(__fp)
+      { }
+
+      atomic& operator=(const atomic&) volatile = delete;
+      atomic& operator=(const atomic&) = delete;
+
+      using __atomic_float<_Float32>::operator=;
+    };
+#endif
+
+#ifdef __STDCPP_FLOAT64_T__
+  template<>
+    struct atomic<_Float64> : __atomic_float<_Float64>
+    {
+      atomic() noexcept = default;
+
+      constexpr
+      atomic(_Float64 __fp) noexcept : __atomic_float<_Float64>(__fp)
+      { }
+
+      atomic& operator=(const atomic&) volatile = delete;
+      atomic& operator=(const atomic&) = delete;
+
+      using __atomic_float<_Float64>::operator=;
+    };
+#endif
+
+#ifdef __STDCPP_FLOAT128_T__
+  template<>
+    struct atomic<_Float128> : __atomic_float<_Float128>
+    {
+      atomic() noexcept = default;
+
+      constexpr
+      atomic(_Float128 __fp) noexcept : __atomic_float<_Float128>(__fp)
+      { }
+
+      atomic& operator=(const atomic&) volatile = delete;
+      atomic& operator=(const atomic&) = delete;
+
+      using __atomic_float<_Float128>::operator=;
+    };
+#endif
+
 #define __cpp_lib_atomic_ref 201806L
 
   /// Class template to provide atomic operations on a non-atomic variable.
--- libstdc++-v3/include/std/type_traits.jj	2022-09-25 22:22:03.979596700 +0200
+++ libstdc++-v3/include/std/type_traits	2022-09-27 08:49:45.934769507 +0200
@@ -459,6 +459,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __is_floating_point_helper<long double>
     : public true_type { };
 
+#ifdef __STDCPP_FLOAT16_T__
+  template<>
+    struct __is_floating_point_helper<_Float16>
+    : public true_type { };
+#endif
+
+#ifdef __STDCPP_FLOAT32_T__
+  template<>
+    struct __is_floating_point_helper<_Float32>
+    : public true_type { };
+#endif
+
+#ifdef __STDCPP_FLOAT64_T__
+  template<>
+    struct __is_floating_point_helper<_Float64>
+    : public true_type { };
+#endif
+
+#ifdef __STDCPP_FLOAT128_T__
+  template<>
+    struct __is_floating_point_helper<_Float128>
+    : public true_type { };
+#endif
+
 #if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
   template<>
     struct __is_floating_point_helper<__float128>
--- libstdc++-v3/include/std/limits.jj	2022-01-11 22:31:41.525756652 +0100
+++ libstdc++-v3/include/std/limits	2022-09-27 08:49:45.933769521 +0200
@@ -1890,6 +1890,115 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #undef __glibcxx_long_double_traps
 #undef __glibcxx_long_double_tinyness_before
 
+#if __cplusplus > 202202L
+
+#define __glibcxx_concat3_(P,M,S) P ## M ## S
+#define __glibcxx_concat3(P,M,S) __glibcxx_concat3_ (P,M,S)
+
+#define __glibcxx_float_n(BITSIZE)					\
+  __extension__								\
+  template<>								\
+    struct numeric_limits<_Float##BITSIZE>				\
+    {									\
+      static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true;		\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      min() _GLIBCXX_USE_NOEXCEPT					\
+      { return __glibcxx_concat3 (__FLT, BITSIZE, _MIN__); }		\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      max() _GLIBCXX_USE_NOEXCEPT					\
+      { return __glibcxx_concat3 (__FLT, BITSIZE, _MAX__); }		\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      lowest() noexcept							\
+      { return -__glibcxx_concat3 (__FLT, BITSIZE, _MAX__); }		\
+									\
+      static _GLIBCXX_USE_CONSTEXPR int digits				\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MANT_DIG__);		\
+      static _GLIBCXX_USE_CONSTEXPR int digits10			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _DIG__);			\
+      static _GLIBCXX_USE_CONSTEXPR int max_digits10			\
+	= __glibcxx_max_digits10 (__glibcxx_concat3 (__FLT, BITSIZE,	\
+						     _MANT_DIG__));	\
+      static _GLIBCXX_USE_CONSTEXPR bool is_signed = true;		\
+      static _GLIBCXX_USE_CONSTEXPR bool is_integer = false;		\
+      static _GLIBCXX_USE_CONSTEXPR bool is_exact = false;		\
+      static _GLIBCXX_USE_CONSTEXPR int radix				\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _RADIX__);			\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      epsilon() _GLIBCXX_USE_NOEXCEPT					\
+      { return __glibcxx_concat3 (__FLT, BITSIZE, _EPSILON__); }	\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE 			\
+      round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5F##BITSIZE; }	\
+									\
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MIN_EXP__);		\
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent10			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MIN_10_EXP__);		\
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MAX_EXP__);		\
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent10			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MAX_10_EXP__);		\
+									\
+      static _GLIBCXX_USE_CONSTEXPR bool has_infinity			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _HAS_INFINITY__);		\
+      static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _HAS_QUIET_NAN__);		\
+      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN		\
+	= has_quiet_NaN;						\
+      static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm	\
+	= bool(__glibcxx_concat3 (__FLT, BITSIZE, _HAS_DENORM__))	\
+	  ? denorm_present : denorm_absent;				\
+      static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false;	\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      infinity() _GLIBCXX_USE_NOEXCEPT					\
+      { return __builtin_huge_valf##BITSIZE(); }			\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      quiet_NaN() _GLIBCXX_USE_NOEXCEPT					\
+      { return __builtin_nanf##BITSIZE(""); }				\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      signaling_NaN() _GLIBCXX_USE_NOEXCEPT				\
+      { return __builtin_nansf##BITSIZE(""); }				\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      denorm_min() _GLIBCXX_USE_NOEXCEPT				\
+      { return __glibcxx_concat3 (__FLT, BITSIZE, _DENORM_MIN__); }	\
+									\
+      static _GLIBCXX_USE_CONSTEXPR bool is_iec559			\
+	= as_infinity && has_quiet_NaN && has_denorm == denorm_present;	\
+      static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; 		\
+      static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; 		\
+									\
+      static _GLIBCXX_USE_CONSTEXPR bool traps = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; 	\
+      static _GLIBCXX_USE_CONSTEXPR float_round_style round_style 	\
+	= round_to_nearest; 						\
+    }; 									\
+
+#ifdef __STDCPP_FLOAT16_T__
+__glibcxx_float_n(16)
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+__glibcxx_float_n(32)
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+__glibcxx_float_n(64)
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+__glibcxx_float_n(128)
+#endif
+#undef __glibcxx_float_n
+#undef __glibcxx_concat3
+#undef __glibcxx_concat3_
+
+#endif
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
--- libstdc++-v3/include/Makefile.am.jj	2022-08-10 23:16:41.981479135 +0200
+++ libstdc++-v3/include/Makefile.am	2022-09-27 09:33:16.838564748 +0200
@@ -83,6 +83,7 @@ std_headers = \
 	${std_srcdir}/stack \
 	${std_srcdir}/stacktrace \
 	${std_srcdir}/stdexcept \
+	${std_srcdir}/stdfloat \
 	${std_srcdir}/stop_token \
 	${std_srcdir}/streambuf \
 	${std_srcdir}/string \
--- libstdc++-v3/include/Makefile.in.jj	2022-08-10 23:16:41.982479122 +0200
+++ libstdc++-v3/include/Makefile.in	2022-09-27 09:33:30.089386201 +0200
@@ -441,6 +441,7 @@ std_headers = \
 	${std_srcdir}/stack \
 	${std_srcdir}/stacktrace \
 	${std_srcdir}/stdexcept \
+	${std_srcdir}/stdfloat \
 	${std_srcdir}/stop_token \
 	${std_srcdir}/streambuf \
 	${std_srcdir}/string \
--- libstdc++-v3/include/precompiled/stdc++.h.jj	2022-05-23 21:44:49.094846916 +0200
+++ libstdc++-v3/include/precompiled/stdc++.h	2022-09-27 08:49:45.932769534 +0200
@@ -159,4 +159,5 @@
 # include <stacktrace>
 #endif
 #include <stdatomic.h>
+#include <stdfloat>
 #endif
--- libstdc++-v3/testsuite/18_support/headers/stdfloat/types_std.cc.jj	2022-09-27 08:56:15.806529350 +0200
+++ libstdc++-v3/testsuite/18_support/headers/stdfloat/types_std.cc	2022-09-27 09:26:58.681660524 +0200
@@ -0,0 +1,40 @@
+// { dg-options "-std=gnu++2b" }
+// { dg-do compile { target c++23 } }
+
+// Copyright (C) 2022 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <stdfloat>
+
+namespace gnu
+{
+#if defined(__STDCPP_FLOAT16_T__)
+  typedef std::float16_t t1;
+#endif
+#if defined(__STDCPP_FLOAT32_T__)
+  typedef std::float32_t t2;
+#endif
+#if defined(__STDCPP_FLOAT64_T__)
+  typedef std::float64_t t3;
+#endif
+#if defined(__STDCPP_FLOAT128_T__)
+  typedef std::float128_t t4;
+#endif
+#if defined(__STDCPP_BFLOAT16_T__)
+  typedef std::bfloat16_t t5;
+#endif
+}
--- libstdc++-v3/testsuite/18_support/headers/limits/synopsis_cxx23.cc.jj	2022-09-27 09:00:16.815274177 +0200
+++ libstdc++-v3/testsuite/18_support/headers/limits/synopsis_cxx23.cc	2022-09-27 09:26:44.055857783 +0200
@@ -0,0 +1,43 @@
+// { dg-options "-std=gnu++2b" }
+// { dg-do compile { target c++23 } }
+// { dg-require-normal-namespace "" }
+
+// Copyright (C) 2022 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <limits>
+#include <stdfloat>
+
+namespace std {
+  template<class T> class numeric_limits;
+
+#if defined(__STDCPP_FLOAT16_T__)
+  template<> class numeric_limits<float16_t>;
+#endif
+#if defined(__STDCPP_FLOAT32_T__)
+  template<> class numeric_limits<float32_t>;
+#endif
+#if defined(__STDCPP_FLOAT64_T__)
+  template<> class numeric_limits<float64_t>;
+#endif
+#if defined(__STDCPP_FLOAT128_T__)
+  template<> class numeric_limits<float128_t>;
+#endif
+#if defined(__STDCPP_BFLOAT16_T__)
+  template<> class numeric_limits<bfloat16_t>;
+#endif
+}
--- libstdc++-v3/testsuite/26_numerics/numbers/4.cc.jj	2022-09-27 09:04:07.578159213 +0200
+++ libstdc++-v3/testsuite/26_numerics/numbers/4.cc	2022-09-27 09:06:44.603039943 +0200
@@ -0,0 +1,122 @@
+// Copyright (C) 2022 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2b" }
+// { dg-do compile { target c++23 } }
+
+#include <numbers>
+#include <stdfloat>
+
+#if defined(__STDCPP_FLOAT16_T__)
+void
+test01()
+{
+  const std::float16_t* d1  = &std::numbers::e_v<std::float16_t>;
+  const std::float16_t* d2  = &std::numbers::log2e_v<std::float16_t>;
+  const std::float16_t* d3  = &std::numbers::log10e_v<std::float16_t>;
+  const std::float16_t* d4  = &std::numbers::pi_v<std::float16_t>;
+  const std::float16_t* d5  = &std::numbers::inv_pi_v<std::float16_t>;
+  const std::float16_t* d6  = &std::numbers::inv_sqrtpi_v<std::float16_t>;
+  const std::float16_t* d7  = &std::numbers::ln2_v<std::float16_t>;
+  const std::float16_t* d8  = &std::numbers::ln10_v<std::float16_t>;
+  const std::float16_t* d9  = &std::numbers::sqrt2_v<std::float16_t>;
+  const std::float16_t* d10 = &std::numbers::sqrt3_v<std::float16_t>;
+  const std::float16_t* d11 = &std::numbers::inv_sqrt3_v<std::float16_t>;
+  const std::float16_t* d12 = &std::numbers::egamma_v<std::float16_t>;
+  const std::float16_t* d13 = &std::numbers::phi_v<std::float16_t>;
+}
+#endif
+
+#if defined(__STDCPP_FLOAT32_T__)
+void
+test02()
+{
+  const std::float32_t* d1  = &std::numbers::e_v<std::float32_t>;
+  const std::float32_t* d2  = &std::numbers::log2e_v<std::float32_t>;
+  const std::float32_t* d3  = &std::numbers::log10e_v<std::float32_t>;
+  const std::float32_t* d4  = &std::numbers::pi_v<std::float32_t>;
+  const std::float32_t* d5  = &std::numbers::inv_pi_v<std::float32_t>;
+  const std::float32_t* d6  = &std::numbers::inv_sqrtpi_v<std::float32_t>;
+  const std::float32_t* d7  = &std::numbers::ln2_v<std::float32_t>;
+  const std::float32_t* d8  = &std::numbers::ln10_v<std::float32_t>;
+  const std::float32_t* d9  = &std::numbers::sqrt2_v<std::float32_t>;
+  const std::float32_t* d10 = &std::numbers::sqrt3_v<std::float32_t>;
+  const std::float32_t* d11 = &std::numbers::inv_sqrt3_v<std::float32_t>;
+  const std::float32_t* d12 = &std::numbers::egamma_v<std::float32_t>;
+  const std::float32_t* d13 = &std::numbers::phi_v<std::float32_t>;
+}
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__)
+void
+test03()
+{
+  const std::float64_t* d1  = &std::numbers::e_v<std::float64_t>;
+  const std::float64_t* d2  = &std::numbers::log2e_v<std::float64_t>;
+  const std::float64_t* d3  = &std::numbers::log10e_v<std::float64_t>;
+  const std::float64_t* d4  = &std::numbers::pi_v<std::float64_t>;
+  const std::float64_t* d5  = &std::numbers::inv_pi_v<std::float64_t>;
+  const std::float64_t* d6  = &std::numbers::inv_sqrtpi_v<std::float64_t>;
+  const std::float64_t* d7  = &std::numbers::ln2_v<std::float64_t>;
+  const std::float64_t* d8  = &std::numbers::ln10_v<std::float64_t>;
+  const std::float64_t* d9  = &std::numbers::sqrt2_v<std::float64_t>;
+  const std::float64_t* d10 = &std::numbers::sqrt3_v<std::float64_t>;
+  const std::float64_t* d11 = &std::numbers::inv_sqrt3_v<std::float64_t>;
+  const std::float64_t* d12 = &std::numbers::egamma_v<std::float64_t>;
+  const std::float64_t* d13 = &std::numbers::phi_v<std::float64_t>;
+}
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__)
+void
+test04()
+{
+  const std::float128_t* d1  = &std::numbers::e_v<std::float128_t>;
+  const std::float128_t* d2  = &std::numbers::log2e_v<std::float128_t>;
+  const std::float128_t* d3  = &std::numbers::log10e_v<std::float128_t>;
+  const std::float128_t* d4  = &std::numbers::pi_v<std::float128_t>;
+  const std::float128_t* d5  = &std::numbers::inv_pi_v<std::float128_t>;
+  const std::float128_t* d6  = &std::numbers::inv_sqrtpi_v<std::float128_t>;
+  const std::float128_t* d7  = &std::numbers::ln2_v<std::float128_t>;
+  const std::float128_t* d8  = &std::numbers::ln10_v<std::float128_t>;
+  const std::float128_t* d9  = &std::numbers::sqrt2_v<std::float128_t>;
+  const std::float128_t* d10 = &std::numbers::sqrt3_v<std::float128_t>;
+  const std::float128_t* d11 = &std::numbers::inv_sqrt3_v<std::float128_t>;
+  const std::float128_t* d12 = &std::numbers::egamma_v<std::float128_t>;
+  const std::float128_t* d13 = &std::numbers::phi_v<std::float128_t>;
+}
+#endif
+
+#if defined(__STDCPP_BFLOAT16_T__)
+void
+test05()
+{
+  const std::bfloat16_t* d1  = &std::numbers::e_v<std::bfloat16_t>;
+  const std::bfloat16_t* d2  = &std::numbers::log2e_v<std::bfloat16_t>;
+  const std::bfloat16_t* d3  = &std::numbers::log10e_v<std::bfloat16_t>;
+  const std::bfloat16_t* d4  = &std::numbers::pi_v<std::bfloat16_t>;
+  const std::bfloat16_t* d5  = &std::numbers::inv_pi_v<std::bfloat16_t>;
+  const std::bfloat16_t* d6  = &std::numbers::inv_sqrtpi_v<std::bfloat16_t>;
+  const std::bfloat16_t* d7  = &std::numbers::ln2_v<std::bfloat16_t>;
+  const std::bfloat16_t* d8  = &std::numbers::ln10_v<std::bfloat16_t>;
+  const std::bfloat16_t* d9  = &std::numbers::sqrt2_v<std::bfloat16_t>;
+  const std::bfloat16_t* d10 = &std::numbers::sqrt3_v<std::bfloat16_t>;
+  const std::bfloat16_t* d11 = &std::numbers::inv_sqrt3_v<std::bfloat16_t>;
+  const std::bfloat16_t* d12 = &std::numbers::egamma_v<std::bfloat16_t>;
+  const std::bfloat16_t* d13 = &std::numbers::phi_v<std::bfloat16_t>;
+}
+#endif
--- libstdc++-v3/testsuite/29_atomics/atomic_float/requirements_cxx23.cc.jj	2022-09-27 09:14:12.423997581 +0200
+++ libstdc++-v3/testsuite/29_atomics/atomic_float/requirements_cxx23.cc	2022-09-27 09:16:26.005195519 +0200
@@ -0,0 +1,112 @@
+// Copyright (C) 2022 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2b" }
+// { dg-do compile { target c++23 } }
+
+#include <atomic>
+#include <stdfloat>
+
+#if defined(__STDCPP_FLOAT16_T__)
+void
+test01()
+{
+  using A = std::atomic<std::float16_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::float16_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif
+
+#if defined(__STDCPP_FLOAT32_T__)
+void
+test02()
+{
+  using A = std::atomic<std::float32_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::float32_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__)
+void
+test03()
+{
+  using A = std::atomic<std::float64_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::float64_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__)
+void
+test04()
+{
+  using A = std::atomic<std::float128_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::float128_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif
+
+#if defined(__STDCPP_BFLOAT16_T__)
+void
+test05()
+{
+  using A = std::atomic<std::bfloat16_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::bfloat16_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif

	Jakub


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [RFC PATCH] libstdc++, v2: Partial library support for std::float{16,32,64,128}_t
  2022-09-27  8:45 [RFC PATCH] libstdc++: Partial library support for std::float{16,32,64,128}_t Jakub Jelinek
@ 2022-10-16 10:20 ` Jakub Jelinek
  2022-10-17 13:07   ` Jonathan Wakely
  0 siblings, 1 reply; 8+ messages in thread
From: Jakub Jelinek @ 2022-10-16 10:20 UTC (permalink / raw)
  To: Jonathan Wakely, libstdc++, gcc-patches

Hi!

As the __bf16 support is now in at least on x86_64/i686, I've
updated my patch to cover bfloat16_t as well and implemented almost
everything for <cmath> - the only thing missing I'm aware of is
std::nextafter std::float16_t and std::bfloat16_t overloads (I think
we probably need to implement that out of line somewhere, or inline? - might
need inline asm barriers) and std::nexttoward overloads (those are
intentional, you said there is a LWG issue about that).
If you want to have <cmath> done in a different way, e.g. the patch
groups a lot of different function overloads by the floating point type,
is that ok or do you want to have them one function at a time for all types,
then next?
I could try to handle <complex> too, but am kind of lost there.
The paper dropped the explicit std::complex specializations, can they stay
around as is and should new overloads be added for the
_Float*/__gnu_cxx::__bfloat16_t types?
And I/O etc. support is missing, not sure I'm able to handle that and if it
is e.g. possible to keep that support out of libstdc++.so.6, because what
extended floating point types one has on a particular arch could change over
time (I mean e.g. bfloat16_t support or float16_t support can be added
etc.).

Bootstrapped/regtested on x86_64-linux and i686-linux.

2022-10-15  Jakub Jelinek  <jakub@redhat.com>

	* include/std/stdfloat: New file.
	* include/std/numbers (__glibcxx_numbers): Define and use it
	for __float128 explicit instantiations as well as
	_Float{16,32,64,128} and __gnu_cxx::__bfloat16_t.
	* include/std/atomic (atomic<_Float16>, atomic<_Float32>,
	atomic<_Float64>, atomic<_Float128>, atomic<__gnu_cxx::__bfloat16_t>):
	New explicit instantiations.
	* include/std/type_traits (__is_floating_point_helper<_Float16>,
	__is_floating_point_helper<_Float32>,
	__is_floating_point_helper<_Float64>,
	__is_floating_point_helper<_Float128>,
	__is_floating_point_helper<__gnu_cxx::__bfloat16_t>): Likewise.
	* include/std/limits (__glibcxx_concat3_, __glibcxx_concat3,
	__glibcxx_float_n): Define.
	(numeric_limits<_Float16>, numeric_limits<_Float32>,
	numeric_limits<_Float64>, numeric_limits<_Float128>,
	numeric_limits<__gnu_cxx::__bfloat16_t>): New explicit instantiations.
	* include/bits/std_abs.h (abs): New overloads for
	_Float{16,32,64,128} and __gnu_cxx::__bfloat16_t.
	* include/bits/c++config (_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128): Define
	if long double is IEEE quad.
	(__gnu_cxx::__bfloat16_t): New using.
	* include/c_global/cmath (acos, asin, atan, atan2, ceil, cos, cosh,
	exp, fabs, floor, fmod, frexp, ldexp, log, log10, modf, pow, sin,
	sinh, sqrt, tan, tanh, fpclassify, isfinite, isinf, isnan, isnormal,
	signbit, isgreater, isgreaterequal, isless, islessequal,
	islessgreater, isunordered, acosh, asinh, atanh, cbrt, copysign, erf,
	erfc, exp2, expm1, fdim, fma, fmax, fmin, hypot, ilogb, lgamma,
	llrint, llround, log1p, log2, logb, lrint, lround, nearbyint,
	nextafter, remainder, rint, round, scalbln, scalbn, tgamma, trunc,
	lerp): New overloads with _Float{16,32,64,128} or
	__gnu_cxx::__bfloat16_t types.
	* config/os/gnu-linux/os_defines.h (_GLIBCXX_HAVE_FLOAT128_MATH):
	Define if glibc 2.26 and later implements *f128 APIs.
	* include/ext/type_traits.h (__promote<_Float16>, __promote<_Float32>,
	__promote<_Float64>, __promote<_Float128>,
	__promote<__gnu_cxx::__bfloat16_t>): New specializations.
	* include/Makefile.am (std_headers): Add stdfloat.
	* include/Makefile.in: Regenerated.
	* include/precompiled/stdc++.h: Include stdfloat.
	* testsuite/18_support/headers/stdfloat/types_std.cc: New test.
	* testsuite/18_support/headers/limits/synopsis_cxx23.cc: New test.
	* testsuite/26_numerics/headers/cmath/c99_classification_macros_c++23.cc:
	New test.
	* testsuite/26_numerics/headers/cmath/functions_std_c++23.cc: New test.
	* testsuite/26_numerics/numbers/4.cc: New test.
	* testsuite/29_atomics/atomic_float/requirements_cxx23.cc: New test.

--- libstdc++-v3/include/std/stdfloat.jj	2022-10-14 22:32:55.409346491 +0200
+++ libstdc++-v3/include/std/stdfloat	2022-10-14 22:32:55.408346505 +0200
@@ -0,0 +1,62 @@
+// <stdfloat> -*- C++ -*-
+
+// Copyright (C) 2022 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 include/stdfloat
+ *  This is a Standard C++ Library header.
+ */
+
+#ifndef _GLIBCXX_STDFLOAT
+#define _GLIBCXX_STDFLOAT 1
+
+#if __cplusplus > 202002L
+#include <bits/c++config.h>
+
+namespace std
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  #ifdef __STDCPP_FLOAT16_T__
+  using float16_t = _Float16;
+  #endif
+
+  #ifdef __STDCPP_FLOAT32_T__
+  using float32_t = _Float32;
+  #endif
+
+  #ifdef __STDCPP_FLOAT64_T__
+  using float64_t = _Float64;
+  #endif
+
+  #ifdef __STDCPP_FLOAT128_T__
+  using float128_t = _Float128;
+  #endif
+
+  #ifdef __STDCPP_BFLOAT16_T__
+  using bfloat16_t = __gnu_cxx::__bfloat16_t;
+  #endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // C++23
+#endif // _GLIBCXX_STDFLOAT
--- libstdc++-v3/include/std/numbers.jj	2022-09-29 22:16:25.227338468 +0200
+++ libstdc++-v3/include/std/numbers	2022-10-14 22:32:55.409346491 +0200
@@ -133,72 +133,98 @@ namespace numbers
   inline constexpr double egamma = egamma_v<double>;
   inline constexpr double phi = phi_v<double>;
 
+#define __glibcxx_numbers(TYPE, SUFFIX) \
+  /* e */						\
+  template<>						\
+    inline constexpr TYPE e_v<TYPE>			\
+      = 2.718281828459045235360287471352662498##SUFFIX;	\
+							\
+  /* log_2 e */						\
+  template<>						\
+    inline constexpr TYPE log2e_v<TYPE>			\
+      = 1.442695040888963407359924681001892137##SUFFIX;	\
+							\
+  /* log_10 e */					\
+  template<>						\
+    inline constexpr TYPE log10e_v<TYPE>		\
+      = 0.434294481903251827651128918916605082##SUFFIX;	\
+							\
+  /* pi */						\
+  template<>						\
+    inline constexpr TYPE pi_v<TYPE>			\
+      = 3.141592653589793238462643383279502884##SUFFIX;	\
+							\
+  /* 1/pi */						\
+  template<>						\
+    inline constexpr TYPE inv_pi_v<TYPE>		\
+      = 0.318309886183790671537767526745028724##SUFFIX;	\
+							\
+  /* 1/sqrt(pi) */					\
+  template<>						\
+    inline constexpr TYPE inv_sqrtpi_v<TYPE>		\
+      = 0.564189583547756286948079451560772586##SUFFIX;	\
+							\
+  /* log_e 2 */						\
+  template<>						\
+    inline constexpr TYPE ln2_v<TYPE>			\
+      = 0.693147180559945309417232121458176568##SUFFIX;	\
+							\
+  /* log_e 10 */					\
+  template<>						\
+    inline constexpr TYPE ln10_v<TYPE>			\
+      = 2.302585092994045684017991454684364208##SUFFIX;	\
+							\
+  /* sqrt(2) */						\
+  template<>						\
+    inline constexpr TYPE sqrt2_v<TYPE>			\
+      = 1.414213562373095048801688724209698079##SUFFIX;	\
+							\
+  /* sqrt(3) */						\
+  template<>						\
+    inline constexpr TYPE sqrt3_v<TYPE>			\
+      = 1.732050807568877293527446341505872367##SUFFIX;	\
+							\
+  /* 1/sqrt(3) */					\
+  template<>						\
+    inline constexpr TYPE inv_sqrt3_v<TYPE>		\
+      = 0.577350269189625764509148780501957456##SUFFIX;	\
+							\
+  /* The Euler-Mascheroni constant */			\
+  template<>						\
+    inline constexpr TYPE egamma_v<TYPE>		\
+      = 0.577215664901532860606512090082402431##SUFFIX;	\
+							\
+  /* The golden ratio, (1+sqrt(5))/2 */			\
+  template<>						\
+    inline constexpr TYPE phi_v<TYPE>			\
+      = 1.618033988749894848204586834365638118##SUFFIX
+
+#ifdef __STDCPP_FLOAT16_T__
+__glibcxx_numbers (_Float16, F16);
+#endif
+
+#ifdef __STDCPP_FLOAT32_T__
+__glibcxx_numbers (_Float32, F32);
+#endif
+
+#ifdef __STDCPP_FLOAT64_T__
+__glibcxx_numbers (_Float64, F64);
+#endif
+
+#ifdef __STDCPP_FLOAT128_T__
+__glibcxx_numbers (_Float128, F128);
+#endif
+
+#ifdef __STDCPP_BFLOAT128_T__
+__glibcxx_numbers (__gnu_cxx::__bfloat16_t, BF16);
+#endif
+
 #if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
-  template<>
-    inline constexpr __float128 e_v<__float128>
-      = 2.718281828459045235360287471352662498Q;
-
-  /// log_2 e
-  template<>
-    inline constexpr __float128 log2e_v<__float128>
-      = 1.442695040888963407359924681001892137Q;
-
-  /// log_10 e
-  template<>
-    inline constexpr __float128 log10e_v<__float128>
-      = 0.434294481903251827651128918916605082Q;
-
-  /// pi
-  template<>
-    inline constexpr __float128 pi_v<__float128>
-      = 3.141592653589793238462643383279502884Q;
-
-  /// 1/pi
-  template<>
-    inline constexpr __float128 inv_pi_v<__float128>
-      = 0.318309886183790671537767526745028724Q;
-
-  /// 1/sqrt(pi)
-  template<>
-    inline constexpr __float128 inv_sqrtpi_v<__float128>
-      = 0.564189583547756286948079451560772586Q;
-
-  /// log_e 2
-  template<>
-    inline constexpr __float128 ln2_v<__float128>
-      = 0.693147180559945309417232121458176568Q;
-
-  /// log_e 10
-  template<>
-    inline constexpr __float128 ln10_v<__float128>
-      = 2.302585092994045684017991454684364208Q;
-
-  /// sqrt(2)
-  template<>
-    inline constexpr __float128 sqrt2_v<__float128>
-      = 1.414213562373095048801688724209698079Q;
-
-  /// sqrt(3)
-  template<>
-    inline constexpr __float128 sqrt3_v<__float128>
-      = 1.732050807568877293527446341505872367Q;
-
-  /// 1/sqrt(3)
-  template<>
-    inline constexpr __float128 inv_sqrt3_v<__float128>
-      = 0.577350269189625764509148780501957456Q;
-
-  /// The Euler-Mascheroni constant
-  template<>
-    inline constexpr __float128 egamma_v<__float128>
-      = 0.577215664901532860606512090082402431Q;
-
-  /// The golden ratio, (1+sqrt(5))/2
-  template<>
-    inline constexpr __float128 phi_v<__float128>
-      = 1.618033988749894848204586834365638118Q;
+__glibcxx_numbers (__float128, Q);
 #endif // USE_FLOAT128
 
+#undef __glibcxx_numbers
+
 } // namespace numbers
 /// @}
 _GLIBCXX_END_NAMESPACE_VERSION
--- libstdc++-v3/include/std/atomic.jj	2022-09-29 22:16:25.227338468 +0200
+++ libstdc++-v3/include/std/atomic	2022-10-14 22:32:55.410346477 +0200
@@ -1625,6 +1625,91 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using __atomic_float<long double>::operator=;
     };
 
+#ifdef __STDCPP_FLOAT16_T__
+  template<>
+    struct atomic<_Float16> : __atomic_float<_Float16>
+    {
+      atomic() noexcept = default;
+
+      constexpr
+      atomic(_Float16 __fp) noexcept : __atomic_float<_Float16>(__fp)
+      { }
+
+      atomic& operator=(const atomic&) volatile = delete;
+      atomic& operator=(const atomic&) = delete;
+
+      using __atomic_float<_Float16>::operator=;
+    };
+#endif
+
+#ifdef __STDCPP_FLOAT32_T__
+  template<>
+    struct atomic<_Float32> : __atomic_float<_Float32>
+    {
+      atomic() noexcept = default;
+
+      constexpr
+      atomic(_Float32 __fp) noexcept : __atomic_float<_Float32>(__fp)
+      { }
+
+      atomic& operator=(const atomic&) volatile = delete;
+      atomic& operator=(const atomic&) = delete;
+
+      using __atomic_float<_Float32>::operator=;
+    };
+#endif
+
+#ifdef __STDCPP_FLOAT64_T__
+  template<>
+    struct atomic<_Float64> : __atomic_float<_Float64>
+    {
+      atomic() noexcept = default;
+
+      constexpr
+      atomic(_Float64 __fp) noexcept : __atomic_float<_Float64>(__fp)
+      { }
+
+      atomic& operator=(const atomic&) volatile = delete;
+      atomic& operator=(const atomic&) = delete;
+
+      using __atomic_float<_Float64>::operator=;
+    };
+#endif
+
+#ifdef __STDCPP_FLOAT128_T__
+  template<>
+    struct atomic<_Float128> : __atomic_float<_Float128>
+    {
+      atomic() noexcept = default;
+
+      constexpr
+      atomic(_Float128 __fp) noexcept : __atomic_float<_Float128>(__fp)
+      { }
+
+      atomic& operator=(const atomic&) volatile = delete;
+      atomic& operator=(const atomic&) = delete;
+
+      using __atomic_float<_Float128>::operator=;
+    };
+#endif
+
+#ifdef __STDCPP_BFLOAT16_T__
+  template<>
+    struct atomic<__gnu_cxx::__bfloat16_t> : __atomic_float<__gnu_cxx::__bfloat16_t>
+    {
+      atomic() noexcept = default;
+
+      constexpr
+      atomic(__gnu_cxx::__bfloat16_t __fp) noexcept : __atomic_float<__gnu_cxx::__bfloat16_t>(__fp)
+      { }
+
+      atomic& operator=(const atomic&) volatile = delete;
+      atomic& operator=(const atomic&) = delete;
+
+      using __atomic_float<__gnu_cxx::__bfloat16_t>::operator=;
+    };
+#endif
+
 #define __cpp_lib_atomic_ref 201806L
 
   /// Class template to provide atomic operations on a non-atomic variable.
--- libstdc++-v3/include/std/type_traits.jj	2022-10-11 12:10:42.236890466 +0200
+++ libstdc++-v3/include/std/type_traits	2022-10-14 22:32:55.410346477 +0200
@@ -459,6 +459,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __is_floating_point_helper<long double>
     : public true_type { };
 
+#ifdef __STDCPP_FLOAT16_T__
+  template<>
+    struct __is_floating_point_helper<_Float16>
+    : public true_type { };
+#endif
+
+#ifdef __STDCPP_FLOAT32_T__
+  template<>
+    struct __is_floating_point_helper<_Float32>
+    : public true_type { };
+#endif
+
+#ifdef __STDCPP_FLOAT64_T__
+  template<>
+    struct __is_floating_point_helper<_Float64>
+    : public true_type { };
+#endif
+
+#ifdef __STDCPP_FLOAT128_T__
+  template<>
+    struct __is_floating_point_helper<_Float128>
+    : public true_type { };
+#endif
+
+#ifdef __STDCPP_BFLOAT16_T__
+  template<>
+    struct __is_floating_point_helper<__gnu_cxx::__bfloat16_t>
+    : public true_type { };
+#endif
+
 #if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
   template<>
     struct __is_floating_point_helper<__float128>
--- libstdc++-v3/include/std/limits.jj	2022-10-05 21:23:02.984826675 +0200
+++ libstdc++-v3/include/std/limits	2022-10-14 22:32:55.000000000 +0200
@@ -1890,6 +1890,201 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #undef __glibcxx_long_double_traps
 #undef __glibcxx_long_double_tinyness_before
 
+#if __cplusplus > 202202L
+
+#define __glibcxx_concat3_(P,M,S) P ## M ## S
+#define __glibcxx_concat3(P,M,S) __glibcxx_concat3_ (P,M,S)
+
+#define __glibcxx_float_n(BITSIZE)					\
+  __extension__								\
+  template<>								\
+    struct numeric_limits<_Float##BITSIZE>				\
+    {									\
+      static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true;		\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      min() _GLIBCXX_USE_NOEXCEPT					\
+      { return __glibcxx_concat3 (__FLT, BITSIZE, _MIN__); }		\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      max() _GLIBCXX_USE_NOEXCEPT					\
+      { return __glibcxx_concat3 (__FLT, BITSIZE, _MAX__); }		\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      lowest() noexcept							\
+      { return -__glibcxx_concat3 (__FLT, BITSIZE, _MAX__); }		\
+									\
+      static _GLIBCXX_USE_CONSTEXPR int digits				\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MANT_DIG__);		\
+      static _GLIBCXX_USE_CONSTEXPR int digits10			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _DIG__);			\
+      static _GLIBCXX_USE_CONSTEXPR int max_digits10			\
+	= __glibcxx_max_digits10 (__glibcxx_concat3 (__FLT, BITSIZE,	\
+						     _MANT_DIG__));	\
+      static _GLIBCXX_USE_CONSTEXPR bool is_signed = true;		\
+      static _GLIBCXX_USE_CONSTEXPR bool is_integer = false;		\
+      static _GLIBCXX_USE_CONSTEXPR bool is_exact = false;		\
+      static _GLIBCXX_USE_CONSTEXPR int radix				\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _RADIX__);			\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      epsilon() _GLIBCXX_USE_NOEXCEPT					\
+      { return __glibcxx_concat3 (__FLT, BITSIZE, _EPSILON__); }	\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE 			\
+      round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5F##BITSIZE; }	\
+									\
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MIN_EXP__);		\
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent10			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MIN_10_EXP__);		\
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MAX_EXP__);		\
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent10			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MAX_10_EXP__);		\
+									\
+      static _GLIBCXX_USE_CONSTEXPR bool has_infinity			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _HAS_INFINITY__);		\
+      static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _HAS_QUIET_NAN__);		\
+      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN		\
+	= has_quiet_NaN;						\
+      static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm	\
+	= bool(__glibcxx_concat3 (__FLT, BITSIZE, _HAS_DENORM__))	\
+	  ? denorm_present : denorm_absent;				\
+      static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false;	\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      infinity() _GLIBCXX_USE_NOEXCEPT					\
+      { return __builtin_huge_valf##BITSIZE(); }			\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      quiet_NaN() _GLIBCXX_USE_NOEXCEPT					\
+      { return __builtin_nanf##BITSIZE(""); }				\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      signaling_NaN() _GLIBCXX_USE_NOEXCEPT				\
+      { return __builtin_nansf##BITSIZE(""); }				\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      denorm_min() _GLIBCXX_USE_NOEXCEPT				\
+      { return __glibcxx_concat3 (__FLT, BITSIZE, _DENORM_MIN__); }	\
+									\
+      static _GLIBCXX_USE_CONSTEXPR bool is_iec559			\
+	= as_infinity && has_quiet_NaN && has_denorm == denorm_present;	\
+      static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; 		\
+      static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; 		\
+									\
+      static _GLIBCXX_USE_CONSTEXPR bool traps = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; 	\
+      static _GLIBCXX_USE_CONSTEXPR float_round_style round_style 	\
+	= round_to_nearest; 						\
+    }; 									\
+
+#ifdef __STDCPP_FLOAT16_T__
+__glibcxx_float_n(16)
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+__glibcxx_float_n(32)
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+__glibcxx_float_n(64)
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+__glibcxx_float_n(128)
+#endif
+#undef __glibcxx_float_n
+#undef __glibcxx_concat3
+#undef __glibcxx_concat3_
+
+#ifdef __STDCPP_BFLOAT16_T__
+  __extension__
+  template<>
+    struct numeric_limits<__gnu_cxx::__bfloat16_t>
+    {
+      static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true;
+
+      static _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+      min() _GLIBCXX_USE_NOEXCEPT
+      { return __BFLT16_MIN__; }
+
+      static _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+      max() _GLIBCXX_USE_NOEXCEPT
+      { return __BFLT16_MAX__; }
+
+      static _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+      lowest() noexcept
+      { return -__BFLT16_MAX__; }
+
+      static _GLIBCXX_USE_CONSTEXPR int digits
+	= __BFLT16_MANT_DIG__;
+      static _GLIBCXX_USE_CONSTEXPR int digits10
+	= __BFLT16_DIG__;
+      static _GLIBCXX_USE_CONSTEXPR int max_digits10
+	= __glibcxx_max_digits10 (__BFLT16_MANT_DIG__);
+      static _GLIBCXX_USE_CONSTEXPR bool is_signed = true;
+      static _GLIBCXX_USE_CONSTEXPR bool is_integer = false;
+      static _GLIBCXX_USE_CONSTEXPR bool is_exact = false;
+      static _GLIBCXX_USE_CONSTEXPR int radix
+	= __BFLT16_RADIX__;
+
+      static _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+      epsilon() _GLIBCXX_USE_NOEXCEPT
+      { return __BFLT16_EPSILON__; }
+
+      static _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+      round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5BF16; }
+
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent
+	= __BFLT16_MIN_EXP__;
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent10
+	= __BFLT16_MIN_10_EXP__;
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent
+	= __BFLT16_MAX_EXP__;
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent10
+	= __BFLT16_MAX_10_EXP__;
+
+      static _GLIBCXX_USE_CONSTEXPR bool has_infinity
+	= __BFLT16_HAS_INFINITY__;
+      static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN
+	= __BFLT16_HAS_QUIET_NAN__;
+      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN
+	= has_quiet_NaN;
+      static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm
+	= bool(__BFLT16_HAS_DENORM__)
+	  ? denorm_present : denorm_absent;
+      static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false;
+
+      static _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+      infinity() _GLIBCXX_USE_NOEXCEPT
+      { return __gnu_cxx::__bfloat16_t(__builtin_huge_valf()); }
+
+      static _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+      quiet_NaN() _GLIBCXX_USE_NOEXCEPT
+      { return __gnu_cxx::__bfloat16_t(__builtin_nanf("")); }
+
+      static _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+      signaling_NaN() _GLIBCXX_USE_NOEXCEPT
+      { return __builtin_nansf16b(""); }
+
+      static _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+      denorm_min() _GLIBCXX_USE_NOEXCEPT
+      { return __BFLT16_DENORM_MIN__; }
+
+      static _GLIBCXX_USE_CONSTEXPR bool is_iec559
+	= as_infinity && has_quiet_NaN && has_denorm == denorm_present;
+      static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true;
+      static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false;
+
+      static _GLIBCXX_USE_CONSTEXPR bool traps = false;
+      static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false;
+      static _GLIBCXX_USE_CONSTEXPR float_round_style round_style
+	= round_to_nearest;
+    };
+#endif
+
+#endif
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
--- libstdc++-v3/include/bits/std_abs.h.jj	2022-01-11 22:31:41.490757144 +0100
+++ libstdc++-v3/include/bits/std_abs.h	2022-10-14 22:32:55.411346463 +0200
@@ -97,6 +97,40 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   abs(__GLIBCXX_TYPE_INT_N_3 __x) { return __x >= 0 ? __x : -__x; }
 #endif
 
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  inline _GLIBCXX_CONSTEXPR _Float16
+  abs(_Float16 __x)
+  { return _Float16(__builtin_fabsf(__x)); }
+#endif
+
+#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  inline _GLIBCXX_CONSTEXPR _Float32
+  abs(_Float32 __x)
+  { return __builtin_fabsf(__x); }
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+  inline _GLIBCXX_CONSTEXPR _Float64
+  abs(_Float64 __x)
+  { return __builtin_fabs(__x); }
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128)
+  inline _GLIBCXX_CONSTEXPR _Float128
+  abs(_Float128 __x)
+  { return __builtin_fabsl(__x); }
+#elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH)
+  inline _GLIBCXX_CONSTEXPR _Float128
+  abs(_Float128 __x)
+  { return __builtin_fabsf128(__x); }
+#endif
+
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  abs(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_fabsf(__x)); }
+#endif
+
 #if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
   __extension__ inline _GLIBCXX_CONSTEXPR
   __float128
--- libstdc++-v3/include/bits/c++config.jj	2022-05-23 21:44:49.082847038 +0200
+++ libstdc++-v3/include/bits/c++config	2022-10-14 22:32:55.411346463 +0200
@@ -1,4 +1,4 @@
-// Predefined symbols and macros -*- C++ -*-
+	// Predefined symbols and macros -*- C++ -*-
 
 // Copyright (C) 1997-2022 Free Software Foundation, Inc.
 //
@@ -796,6 +796,20 @@ namespace std
 # define _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 1
 #endif
 
+// Define if long double has the IEEE binary128 format.
+#if __LDBL_MANT_DIG__ == 113 \
+  && __LDBL_MIN_EXP__ == -16381 \
+  && __LDBL_MAX_EXP__ == 16384
+# define _GLIBCXX_LDOUBLE_IS_IEEE_BINARY128 1
+#endif
+
+#ifdef __STDCPP_BFLOAT16_T__
+namespace __gnu_cxx
+{
+  using __bfloat16_t = decltype(0.0bf16);
+}
+#endif
+
 #ifdef __has_builtin
 # ifdef __is_identifier
 // Intel and older Clang require !__is_identifier for some built-ins:
--- libstdc++-v3/include/c_global/cmath.jj	2022-10-03 22:45:46.093435123 +0200
+++ libstdc++-v3/include/c_global/cmath	2022-10-14 22:32:55.412346449 +0200
@@ -515,6 +515,564 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     tanh(_Tp __x)
     { return __builtin_tanh(__x); }
 
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  inline _GLIBCXX_CONSTEXPR _Float16
+  acos(_Float16 __x)
+  { return _Float16(__builtin_acosf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR _Float16
+  asin(_Float16 __x)
+  { return _Float16(__builtin_asinf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR _Float16
+  atan(_Float16 __x)
+  { return _Float16(__builtin_atanf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR _Float16
+  atan2(_Float16 __y, _Float16 __x)
+  { return _Float16(__builtin_atan2f(__y, __x)); }
+
+  inline _GLIBCXX_CONSTEXPR _Float16
+  ceil(_Float16 __x)
+  { return _Float16(__builtin_ceilf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR _Float16
+  cos(_Float16 __x)
+  { return _Float16(__builtin_cosf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR _Float16
+  cosh(_Float16 __x)
+  { return _Float16(__builtin_coshf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR _Float16
+  exp(_Float16 __x)
+  { return _Float16(__builtin_expf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR _Float16
+  fabs(_Float16 __x)
+  { return _Float16(__builtin_fabsf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR _Float16
+  floor(_Float16 __x)
+  { return _Float16(__builtin_floorf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR _Float16
+  fmod(_Float16 __x, _Float16 __y)
+  { return _Float16(__builtin_fmodf(__x, __y)); }
+
+  inline _Float16
+  frexp(_Float16 __x, int* __exp)
+  { return _Float16(__builtin_frexpf(__x, __exp)); }
+
+  inline _GLIBCXX_CONSTEXPR _Float16
+  ldexp(_Float16 __x, int __exp)
+  { return _Float16(__builtin_ldexpf(__x, __exp)); }
+
+  inline _GLIBCXX_CONSTEXPR _Float16
+  log(_Float16 __x)
+  { return _Float16(__builtin_logf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR _Float16
+  log10(_Float16 __x)
+  { return _Float16(__builtin_log10f(__x)); }
+
+  inline _Float16
+  modf(_Float16 __x, _Float16* __iptr)
+  {
+    float __i, __ret = __builtin_modff(__x, &__i);
+    *__iptr = _Float16(__i);
+    return _Float16(__ret);
+  }
+
+  inline _GLIBCXX_CONSTEXPR _Float16
+  pow(_Float16 __x, _Float16 __y)
+  { return _Float16(__builtin_powf(__x, __y)); }
+
+  inline _GLIBCXX_CONSTEXPR _Float16
+  sin(_Float16 __x)
+  { return _Float16(__builtin_sinf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR _Float16
+  sinh(_Float16 __x)
+  { return _Float16(__builtin_sinhf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR _Float16
+  sqrt(_Float16 __x)
+  { return _Float16(__builtin_sqrtf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR _Float16
+  tan(_Float16 __x)
+  { return _Float16(__builtin_tanf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR _Float16
+  tanh(_Float16 __x)
+  { return _Float16(__builtin_tanhf(__x)); }
+#endif
+
+#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  inline _GLIBCXX_CONSTEXPR _Float32
+  acos(_Float32 __x)
+  { return __builtin_acosf(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float32
+  asin(_Float32 __x)
+  { return __builtin_asinf(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float32
+  atan(_Float32 __x)
+  { return __builtin_atanf(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float32
+  atan2(_Float32 __y, _Float32 __x)
+  { return __builtin_atan2f(__y, __x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float32
+  ceil(_Float32 __x)
+  { return __builtin_ceilf(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float32
+  cos(_Float32 __x)
+  { return __builtin_cosf(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float32
+  cosh(_Float32 __x)
+  { return __builtin_coshf(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float32
+  exp(_Float32 __x)
+  { return __builtin_expf(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float32
+  fabs(_Float32 __x)
+  { return __builtin_fabsf(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float32
+  floor(_Float32 __x)
+  { return __builtin_floorf(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float32
+  fmod(_Float32 __x, _Float32 __y)
+  { return __builtin_fmodf(__x, __y); }
+
+  inline _Float32
+  frexp(_Float32 __x, int* __exp)
+  { return __builtin_frexpf(__x, __exp); }
+
+  inline _GLIBCXX_CONSTEXPR _Float32
+  ldexp(_Float32 __x, int __exp)
+  { return __builtin_ldexpf(__x, __exp); }
+
+  inline _GLIBCXX_CONSTEXPR _Float32
+  log(_Float32 __x)
+  { return __builtin_logf(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float32
+  log10(_Float32 __x)
+  { return __builtin_log10f(__x); }
+
+  inline _Float32
+  modf(_Float32 __x, _Float32* __iptr)
+  {
+    float __i, __ret = __builtin_modff(__x, &__i);
+    *__iptr = __i;
+    return __ret;
+  }
+
+  inline _GLIBCXX_CONSTEXPR _Float32
+  pow(_Float32 __x, _Float32 __y)
+  { return __builtin_powf(__x, __y); }
+
+  inline _GLIBCXX_CONSTEXPR _Float32
+  sin(_Float32 __x)
+  { return __builtin_sinf(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float32
+  sinh(_Float32 __x)
+  { return __builtin_sinhf(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float32
+  sqrt(_Float32 __x)
+  { return __builtin_sqrtf(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float32
+  tan(_Float32 __x)
+  { return __builtin_tanf(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float32
+  tanh(_Float32 __x)
+  { return __builtin_tanhf(__x); }
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+  inline _GLIBCXX_CONSTEXPR _Float64
+  acos(_Float64 __x)
+  { return __builtin_acos(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float64
+  asin(_Float64 __x)
+  { return __builtin_asin(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float64
+  atan(_Float64 __x)
+  { return __builtin_atan(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float64
+  atan2(_Float64 __y, _Float64 __x)
+  { return __builtin_atan2(__y, __x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float64
+  ceil(_Float64 __x)
+  { return __builtin_ceil(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float64
+  cos(_Float64 __x)
+  { return __builtin_cos(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float64
+  cosh(_Float64 __x)
+  { return __builtin_cosh(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float64
+  exp(_Float64 __x)
+  { return __builtin_exp(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float64
+  fabs(_Float64 __x)
+  { return __builtin_fabs(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float64
+  floor(_Float64 __x)
+  { return __builtin_floor(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float64
+  fmod(_Float64 __x, _Float64 __y)
+  { return __builtin_fmod(__x, __y); }
+
+  inline _Float64
+  frexp(_Float64 __x, int* __exp)
+  { return __builtin_frexp(__x, __exp); }
+
+  inline _GLIBCXX_CONSTEXPR _Float64
+  ldexp(_Float64 __x, int __exp)
+  { return __builtin_ldexp(__x, __exp); }
+
+  inline _GLIBCXX_CONSTEXPR _Float64
+  log(_Float64 __x)
+  { return __builtin_log(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float64
+  log10(_Float64 __x)
+  { return __builtin_log10(__x); }
+
+  inline _Float64
+  modf(_Float64 __x, _Float64* __iptr)
+  {
+    double __i, __ret = __builtin_modf(__x, &__i);
+    *__iptr = __i;
+    return __ret;
+  }
+
+  inline _GLIBCXX_CONSTEXPR _Float64
+  pow(_Float64 __x, _Float64 __y)
+  { return __builtin_pow(__x, __y); }
+
+  inline _GLIBCXX_CONSTEXPR _Float64
+  sin(_Float64 __x)
+  { return __builtin_sin(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float64
+  sinh(_Float64 __x)
+  { return __builtin_sinh(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float64
+  sqrt(_Float64 __x)
+  { return __builtin_sqrt(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float64
+  tan(_Float64 __x)
+  { return __builtin_tan(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float64
+  tanh(_Float64 __x)
+  { return __builtin_tanh(__x); }
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128)
+  inline _GLIBCXX_CONSTEXPR _Float128
+  acos(_Float128 __x)
+  { return __builtin_acosl(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  asin(_Float128 __x)
+  { return __builtin_asinl(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  atan(_Float128 __x)
+  { return __builtin_atanl(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  atan2(_Float128 __y, _Float128 __x)
+  { return __builtin_atan2l(__y, __x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  ceil(_Float128 __x)
+  { return __builtin_ceill(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  cos(_Float128 __x)
+  { return __builtin_cosl(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  cosh(_Float128 __x)
+  { return __builtin_coshl(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  exp(_Float128 __x)
+  { return __builtin_expl(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  fabs(_Float128 __x)
+  { return __builtin_fabsl(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  floor(_Float128 __x)
+  { return __builtin_floorl(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  fmod(_Float128 __x, _Float128 __y)
+  { return __builtin_fmodl(__x, __y); }
+
+  inline _Float128
+  frexp(_Float128 __x, int* __exp)
+  { return __builtin_frexpl(__x, __exp); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  ldexp(_Float128 __x, int __exp)
+  { return __builtin_ldexpl(__x, __exp); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  log(_Float128 __x)
+  { return __builtin_logl(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  log10(_Float128 __x)
+  { return __builtin_log10l(__x); }
+
+  inline _Float128
+  modf(_Float128 __x, _Float128* __iptr)
+  {
+    long double __i, __ret = __builtin_modfl(__x, &__i);
+    *__iptr = __i;
+    return __ret;
+  }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  pow(_Float128 __x, _Float128 __y)
+  { return __builtin_powl(__x, __y); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  sin(_Float128 __x)
+  { return __builtin_sinl(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  sinh(_Float128 __x)
+  { return __builtin_sinhl(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  sqrt(_Float128 __x)
+  { return __builtin_sqrtl(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  tan(_Float128 __x)
+  { return __builtin_tanl(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  tanh(_Float128 __x)
+  { return __builtin_tanhl(__x); }
+#elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH)
+  inline _GLIBCXX_CONSTEXPR _Float128
+  acos(_Float128 __x)
+  { return __builtin_acosf128(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  asin(_Float128 __x)
+  { return __builtin_asinf128(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  atan(_Float128 __x)
+  { return __builtin_atanf128(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  atan2(_Float128 __y, _Float128 __x)
+  { return __builtin_atan2f128(__y, __x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  ceil(_Float128 __x)
+  { return __builtin_ceilf128(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  cos(_Float128 __x)
+  { return __builtin_cosf128(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  cosh(_Float128 __x)
+  { return __builtin_coshf128(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  exp(_Float128 __x)
+  { return __builtin_expf128(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  fabs(_Float128 __x)
+  { return __builtin_fabsf128(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  floor(_Float128 __x)
+  { return __builtin_floorf128(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  fmod(_Float128 __x, _Float128 __y)
+  { return __builtin_fmodf128(__x, __y); }
+
+  inline _Float128
+  frexp(_Float128 __x, int* __exp)
+  { return __builtin_frexpf128(__x, __exp); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  ldexp(_Float128 __x, int __exp)
+  { return __builtin_ldexpf128(__x, __exp); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  log(_Float128 __x)
+  { return __builtin_logf128(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  log10(_Float128 __x)
+  { return __builtin_log10f128(__x); }
+
+  inline _Float128
+  modf(_Float128 __x, _Float128* __iptr)
+  { return __builtin_modff128(__x, __iptr); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  pow(_Float128 __x, _Float128 __y)
+  { return __builtin_powf128(__x, __y); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  sin(_Float128 __x)
+  { return __builtin_sinf128(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  sinh(_Float128 __x)
+  { return __builtin_sinhf128(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  sqrt(_Float128 __x)
+  { return __builtin_sqrtf128(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  tan(_Float128 __x)
+  { return __builtin_tanf128(__x); }
+
+  inline _GLIBCXX_CONSTEXPR _Float128
+  tanh(_Float128 __x)
+  { return __builtin_tanhf128(__x); }
+#endif
+
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  acos(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_acosf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  asin(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_asinf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  atan(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_atanf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  atan2(__gnu_cxx::__bfloat16_t __y, __gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_atan2f(__y, __x)); }
+
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  ceil(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_ceilf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  cos(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_cosf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  cosh(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_coshf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  exp(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_expf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  fabs(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_fabsf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  floor(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_floorf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  fmod(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __gnu_cxx::__bfloat16_t(__builtin_fmodf(__x, __y)); }
+
+  inline __gnu_cxx::__bfloat16_t
+  frexp(__gnu_cxx::__bfloat16_t __x, int* __exp)
+  { return __gnu_cxx::__bfloat16_t(__builtin_frexpf(__x, __exp)); }
+
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  ldexp(__gnu_cxx::__bfloat16_t __x, int __exp)
+  { return __gnu_cxx::__bfloat16_t(__builtin_ldexpf(__x, __exp)); }
+
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  log(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_logf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  log10(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_log10f(__x)); }
+
+  inline __gnu_cxx::__bfloat16_t
+  modf(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t* __iptr)
+  {
+    float __i, __ret = __builtin_modff(__x, &__i);
+    *__iptr = __gnu_cxx::__bfloat16_t(__i);
+    return __gnu_cxx::__bfloat16_t(__ret);
+  }
+
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  pow(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __gnu_cxx::__bfloat16_t(__builtin_powf(__x, __y)); }
+
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  sin(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_sinf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  sinh(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_sinhf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  sqrt(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_sqrtf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  tan(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_tanf(__x)); }
+
+  inline _GLIBCXX_CONSTEXPR __gnu_cxx::__bfloat16_t
+  tanh(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_tanhf(__x)); }
+#endif
+
 #if _GLIBCXX_USE_C99_MATH
 #if !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
 
@@ -948,6 +1506,262 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
 #endif // C++11
+
+#ifdef __STDCPP_FLOAT16_T__
+  constexpr int
+  fpclassify(_Float16 __x)
+  { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
+				FP_SUBNORMAL, FP_ZERO, __x); }
+
+  constexpr bool
+  isfinite(_Float16 __x)
+  { return __builtin_isfinite(__x); }
+
+  constexpr bool
+  isinf(_Float16 __x)
+  { return __builtin_isinf(__x); }
+
+  constexpr bool
+  isnan(_Float16 __x)
+  { return __builtin_isnan(__x); }
+
+  constexpr bool
+  isnormal(_Float16 __x)
+  { return __builtin_isnormal(__x); }
+
+  constexpr bool
+  signbit(_Float16 __x)
+  { return __builtin_signbit(__x); }
+
+  constexpr bool
+  isgreater(_Float16 __x, _Float16 __y)
+  { return __builtin_isgreater(__x, __y); }
+
+  constexpr bool
+  isgreaterequal(_Float16 __x, _Float16 __y)
+  { return __builtin_isgreaterequal(__x, __y); }
+
+  constexpr bool
+  isless(_Float16 __x, _Float16 __y)
+  { return __builtin_isless(__x, __y); }
+
+  constexpr bool
+  islessequal(_Float16 __x, _Float16 __y)
+  { return __builtin_islessequal(__x, __y); }
+
+  constexpr bool
+  islessgreater(_Float16 __x, _Float16 __y)
+  { return __builtin_islessgreater(__x, __y); }
+
+  constexpr bool
+  isunordered(_Float16 __x, _Float16 __y)
+  { return __builtin_isunordered(__x, __y); }
+#endif
+
+#ifdef __STDCPP_FLOAT32_T__
+  constexpr int
+  fpclassify(_Float32 __x)
+  { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
+				FP_SUBNORMAL, FP_ZERO, __x); }
+
+  constexpr bool
+  isfinite(_Float32 __x)
+  { return __builtin_isfinite(__x); }
+
+  constexpr bool
+  isinf(_Float32 __x)
+  { return __builtin_isinf(__x); }
+
+  constexpr bool
+  isnan(_Float32 __x)
+  { return __builtin_isnan(__x); }
+
+  constexpr bool
+  isnormal(_Float32 __x)
+  { return __builtin_isnormal(__x); }
+
+  constexpr bool
+  signbit(_Float32 __x)
+  { return __builtin_signbit(__x); }
+
+  constexpr bool
+  isgreater(_Float32 __x, _Float32 __y)
+  { return __builtin_isgreater(__x, __y); }
+
+  constexpr bool
+  isgreaterequal(_Float32 __x, _Float32 __y)
+  { return __builtin_isgreaterequal(__x, __y); }
+
+  constexpr bool
+  isless(_Float32 __x, _Float32 __y)
+  { return __builtin_isless(__x, __y); }
+
+  constexpr bool
+  islessequal(_Float32 __x, _Float32 __y)
+  { return __builtin_islessequal(__x, __y); }
+
+  constexpr bool
+  islessgreater(_Float32 __x, _Float32 __y)
+  { return __builtin_islessgreater(__x, __y); }
+
+  constexpr bool
+  isunordered(_Float32 __x, _Float32 __y)
+  { return __builtin_isunordered(__x, __y); }
+#endif
+
+#ifdef __STDCPP_FLOAT64_T__
+  constexpr int
+  fpclassify(_Float64 __x)
+  { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
+				FP_SUBNORMAL, FP_ZERO, __x); }
+
+  constexpr bool
+  isfinite(_Float64 __x)
+  { return __builtin_isfinite(__x); }
+
+  constexpr bool
+  isinf(_Float64 __x)
+  { return __builtin_isinf(__x); }
+
+  constexpr bool
+  isnan(_Float64 __x)
+  { return __builtin_isnan(__x); }
+
+  constexpr bool
+  isnormal(_Float64 __x)
+  { return __builtin_isnormal(__x); }
+
+  constexpr bool
+  signbit(_Float64 __x)
+  { return __builtin_signbit(__x); }
+
+  constexpr bool
+  isgreater(_Float64 __x, _Float64 __y)
+  { return __builtin_isgreater(__x, __y); }
+
+  constexpr bool
+  isgreaterequal(_Float64 __x, _Float64 __y)
+  { return __builtin_isgreaterequal(__x, __y); }
+
+  constexpr bool
+  isless(_Float64 __x, _Float64 __y)
+  { return __builtin_isless(__x, __y); }
+
+  constexpr bool
+  islessequal(_Float64 __x, _Float64 __y)
+  { return __builtin_islessequal(__x, __y); }
+
+  constexpr bool
+  islessgreater(_Float64 __x, _Float64 __y)
+  { return __builtin_islessgreater(__x, __y); }
+
+  constexpr bool
+  isunordered(_Float64 __x, _Float64 __y)
+  { return __builtin_isunordered(__x, __y); }
+#endif
+
+#ifdef __STDCPP_FLOAT128_T__
+  constexpr int
+  fpclassify(_Float128 __x)
+  { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
+				FP_SUBNORMAL, FP_ZERO, __x); }
+
+  constexpr bool
+  isfinite(_Float128 __x)
+  { return __builtin_isfinite(__x); }
+
+  constexpr bool
+  isinf(_Float128 __x)
+  { return __builtin_isinf(__x); }
+
+  constexpr bool
+  isnan(_Float128 __x)
+  { return __builtin_isnan(__x); }
+
+  constexpr bool
+  isnormal(_Float128 __x)
+  { return __builtin_isnormal(__x); }
+
+  constexpr bool
+  signbit(_Float128 __x)
+  { return __builtin_signbit(__x); }
+
+  constexpr bool
+  isgreater(_Float128 __x, _Float128 __y)
+  { return __builtin_isgreater(__x, __y); }
+
+  constexpr bool
+  isgreaterequal(_Float128 __x, _Float128 __y)
+  { return __builtin_isgreaterequal(__x, __y); }
+
+  constexpr bool
+  isless(_Float128 __x, _Float128 __y)
+  { return __builtin_isless(__x, __y); }
+
+  constexpr bool
+  islessequal(_Float128 __x, _Float128 __y)
+  { return __builtin_islessequal(__x, __y); }
+
+  constexpr bool
+  islessgreater(_Float128 __x, _Float128 __y)
+  { return __builtin_islessgreater(__x, __y); }
+
+  constexpr bool
+  isunordered(_Float128 __x, _Float128 __y)
+  { return __builtin_isunordered(__x, __y); }
+#endif
+
+#ifdef __STDCPP_BFLOAT16_T__
+  constexpr int
+  fpclassify(__gnu_cxx::__bfloat16_t __x)
+  { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
+				FP_SUBNORMAL, FP_ZERO, __x); }
+
+  constexpr bool
+  isfinite(__gnu_cxx::__bfloat16_t __x)
+  { return __builtin_isfinite(__x); }
+
+  constexpr bool
+  isinf(__gnu_cxx::__bfloat16_t __x)
+  { return __builtin_isinf(__x); }
+
+  constexpr bool
+  isnan(__gnu_cxx::__bfloat16_t __x)
+  { return __builtin_isnan(__x); }
+
+  constexpr bool
+  isnormal(__gnu_cxx::__bfloat16_t __x)
+  { return __builtin_isnormal(__x); }
+
+  constexpr bool
+  signbit(__gnu_cxx::__bfloat16_t __x)
+  { return __builtin_signbit(__x); }
+
+  constexpr bool
+  isgreater(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __builtin_isgreater(__x, __y); }
+
+  constexpr bool
+  isgreaterequal(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __builtin_isgreaterequal(__x, __y); }
+
+  constexpr bool
+  isless(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __builtin_isless(__x, __y); }
+
+  constexpr bool
+  islessequal(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __builtin_islessequal(__x, __y); }
+
+  constexpr bool
+  islessgreater(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __builtin_islessgreater(__x, __y); }
+
+  constexpr bool
+  isunordered(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __builtin_isunordered(__x, __y); }
+#endif
+
 #endif /* _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC */
 #endif /* _GLIBCXX_USE_C99_MATH */
 
@@ -1843,6 +2657,811 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { return __builtin_trunc(__x); }
 #endif
 
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  constexpr _Float16
+  acosh(_Float16 __x)
+  { return _Float16(__builtin_acoshf(__x)); }
+
+  constexpr _Float16
+  asinh(_Float16 __x)
+  { return _Float16(__builtin_asinhf(__x)); }
+
+  constexpr _Float16
+  atanh(_Float16 __x)
+  { return _Float16(__builtin_atanhf(__x)); }
+
+  constexpr _Float16
+  cbrt(_Float16 __x)
+  { return _Float16(__builtin_cbrtf(__x)); }
+
+  constexpr _Float16
+  copysign(_Float16 __x, _Float16 __y)
+  { return __builtin_copysignf16(__x, __y); }
+
+  constexpr _Float16
+  erf(_Float16 __x)
+  { return _Float16(__builtin_erff(__x)); }
+
+  constexpr _Float16
+  erfc(_Float16 __x)
+  { return _Float16(__builtin_erfcf(__x)); }
+
+  constexpr _Float16
+  exp2(_Float16 __x)
+  { return _Float16(__builtin_exp2f(__x)); }
+
+  constexpr _Float16
+  expm1(_Float16 __x)
+  { return _Float16(__builtin_expm1f(__x)); }
+
+  constexpr _Float16
+  fdim(_Float16 __x, _Float16 __y)
+  { return _Float16(__builtin_fdimf(__x, __y)); }
+
+  constexpr _Float16
+  fma(_Float16 __x, _Float16 __y, _Float16 __z)
+  { return _Float16(__builtin_fmaf(__x, __y, __z)); }
+
+  constexpr _Float16
+  fmax(_Float16 __x, _Float16 __y)
+  { return _Float16(__builtin_fmaxf(__x, __y)); }
+
+  constexpr _Float16
+  fmin(_Float16 __x, _Float16 __y)
+  { return _Float16(__builtin_fminf(__x, __y)); }
+
+  constexpr _Float16
+  hypot(_Float16 __x, _Float16 __y)
+  { return _Float16(__builtin_hypotf(__x, __y)); }
+
+  constexpr int
+  ilogb(_Float16 __x)
+  { return _Float16(__builtin_ilogbf(__x)); }
+
+  constexpr _Float16
+  lgamma(_Float16 __x)
+  { return _Float16(__builtin_lgammaf(__x)); }
+
+  constexpr long long
+  llrint(_Float16 __x)
+  { return _Float16(__builtin_llrintf(__x)); }
+
+  constexpr long long
+  llround(_Float16 __x)
+  { return _Float16(__builtin_llroundf(__x)); }
+
+  constexpr _Float16
+  log1p(_Float16 __x)
+  { return _Float16(__builtin_log1pf(__x)); }
+
+  // DR 568.
+  constexpr _Float16
+  log2(_Float16 __x)
+  { return _Float16(__builtin_log2f(__x)); }
+
+  constexpr _Float16
+  logb(_Float16 __x)
+  { return _Float16(__builtin_logbf(__x)); }
+
+  constexpr long
+  lrint(_Float16 __x)
+  { return _Float16(__builtin_lrintf(__x)); }
+
+  constexpr long
+  lround(_Float16 __x)
+  { return _Float16(__builtin_lroundf(__x)); }
+
+  constexpr _Float16
+  nearbyint(_Float16 __x)
+  { return _Float16(__builtin_nearbyintf(__x)); }
+
+  // nextafter not implemented so far.
+
+  constexpr _Float16
+  remainder(_Float16 __x, _Float16 __y)
+  { return _Float16(__builtin_remainderf(__x, __y)); }
+
+  inline _Float16
+  remquo(_Float16 __x, _Float16 __y, int* __pquo)
+  { return _Float16(__builtin_remquof(__x, __y, __pquo)); }
+
+  constexpr _Float16
+  rint(_Float16 __x)
+  { return _Float16(__builtin_rintf(__x)); }
+
+  constexpr _Float16
+  round(_Float16 __x)
+  { return _Float16(__builtin_roundf(__x)); }
+
+  constexpr _Float16
+  scalbln(_Float16 __x, long __ex)
+  { return _Float16(__builtin_scalblnf(__x, __ex)); }
+
+  constexpr _Float16
+  scalbn(_Float16 __x, int __ex)
+  { return _Float16(__builtin_scalbnf(__x, __ex)); }
+
+  constexpr _Float16
+  tgamma(_Float16 __x)
+  { return _Float16(__builtin_tgammaf(__x)); }
+
+  constexpr _Float16
+  trunc(_Float16 __x)
+  { return _Float16(__builtin_truncf(__x)); }
+#endif
+
+#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  constexpr _Float32
+  acosh(_Float32 __x)
+  { return __builtin_acoshf(__x); }
+
+  constexpr _Float32
+  asinh(_Float32 __x)
+  { return __builtin_asinhf(__x); }
+
+  constexpr _Float32
+  atanh(_Float32 __x)
+  { return __builtin_atanhf(__x); }
+
+  constexpr _Float32
+  cbrt(_Float32 __x)
+  { return __builtin_cbrtf(__x); }
+
+  constexpr _Float32
+  copysign(_Float32 __x, _Float32 __y)
+  { return __builtin_copysignf(__x, __y); }
+
+  constexpr _Float32
+  erf(_Float32 __x)
+  { return __builtin_erff(__x); }
+
+  constexpr _Float32
+  erfc(_Float32 __x)
+  { return __builtin_erfcf(__x); }
+
+  constexpr _Float32
+  exp2(_Float32 __x)
+  { return __builtin_exp2f(__x); }
+
+  constexpr _Float32
+  expm1(_Float32 __x)
+  { return __builtin_expm1f(__x); }
+
+  constexpr _Float32
+  fdim(_Float32 __x, _Float32 __y)
+  { return __builtin_fdimf(__x, __y); }
+
+  constexpr _Float32
+  fma(_Float32 __x, _Float32 __y, _Float32 __z)
+  { return __builtin_fmaf(__x, __y, __z); }
+
+  constexpr _Float32
+  fmax(_Float32 __x, _Float32 __y)
+  { return __builtin_fmaxf(__x, __y); }
+
+  constexpr _Float32
+  fmin(_Float32 __x, _Float32 __y)
+  { return __builtin_fminf(__x, __y); }
+
+  constexpr _Float32
+  hypot(_Float32 __x, _Float32 __y)
+  { return __builtin_hypotf(__x, __y); }
+
+  constexpr int
+  ilogb(_Float32 __x)
+  { return __builtin_ilogbf(__x); }
+
+  constexpr _Float32
+  lgamma(_Float32 __x)
+  { return __builtin_lgammaf(__x); }
+
+  constexpr long long
+  llrint(_Float32 __x)
+  { return __builtin_llrintf(__x); }
+
+  constexpr long long
+  llround(_Float32 __x)
+  { return __builtin_llroundf(__x); }
+
+  constexpr _Float32
+  log1p(_Float32 __x)
+  { return __builtin_log1pf(__x); }
+
+  // DR 568.
+  constexpr _Float32
+  log2(_Float32 __x)
+  { return __builtin_log2f(__x); }
+
+  constexpr _Float32
+  logb(_Float32 __x)
+  { return __builtin_logbf(__x); }
+
+  constexpr long
+  lrint(_Float32 __x)
+  { return __builtin_lrintf(__x); }
+
+  constexpr long
+  lround(_Float32 __x)
+  { return __builtin_lroundf(__x); }
+
+  constexpr _Float32
+  nearbyint(_Float32 __x)
+  { return __builtin_nearbyintf(__x); }
+
+  constexpr _Float32
+  nextafter(_Float32 __x, _Float32 __y)
+  { return __builtin_nextafterf(__x, __y); }
+
+  constexpr _Float32
+  remainder(_Float32 __x, _Float32 __y)
+  { return __builtin_remainderf(__x, __y); }
+
+  inline _Float32
+  remquo(_Float32 __x, _Float32 __y, int* __pquo)
+  { return __builtin_remquof(__x, __y, __pquo); }
+
+  constexpr _Float32
+  rint(_Float32 __x)
+  { return __builtin_rintf(__x); }
+
+  constexpr _Float32
+  round(_Float32 __x)
+  { return __builtin_roundf(__x); }
+
+  constexpr _Float32
+  scalbln(_Float32 __x, long __ex)
+  { return __builtin_scalblnf(__x, __ex); }
+
+  constexpr _Float32
+  scalbn(_Float32 __x, int __ex)
+  { return __builtin_scalbnf(__x, __ex); }
+
+  constexpr _Float32
+  tgamma(_Float32 __x)
+  { return __builtin_tgammaf(__x); }
+
+  constexpr _Float32
+  trunc(_Float32 __x)
+  { return __builtin_truncf(__x); }
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+  constexpr _Float64
+  acosh(_Float64 __x)
+  { return __builtin_acosh(__x); }
+
+  constexpr _Float64
+  asinh(_Float64 __x)
+  { return __builtin_asinh(__x); }
+
+  constexpr _Float64
+  atanh(_Float64 __x)
+  { return __builtin_atanh(__x); }
+
+  constexpr _Float64
+  cbrt(_Float64 __x)
+  { return __builtin_cbrt(__x); }
+
+  constexpr _Float64
+  copysign(_Float64 __x, _Float64 __y)
+  { return __builtin_copysign(__x, __y); }
+
+  constexpr _Float64
+  erf(_Float64 __x)
+  { return __builtin_erf(__x); }
+
+  constexpr _Float64
+  erfc(_Float64 __x)
+  { return __builtin_erfc(__x); }
+
+  constexpr _Float64
+  exp2(_Float64 __x)
+  { return __builtin_exp2(__x); }
+
+  constexpr _Float64
+  expm1(_Float64 __x)
+  { return __builtin_expm1(__x); }
+
+  constexpr _Float64
+  fdim(_Float64 __x, _Float64 __y)
+  { return __builtin_fdim(__x, __y); }
+
+  constexpr _Float64
+  fma(_Float64 __x, _Float64 __y, _Float64 __z)
+  { return __builtin_fma(__x, __y, __z); }
+
+  constexpr _Float64
+  fmax(_Float64 __x, _Float64 __y)
+  { return __builtin_fmax(__x, __y); }
+
+  constexpr _Float64
+  fmin(_Float64 __x, _Float64 __y)
+  { return __builtin_fmin(__x, __y); }
+
+  constexpr _Float64
+  hypot(_Float64 __x, _Float64 __y)
+  { return __builtin_hypot(__x, __y); }
+
+  constexpr int
+  ilogb(_Float64 __x)
+  { return __builtin_ilogb(__x); }
+
+  constexpr _Float64
+  lgamma(_Float64 __x)
+  { return __builtin_lgamma(__x); }
+
+  constexpr long long
+  llrint(_Float64 __x)
+  { return __builtin_llrint(__x); }
+
+  constexpr long long
+  llround(_Float64 __x)
+  { return __builtin_llround(__x); }
+
+  constexpr _Float64
+  log1p(_Float64 __x)
+  { return __builtin_log1p(__x); }
+
+  // DR 568.
+  constexpr _Float64
+  log2(_Float64 __x)
+  { return __builtin_log2(__x); }
+
+  constexpr _Float64
+  logb(_Float64 __x)
+  { return __builtin_logb(__x); }
+
+  constexpr long
+  lrint(_Float64 __x)
+  { return __builtin_lrint(__x); }
+
+  constexpr long
+  lround(_Float64 __x)
+  { return __builtin_lround(__x); }
+
+  constexpr _Float64
+  nearbyint(_Float64 __x)
+  { return __builtin_nearbyint(__x); }
+
+  constexpr _Float64
+  nextafter(_Float64 __x, _Float64 __y)
+  { return __builtin_nextafter(__x, __y); }
+
+  constexpr _Float64
+  remainder(_Float64 __x, _Float64 __y)
+  { return __builtin_remainder(__x, __y); }
+
+  inline _Float64
+  remquo(_Float64 __x, _Float64 __y, int* __pquo)
+  { return __builtin_remquo(__x, __y, __pquo); }
+
+  constexpr _Float64
+  rint(_Float64 __x)
+  { return __builtin_rint(__x); }
+
+  constexpr _Float64
+  round(_Float64 __x)
+  { return __builtin_round(__x); }
+
+  constexpr _Float64
+  scalbln(_Float64 __x, long __ex)
+  { return __builtin_scalbln(__x, __ex); }
+
+  constexpr _Float64
+  scalbn(_Float64 __x, int __ex)
+  { return __builtin_scalbn(__x, __ex); }
+
+  constexpr _Float64
+  tgamma(_Float64 __x)
+  { return __builtin_tgamma(__x); }
+
+  constexpr _Float64
+  trunc(_Float64 __x)
+  { return __builtin_trunc(__x); }
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128)
+  constexpr _Float128
+  acosh(_Float128 __x)
+  { return __builtin_acoshl(__x); }
+
+  constexpr _Float128
+  asinh(_Float128 __x)
+  { return __builtin_asinhl(__x); }
+
+  constexpr _Float128
+  atanh(_Float128 __x)
+  { return __builtin_atanhl(__x); }
+
+  constexpr _Float128
+  cbrt(_Float128 __x)
+  { return __builtin_cbrtl(__x); }
+
+  constexpr _Float128
+  copysign(_Float128 __x, _Float128 __y)
+  { return __builtin_copysignl(__x, __y); }
+
+  constexpr _Float128
+  erf(_Float128 __x)
+  { return __builtin_erfl(__x); }
+
+  constexpr _Float128
+  erfc(_Float128 __x)
+  { return __builtin_erfcl(__x); }
+
+  constexpr _Float128
+  exp2(_Float128 __x)
+  { return __builtin_exp2l(__x); }
+
+  constexpr _Float128
+  expm1(_Float128 __x)
+  { return __builtin_expm1l(__x); }
+
+  constexpr _Float128
+  fdim(_Float128 __x, _Float128 __y)
+  { return __builtin_fdiml(__x, __y); }
+
+  constexpr _Float128
+  fma(_Float128 __x, _Float128 __y, _Float128 __z)
+  { return __builtin_fmal(__x, __y, __z); }
+
+  constexpr _Float128
+  fmax(_Float128 __x, _Float128 __y)
+  { return __builtin_fmaxl(__x, __y); }
+
+  constexpr _Float128
+  fmin(_Float128 __x, _Float128 __y)
+  { return __builtin_fminl(__x, __y); }
+
+  constexpr _Float128
+  hypot(_Float128 __x, _Float128 __y)
+  { return __builtin_hypotl(__x, __y); }
+
+  constexpr int
+  ilogb(_Float128 __x)
+  { return __builtin_ilogbl(__x); }
+
+  constexpr _Float128
+  lgamma(_Float128 __x)
+  { return __builtin_lgammal(__x); }
+
+  constexpr long long
+  llrint(_Float128 __x)
+  { return __builtin_llrintl(__x); }
+
+  constexpr long long
+  llround(_Float128 __x)
+  { return __builtin_llroundl(__x); }
+
+  constexpr _Float128
+  log1p(_Float128 __x)
+  { return __builtin_log1pl(__x); }
+
+  // DR 568.
+  constexpr _Float128
+  log2(_Float128 __x)
+  { return __builtin_log2l(__x); }
+
+  constexpr _Float128
+  logb(_Float128 __x)
+  { return __builtin_logbl(__x); }
+
+  constexpr long
+  lrint(_Float128 __x)
+  { return __builtin_lrintl(__x); }
+
+  constexpr long
+  lround(_Float128 __x)
+  { return __builtin_lroundl(__x); }
+
+  constexpr _Float128
+  nearbyint(_Float128 __x)
+  { return __builtin_nearbyintl(__x); }
+
+  constexpr _Float128
+  nextafter(_Float128 __x, _Float128 __y)
+  { return __builtin_nextafterl(__x, __y); }
+
+  constexpr _Float128
+  remainder(_Float128 __x, _Float128 __y)
+  { return __builtin_remainderl(__x, __y); }
+
+  inline _Float128
+  remquo(_Float128 __x, _Float128 __y, int* __pquo)
+  { return __builtin_remquol(__x, __y, __pquo); }
+
+  constexpr _Float128
+  rint(_Float128 __x)
+  { return __builtin_rintl(__x); }
+
+  constexpr _Float128
+  round(_Float128 __x)
+  { return __builtin_roundl(__x); }
+
+  constexpr _Float128
+  scalbln(_Float128 __x, long __ex)
+  { return __builtin_scalblnl(__x, __ex); }
+
+  constexpr _Float128
+  scalbn(_Float128 __x, int __ex)
+  { return __builtin_scalbnl(__x, __ex); }
+
+  constexpr _Float128
+  tgamma(_Float128 __x)
+  { return __builtin_tgammal(__x); }
+
+  constexpr _Float128
+  trunc(_Float128 __x)
+  { return __builtin_truncl(__x); }
+#elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH)
+  constexpr _Float128
+  acosh(_Float128 __x)
+  { return __builtin_acoshf128(__x); }
+
+  constexpr _Float128
+  asinh(_Float128 __x)
+  { return __builtin_asinhf128(__x); }
+
+  constexpr _Float128
+  atanh(_Float128 __x)
+  { return __builtin_atanhf128(__x); }
+
+  constexpr _Float128
+  cbrt(_Float128 __x)
+  { return __builtin_cbrtf128(__x); }
+
+  constexpr _Float128
+  copysign(_Float128 __x, _Float128 __y)
+  { return __builtin_copysignf128(__x, __y); }
+
+  constexpr _Float128
+  erf(_Float128 __x)
+  { return __builtin_erff128(__x); }
+
+  constexpr _Float128
+  erfc(_Float128 __x)
+  { return __builtin_erfcf128(__x); }
+
+  constexpr _Float128
+  exp2(_Float128 __x)
+  { return __builtin_exp2f128(__x); }
+
+  constexpr _Float128
+  expm1(_Float128 __x)
+  { return __builtin_expm1f128(__x); }
+
+  constexpr _Float128
+  fdim(_Float128 __x, _Float128 __y)
+  { return __builtin_fdimf128(__x, __y); }
+
+  constexpr _Float128
+  fma(_Float128 __x, _Float128 __y, _Float128 __z)
+  { return __builtin_fmaf128(__x, __y, __z); }
+
+  constexpr _Float128
+  fmax(_Float128 __x, _Float128 __y)
+  { return __builtin_fmaxf128(__x, __y); }
+
+  constexpr _Float128
+  fmin(_Float128 __x, _Float128 __y)
+  { return __builtin_fminf128(__x, __y); }
+
+  constexpr _Float128
+  hypot(_Float128 __x, _Float128 __y)
+  { return __builtin_hypotf128(__x, __y); }
+
+  constexpr int
+  ilogb(_Float128 __x)
+  { return __builtin_ilogbf128(__x); }
+
+  constexpr _Float128
+  lgamma(_Float128 __x)
+  { return __builtin_lgammaf128(__x); }
+
+  constexpr long long
+  llrint(_Float128 __x)
+  { return __builtin_llrintf128(__x); }
+
+  constexpr long long
+  llround(_Float128 __x)
+  { return __builtin_llroundf128(__x); }
+
+  constexpr _Float128
+  log1p(_Float128 __x)
+  { return __builtin_log1pf128(__x); }
+
+  // DR 568.
+  constexpr _Float128
+  log2(_Float128 __x)
+  { return __builtin_log2f128(__x); }
+
+  constexpr _Float128
+  logb(_Float128 __x)
+  { return __builtin_logbf128(__x); }
+
+  constexpr long
+  lrint(_Float128 __x)
+  { return __builtin_lrintf128(__x); }
+
+  constexpr long
+  lround(_Float128 __x)
+  { return __builtin_lroundf128(__x); }
+
+  constexpr _Float128
+  nearbyint(_Float128 __x)
+  { return __builtin_nearbyintf128(__x); }
+
+  constexpr _Float128
+  nextafter(_Float128 __x, _Float128 __y)
+  { return __builtin_nextafterf128(__x, __y); }
+
+  constexpr _Float128
+  remainder(_Float128 __x, _Float128 __y)
+  { return __builtin_remainderf128(__x, __y); }
+
+  inline _Float128
+  remquo(_Float128 __x, _Float128 __y, int* __pquo)
+  { return __builtin_remquof128(__x, __y, __pquo); }
+
+  constexpr _Float128
+  rint(_Float128 __x)
+  { return __builtin_rintf128(__x); }
+
+  constexpr _Float128
+  round(_Float128 __x)
+  { return __builtin_roundf128(__x); }
+
+  constexpr _Float128
+  scalbln(_Float128 __x, long __ex)
+  { return __builtin_scalblnf128(__x, __ex); }
+
+  constexpr _Float128
+  scalbn(_Float128 __x, int __ex)
+  { return __builtin_scalbnf128(__x, __ex); }
+
+  constexpr _Float128
+  tgamma(_Float128 __x)
+  { return __builtin_tgammaf128(__x); }
+
+  constexpr _Float128
+  trunc(_Float128 __x)
+  { return __builtin_truncf128(__x); }
+#endif
+
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  constexpr __gnu_cxx::__bfloat16_t
+  acosh(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_acoshf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  asinh(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_asinhf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  atanh(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_atanhf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  cbrt(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_cbrtf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  copysign(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __gnu_cxx::__bfloat16_t(__builtin_copysignf(__x, __y)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  erf(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_erff(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  erfc(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_erfcf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  exp2(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_exp2f(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  expm1(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_expm1f(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  fdim(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __gnu_cxx::__bfloat16_t(__builtin_fdimf(__x, __y)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  fma(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y, __gnu_cxx::__bfloat16_t __z)
+  { return __gnu_cxx::__bfloat16_t(__builtin_fmaf(__x, __y, __z)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  fmax(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __gnu_cxx::__bfloat16_t(__builtin_fmaxf(__x, __y)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  fmin(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __gnu_cxx::__bfloat16_t(__builtin_fminf(__x, __y)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  hypot(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __gnu_cxx::__bfloat16_t(__builtin_hypotf(__x, __y)); }
+
+  constexpr int
+  ilogb(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_ilogbf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  lgamma(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_lgammaf(__x)); }
+
+  constexpr long long
+  llrint(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_llrintf(__x)); }
+
+  constexpr long long
+  llround(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_llroundf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  log1p(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_log1pf(__x)); }
+
+  // DR 568.
+  constexpr __gnu_cxx::__bfloat16_t
+  log2(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_log2f(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  logb(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_logbf(__x)); }
+
+  constexpr long
+  lrint(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_lrintf(__x)); }
+
+  constexpr long
+  lround(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_lroundf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  nearbyint(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_nearbyintf(__x)); }
+
+  // nextafter not implemented so far.
+
+  constexpr __gnu_cxx::__bfloat16_t
+  remainder(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __gnu_cxx::__bfloat16_t(__builtin_remainderf(__x, __y)); }
+
+  inline __gnu_cxx::__bfloat16_t
+  remquo(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y, int* __pquo)
+  { return __gnu_cxx::__bfloat16_t(__builtin_remquof(__x, __y, __pquo)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  rint(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_rintf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  round(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_roundf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  scalbln(__gnu_cxx::__bfloat16_t __x, long __ex)
+  { return __gnu_cxx::__bfloat16_t(__builtin_scalblnf(__x, __ex)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  scalbn(__gnu_cxx::__bfloat16_t __x, int __ex)
+  { return __gnu_cxx::__bfloat16_t(__builtin_scalbnf(__x, __ex)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  tgamma(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_tgammaf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  trunc(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_truncf(__x)); }
+#endif
+
+
 #endif // _GLIBCXX_USE_C99_MATH_TR1
 #endif // C++11
 
@@ -1885,6 +3504,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using __type = __gnu_cxx::__promoted_t<_Tp, _Up, _Vp>;
       return std::__hypot3<__type>(__x, __y, __z);
     }
+
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  inline _Float16
+  hypot(_Float16 __x, _Float16 __y, _Float16 __z)
+  { return std::__hypot3<_Float16>(__x, __y, __z); }
+#endif
+
+#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  inline _Float32
+  hypot(_Float32 __x, _Float32 __y, _Float32 __z)
+  { return std::__hypot3<_Float32>(__x, __y, __z); }
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+  inline _Float64
+  hypot(_Float64 __x, _Float64 __y, _Float64 __z)
+  { return std::__hypot3<_Float64>(__x, __y, __z); }
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__) \
+    && (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \
+	|| defined(_GLIBCXX_HAVE_FLOAT128_MATH))
+  inline _Float128
+  hypot(_Float128 __x, _Float128 __y, _Float128 __z)
+  { return std::__hypot3<_Float128>(__x, __y, __z); }
+#endif
+
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  inline __gnu_cxx::__bfloat16_t
+  hypot(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y, __gnu_cxx::__bfloat16_t __z)
+  { return std::__hypot3<__gnu_cxx::__bfloat16_t>(__x, __y, __z); }
+#endif
+
 #endif // C++17
 
 #if __cplusplus >= 202002L
@@ -1928,6 +3580,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using __type = __gnu_cxx::__promoted_t<_Tp, _Up, _Vp>;
       return std::__lerp<__type>(__x, __y, __z);
     }
+
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  inline _Float16
+  lerp(_Float16 __x, _Float16 __y, _Float16 __z) noexcept
+  { return std::__lerp<_Float16>(__x, __y, __z); }
+#endif
+
+#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  inline _Float32
+  lerp(_Float32 __x, _Float32 __y, _Float32 __z) noexcept
+  { return std::__lerp<_Float32>(__x, __y, __z); }
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+  inline _Float64
+  lerp(_Float64 __x, _Float64 __y, _Float64 __z) noexcept
+  { return std::__lerp<_Float64>(__x, __y, __z); }
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__) \
+    && (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \
+	|| defined(_GLIBCXX_HAVE_FLOAT128_MATH))
+  inline _Float128
+  lerp(_Float128 __x, _Float128 __y, _Float128 __z) noexcept
+  { return std::__lerp<_Float128>(__x, __y, __z); }
+#endif
+
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  inline __gnu_cxx::__bfloat16_t
+  lerp(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y, __gnu_cxx::__bfloat16_t __z) noexcept
+  { return std::__lerp<__gnu_cxx::__bfloat16_t>(__x, __y, __z); }
+#endif
+
 #endif // C++20
 
 _GLIBCXX_END_NAMESPACE_VERSION
--- libstdc++-v3/include/ext/type_traits.h.jj	2022-01-11 22:31:41.519756736 +0100
+++ libstdc++-v3/include/ext/type_traits.h	2022-10-15 11:08:49.897857492 +0200
@@ -190,6 +190,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __promote<float>
     { typedef float __type; };
 
+#ifdef __STDCPP_FLOAT16_T__
+  template<>
+    struct __promote<_Float16>
+    { typedef _Float16 __type; };
+#endif
+
+#ifdef __STDCPP_FLOAT32_T__
+  template<>
+    struct __promote<_Float32>
+    { typedef _Float32 __type; };
+#endif
+
+#ifdef __STDCPP_FLOAT64_T__
+  template<>
+    struct __promote<_Float64>
+    { typedef _Float64 __type; };
+#endif
+
+#ifdef __STDCPP_FLOAT128_T__
+  template<>
+    struct __promote<_Float128>
+    { typedef _Float128 __type; };
+#endif
+
+#ifdef __STDCPP_BFLOAT16_T__
+  template<>
+    struct __promote<__gnu_cxx::__bfloat16_t>
+    { typedef __gnu_cxx::__bfloat16_t __type; };
+#endif
+
 #if __cpp_fold_expressions
 
   template<typename... _Tp>
--- libstdc++-v3/include/Makefile.am.jj	2022-10-03 22:45:46.092435137 +0200
+++ libstdc++-v3/include/Makefile.am	2022-10-14 22:32:55.413346435 +0200
@@ -95,6 +95,7 @@ std_headers = \
 	${std_srcdir}/stack \
 	${std_srcdir}/stacktrace \
 	${std_srcdir}/stdexcept \
+	${std_srcdir}/stdfloat \
 	${std_srcdir}/stop_token \
 	${std_srcdir}/streambuf \
 	${std_srcdir}/string \
--- libstdc++-v3/include/Makefile.in.jj	2022-10-11 22:35:26.387468956 +0200
+++ libstdc++-v3/include/Makefile.in	2022-10-14 22:32:55.413346435 +0200
@@ -452,6 +452,7 @@ std_freestanding = \
 @GLIBCXX_HOSTED_TRUE@	${std_srcdir}/stack \
 @GLIBCXX_HOSTED_TRUE@	${std_srcdir}/stacktrace \
 @GLIBCXX_HOSTED_TRUE@	${std_srcdir}/stdexcept \
+@GLIBCXX_HOSTED_TRUE@	${std_srcdir}/stdfloat \
 @GLIBCXX_HOSTED_TRUE@	${std_srcdir}/stop_token \
 @GLIBCXX_HOSTED_TRUE@	${std_srcdir}/streambuf \
 @GLIBCXX_HOSTED_TRUE@	${std_srcdir}/string \
--- libstdc++-v3/include/precompiled/stdc++.h.jj	2022-10-03 22:45:46.100435029 +0200
+++ libstdc++-v3/include/precompiled/stdc++.h	2022-10-14 22:32:55.413346435 +0200
@@ -228,6 +228,7 @@
 # include <stacktrace>
 #endif
 #include <stdatomic.h>
+#include <stdfloat>
 #endif
 
 #endif // HOSTED
--- libstdc++-v3/config/os/gnu-linux/os_defines.h.jj	2022-01-11 22:31:41.469757439 +0100
+++ libstdc++-v3/config/os/gnu-linux/os_defines.h	2022-10-14 22:32:55.414346421 +0200
@@ -49,6 +49,17 @@
 // version dynamically in case it has changed since libstdc++ was configured.
 #define _GLIBCXX_NO_OBSOLETE_ISINF_ISNAN_DYNAMIC __GLIBC_PREREQ(2,23)
 
+// Glibc 2.26 on i?86/x86-64/ia64/ppc64le added *f128 support.
+// Glibc 2.27 added it also on many other arches but those have IEEE quad
+// long double.
+#if __GLIBC_PREREQ(2, 26) \
+    && (defined(__i386__) || defined(__x86_64__) || defined (__ia64__) \
+	|| (defined(__powerpc__) && defined(_ARCH_PWR8) \
+	    && defined(__LITTLE_ENDIAN__) && (_CALL_ELF == 2) \
+	    && defined(__FLOAT128__)))
+# define _GLIBCXX_HAVE_FLOAT128_MATH 1
+#endif
+
 #if __GLIBC_PREREQ(2, 27)
 // Since glibc 2.27 pthread_self() is usable without linking to libpthread.
 # define _GLIBCXX_NATIVE_THREAD_ID pthread_self()
--- libstdc++-v3/testsuite/18_support/headers/stdfloat/types_std.cc.jj	2022-10-14 22:32:55.414346421 +0200
+++ libstdc++-v3/testsuite/18_support/headers/stdfloat/types_std.cc	2022-10-14 22:32:55.414346421 +0200
@@ -0,0 +1,40 @@
+// { dg-options "-std=gnu++2b" }
+// { dg-do compile { target c++23 } }
+
+// Copyright (C) 2022 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <stdfloat>
+
+namespace gnu
+{
+#if defined(__STDCPP_FLOAT16_T__)
+  typedef std::float16_t t1;
+#endif
+#if defined(__STDCPP_FLOAT32_T__)
+  typedef std::float32_t t2;
+#endif
+#if defined(__STDCPP_FLOAT64_T__)
+  typedef std::float64_t t3;
+#endif
+#if defined(__STDCPP_FLOAT128_T__)
+  typedef std::float128_t t4;
+#endif
+#if defined(__STDCPP_BFLOAT16_T__)
+  typedef std::bfloat16_t t5;
+#endif
+}
--- libstdc++-v3/testsuite/18_support/headers/limits/synopsis_cxx23.cc.jj	2022-10-14 22:32:55.415346407 +0200
+++ libstdc++-v3/testsuite/18_support/headers/limits/synopsis_cxx23.cc	2022-10-14 22:32:55.415346407 +0200
@@ -0,0 +1,43 @@
+// { dg-options "-std=gnu++2b" }
+// { dg-do compile { target c++23 } }
+// { dg-require-normal-namespace "" }
+
+// Copyright (C) 2022 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <limits>
+#include <stdfloat>
+
+namespace std {
+  template<class T> class numeric_limits;
+
+#if defined(__STDCPP_FLOAT16_T__)
+  template<> class numeric_limits<float16_t>;
+#endif
+#if defined(__STDCPP_FLOAT32_T__)
+  template<> class numeric_limits<float32_t>;
+#endif
+#if defined(__STDCPP_FLOAT64_T__)
+  template<> class numeric_limits<float64_t>;
+#endif
+#if defined(__STDCPP_FLOAT128_T__)
+  template<> class numeric_limits<float128_t>;
+#endif
+#if defined(__STDCPP_BFLOAT16_T__)
+  template<> class numeric_limits<bfloat16_t>;
+#endif
+}
--- libstdc++-v3/testsuite/26_numerics/headers/cmath/c99_classification_macros_c++23.cc.jj	2022-10-14 22:32:55.415346407 +0200
+++ libstdc++-v3/testsuite/26_numerics/headers/cmath/c99_classification_macros_c++23.cc	2022-10-14 22:32:55.415346407 +0200
@@ -0,0 +1,96 @@
+// Copyright (C) 2022 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do link { target c++23 } }
+// { dg-excess-errors "" { target uclibc } }
+
+#include <cmath>
+#include <stdfloat>
+
+void fpclassify() { }
+
+void isfinite() { }
+
+void isinf() { }
+
+void isnan() { }
+
+void isnormal() { }
+
+void signbit() { }
+
+void isgreater() { }
+
+void isgreaterequal() { }
+
+void isless() { }
+
+void islessequal() { }
+
+void islessgreater() { }
+
+void isunordered() { }
+
+#if _GLIBCXX_USE_C99_MATH
+template <typename _Tp, typename _Up = _Tp>
+  void test_c99_classify()
+  {
+    typedef _Tp fp_type_one;
+    typedef _Up fp_type_two;
+    fp_type_one f1 = _Tp(1.0);
+    fp_type_two f2 = _Up(3.0);
+    int resi;
+    volatile bool res;
+
+    resi = std::fpclassify(f1);
+    res = std::isfinite(f2);
+    res = std::isinf(f1);
+    res = std::isnan(f2);
+    res = std::isnormal(f1);
+    res = std::signbit(f2);
+    res = std::isgreater(f1, f2);
+    res = std::isgreaterequal(f1, f2);
+    res = std::isless(f1, f2);
+    res = std::islessequal(f1,f2);
+    res = std::islessgreater(f1, f2);
+    res = std::isunordered(f1, f2);
+    resi = resi; // Suppress unused warning.
+    res = res;
+  }
+#endif
+
+int main()
+{
+#if _GLIBCXX_USE_C99_MATH
+#ifdef __STDCPP_FLOAT16_T__
+  test_c99_classify<std::float16_t>();
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+  test_c99_classify<std::float32_t>();
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+  test_c99_classify<std::float64_t>();
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+  test_c99_classify<std::float128_t>();
+#endif
+#ifdef __STDCPP_BFLOAT16_T__
+  test_c99_classify<std::bfloat16_t>();
+#endif
+#endif
+  return 0;
+}
--- libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc.jj	2022-10-14 22:32:55.415346407 +0200
+++ libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc	2022-10-15 11:43:08.107500180 +0200
@@ -0,0 +1,146 @@
+// Copyright (C) 2022 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do link { target c++23 } }
+
+#include <stdfloat>
+#include <cmath>
+
+template <typename T>
+__attribute__((__noipa__)) void
+test_functions (T *p, int *q, long int *r, long long int *s)
+{
+  p[0] = std::acos (p[0]);
+  p[1] = std::asin (p[1]);
+  p[2] = std::atan (p[2]);
+  p[3] = std::cos (p[3]);
+  p[4] = std::sin (p[4]);
+  p[5] = std::tan (p[5]);
+  p[6] = std::acosh (p[6]);
+  p[7] = std::asinh (p[7]);
+  p[8] = std::atanh (p[8]);
+  p[9] = std::cosh (p[9]);
+  p[10] = std::sinh (p[10]);
+  p[11] = std::tanh (p[11]);
+  p[12] = std::exp (p[12]);
+  p[13] = std::exp2 (p[13]);
+  p[14] = std::expm1 (p[14]);
+  p[15] = std::log (p[15]);
+  p[16] = std::log10 (p[16]);
+  p[17] = std::log1p (p[17]);
+  p[18] = std::log2 (p[18]);
+  p[19] = std::logb (p[19]);
+  p[20] = std::cbrt (p[20]);
+  p[21] = std::fabs (p[21]);
+  p[22] = std::sqrt (p[22]);
+  p[23] = std::erf (p[23]);
+  p[24] = std::erfc (p[24]);
+  p[25] = std::lgamma (p[25]);
+  p[26] = std::tgamma (p[26]);
+  p[27] = std::ceil (p[27]);
+  p[28] = std::floor (p[28]);
+  p[29] = std::nearbyint (p[29]);
+  p[30] = std::rint (p[30]);
+  p[31] = std::round (p[31]);
+  p[32] = std::trunc (p[32]);
+  p[33] = std::atan2 (p[33], p[100]);
+  p[34] = std::hypot (p[34], p[101]);
+  p[35] = std::pow (p[35], p[102]);
+  p[36] = std::fmod (p[36], p[103]);
+  p[37] = std::remainder (p[37], p[104]);
+  p[38] = std::copysign (p[38], p[105]);
+//  p[39] = std::nextafter (p[39], p[106]);
+  p[40] = std::fdim (p[40], p[107]);
+  p[41] = std::fmax (p[41], p[108]);
+  p[42] = std::fmin (p[42], p[109]);
+  p[43] = std::atan2 (p[43], p[110]);
+  p[44] = std::frexp (p[44], q + 0);
+  q[1] = std::ilogb (p[45]);
+  p[46] = std::ldexp (p[46], q[2]);
+  p[47] = std::modf (p[47], p + 111);
+  p[48] = std::scalbn (p[48], q[3]);
+  p[49] = std::scalbln (p[49], r[0]);
+  p[50] = std::hypot (p[50], p[111], p[112]);
+  r[1] = std::lrint (p[51]);
+  s[0] = std::llrint (p[52]);
+  r[2] = std::lround (p[53]);
+  s[1] = std::llround (p[54]);
+  p[55] = std::remquo (p[55], p[113], q + 4);
+  p[56] = std::fma (p[56], p[114], p[115]);
+  p[57] = std::lerp (p[57], p[116], p[117]);
+  p[58] = std::assoc_laguerre (q[5], q[6], p[58]);
+  p[59] = std::assoc_legendre (q[7], q[8], p[59]);
+  p[60] = std::beta (p[60], p[118]);
+  p[61] = std::comp_ellint_1 (p[61]);
+  p[62] = std::comp_ellint_2 (p[62]);
+  p[63] = std::comp_ellint_3 (p[63], p[119]);
+  p[64] = std::cyl_bessel_i (p[64], p[120]);
+  p[65] = std::cyl_bessel_j (p[65], p[121]);
+  p[66] = std::cyl_bessel_k (p[66], p[122]);
+  p[67] = std::cyl_neumann (p[67], p[123]);
+  p[68] = std::ellint_1 (p[68], p[124]);
+  p[69] = std::ellint_2 (p[69], p[125]);
+  p[70] = std::ellint_3 (p[70], p[126], p[127]);
+  p[71] = std::expint (p[71]);
+  p[72] = std::hermite (q[9], p[72]);
+  p[73] = std::laguerre (q[10], p[73]);
+  p[74] = std::legendre (q[11], p[72]);
+  p[75] = std::riemann_zeta (p[75]);
+  p[76] = std::sph_bessel (q[12], p[76]);
+  p[77] = std::sph_legendre (q[13], q[14], p[77]);
+  p[78] = std::sph_neumann (q[15], q[16], p[78]);
+}
+
+int
+main ()
+{
+  int q[17] = {};
+  long int r[16] = {};
+  long long int s[16] = {};
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  {
+    std::float16_t p[128] = {};
+    test_functions (p, q, r, s);
+  }
+#endif
+#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  {
+    std::float32_t p[128] = {};
+    test_functions (p, q, r, s);
+  }
+#endif
+#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+  {
+    std::float64_t p[128] = {};
+    test_functions (p, q, r, s);
+  }
+#endif
+#if defined(__STDCPP_FLOAT128_T__) \
+    && (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \
+	|| defined(_GLIBCXX_HAVE_FLOAT128_MATH))
+  {
+    std::float128_t p[128] = {};
+    test_functions (p, q, r, s);
+  }
+#endif
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  {
+    std::bfloat16_t p[128] = {};
+    test_functions (p, q, r, s);
+  }
+#endif
+}
--- libstdc++-v3/testsuite/26_numerics/numbers/4.cc.jj	2022-10-14 22:32:55.415346407 +0200
+++ libstdc++-v3/testsuite/26_numerics/numbers/4.cc	2022-10-14 22:32:55.415346407 +0200
@@ -0,0 +1,122 @@
+// Copyright (C) 2022 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2b" }
+// { dg-do compile { target c++23 } }
+
+#include <numbers>
+#include <stdfloat>
+
+#if defined(__STDCPP_FLOAT16_T__)
+void
+test01()
+{
+  const std::float16_t* d1  = &std::numbers::e_v<std::float16_t>;
+  const std::float16_t* d2  = &std::numbers::log2e_v<std::float16_t>;
+  const std::float16_t* d3  = &std::numbers::log10e_v<std::float16_t>;
+  const std::float16_t* d4  = &std::numbers::pi_v<std::float16_t>;
+  const std::float16_t* d5  = &std::numbers::inv_pi_v<std::float16_t>;
+  const std::float16_t* d6  = &std::numbers::inv_sqrtpi_v<std::float16_t>;
+  const std::float16_t* d7  = &std::numbers::ln2_v<std::float16_t>;
+  const std::float16_t* d8  = &std::numbers::ln10_v<std::float16_t>;
+  const std::float16_t* d9  = &std::numbers::sqrt2_v<std::float16_t>;
+  const std::float16_t* d10 = &std::numbers::sqrt3_v<std::float16_t>;
+  const std::float16_t* d11 = &std::numbers::inv_sqrt3_v<std::float16_t>;
+  const std::float16_t* d12 = &std::numbers::egamma_v<std::float16_t>;
+  const std::float16_t* d13 = &std::numbers::phi_v<std::float16_t>;
+}
+#endif
+
+#if defined(__STDCPP_FLOAT32_T__)
+void
+test02()
+{
+  const std::float32_t* d1  = &std::numbers::e_v<std::float32_t>;
+  const std::float32_t* d2  = &std::numbers::log2e_v<std::float32_t>;
+  const std::float32_t* d3  = &std::numbers::log10e_v<std::float32_t>;
+  const std::float32_t* d4  = &std::numbers::pi_v<std::float32_t>;
+  const std::float32_t* d5  = &std::numbers::inv_pi_v<std::float32_t>;
+  const std::float32_t* d6  = &std::numbers::inv_sqrtpi_v<std::float32_t>;
+  const std::float32_t* d7  = &std::numbers::ln2_v<std::float32_t>;
+  const std::float32_t* d8  = &std::numbers::ln10_v<std::float32_t>;
+  const std::float32_t* d9  = &std::numbers::sqrt2_v<std::float32_t>;
+  const std::float32_t* d10 = &std::numbers::sqrt3_v<std::float32_t>;
+  const std::float32_t* d11 = &std::numbers::inv_sqrt3_v<std::float32_t>;
+  const std::float32_t* d12 = &std::numbers::egamma_v<std::float32_t>;
+  const std::float32_t* d13 = &std::numbers::phi_v<std::float32_t>;
+}
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__)
+void
+test03()
+{
+  const std::float64_t* d1  = &std::numbers::e_v<std::float64_t>;
+  const std::float64_t* d2  = &std::numbers::log2e_v<std::float64_t>;
+  const std::float64_t* d3  = &std::numbers::log10e_v<std::float64_t>;
+  const std::float64_t* d4  = &std::numbers::pi_v<std::float64_t>;
+  const std::float64_t* d5  = &std::numbers::inv_pi_v<std::float64_t>;
+  const std::float64_t* d6  = &std::numbers::inv_sqrtpi_v<std::float64_t>;
+  const std::float64_t* d7  = &std::numbers::ln2_v<std::float64_t>;
+  const std::float64_t* d8  = &std::numbers::ln10_v<std::float64_t>;
+  const std::float64_t* d9  = &std::numbers::sqrt2_v<std::float64_t>;
+  const std::float64_t* d10 = &std::numbers::sqrt3_v<std::float64_t>;
+  const std::float64_t* d11 = &std::numbers::inv_sqrt3_v<std::float64_t>;
+  const std::float64_t* d12 = &std::numbers::egamma_v<std::float64_t>;
+  const std::float64_t* d13 = &std::numbers::phi_v<std::float64_t>;
+}
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__)
+void
+test04()
+{
+  const std::float128_t* d1  = &std::numbers::e_v<std::float128_t>;
+  const std::float128_t* d2  = &std::numbers::log2e_v<std::float128_t>;
+  const std::float128_t* d3  = &std::numbers::log10e_v<std::float128_t>;
+  const std::float128_t* d4  = &std::numbers::pi_v<std::float128_t>;
+  const std::float128_t* d5  = &std::numbers::inv_pi_v<std::float128_t>;
+  const std::float128_t* d6  = &std::numbers::inv_sqrtpi_v<std::float128_t>;
+  const std::float128_t* d7  = &std::numbers::ln2_v<std::float128_t>;
+  const std::float128_t* d8  = &std::numbers::ln10_v<std::float128_t>;
+  const std::float128_t* d9  = &std::numbers::sqrt2_v<std::float128_t>;
+  const std::float128_t* d10 = &std::numbers::sqrt3_v<std::float128_t>;
+  const std::float128_t* d11 = &std::numbers::inv_sqrt3_v<std::float128_t>;
+  const std::float128_t* d12 = &std::numbers::egamma_v<std::float128_t>;
+  const std::float128_t* d13 = &std::numbers::phi_v<std::float128_t>;
+}
+#endif
+
+#if defined(__STDCPP_BFLOAT16_T__)
+void
+test05()
+{
+  const std::bfloat16_t* d1  = &std::numbers::e_v<std::bfloat16_t>;
+  const std::bfloat16_t* d2  = &std::numbers::log2e_v<std::bfloat16_t>;
+  const std::bfloat16_t* d3  = &std::numbers::log10e_v<std::bfloat16_t>;
+  const std::bfloat16_t* d4  = &std::numbers::pi_v<std::bfloat16_t>;
+  const std::bfloat16_t* d5  = &std::numbers::inv_pi_v<std::bfloat16_t>;
+  const std::bfloat16_t* d6  = &std::numbers::inv_sqrtpi_v<std::bfloat16_t>;
+  const std::bfloat16_t* d7  = &std::numbers::ln2_v<std::bfloat16_t>;
+  const std::bfloat16_t* d8  = &std::numbers::ln10_v<std::bfloat16_t>;
+  const std::bfloat16_t* d9  = &std::numbers::sqrt2_v<std::bfloat16_t>;
+  const std::bfloat16_t* d10 = &std::numbers::sqrt3_v<std::bfloat16_t>;
+  const std::bfloat16_t* d11 = &std::numbers::inv_sqrt3_v<std::bfloat16_t>;
+  const std::bfloat16_t* d12 = &std::numbers::egamma_v<std::bfloat16_t>;
+  const std::bfloat16_t* d13 = &std::numbers::phi_v<std::bfloat16_t>;
+}
+#endif
--- libstdc++-v3/testsuite/29_atomics/atomic_float/requirements_cxx23.cc.jj	2022-10-14 22:32:55.416346393 +0200
+++ libstdc++-v3/testsuite/29_atomics/atomic_float/requirements_cxx23.cc	2022-10-14 22:32:55.416346393 +0200
@@ -0,0 +1,112 @@
+// Copyright (C) 2022 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2b" }
+// { dg-do compile { target c++23 } }
+
+#include <atomic>
+#include <stdfloat>
+
+#if defined(__STDCPP_FLOAT16_T__)
+void
+test01()
+{
+  using A = std::atomic<std::float16_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::float16_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif
+
+#if defined(__STDCPP_FLOAT32_T__)
+void
+test02()
+{
+  using A = std::atomic<std::float32_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::float32_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__)
+void
+test03()
+{
+  using A = std::atomic<std::float64_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::float64_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__)
+void
+test04()
+{
+  using A = std::atomic<std::float128_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::float128_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif
+
+#if defined(__STDCPP_BFLOAT16_T__)
+void
+test05()
+{
+  using A = std::atomic<std::bfloat16_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::bfloat16_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif


	Jakub


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH] libstdc++, v2: Partial library support for std::float{16,32,64,128}_t
  2022-10-16 10:20 ` [RFC PATCH] libstdc++, v2: " Jakub Jelinek
@ 2022-10-17 13:07   ` Jonathan Wakely
  2022-10-17 16:25     ` [PATCH] libstdc++, v3: Partial library support for std::float{16,32,64,128}_t and std::bfloat16_t Jakub Jelinek
  2022-10-17 21:33     ` [RFC PATCH] libstdc++, v2: Partial library support for std::float{16, 32, 64, 128}_t Joseph Myers
  0 siblings, 2 replies; 8+ messages in thread
From: Jonathan Wakely @ 2022-10-17 13:07 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: libstdc++, gcc-patches

On Sun, 16 Oct 2022 at 11:23, Jakub Jelinek <jakub@redhat.com> wrote:
>
> Hi!
>
> As the __bf16 support is now in at least on x86_64/i686, I've
> updated my patch to cover bfloat16_t as well and implemented almost
> everything for <cmath> - the only thing missing I'm aware of is
> std::nextafter std::float16_t and std::bfloat16_t overloads (I think
> we probably need to implement that out of line somewhere, or inline? - might
> need inline asm barriers) and std::nexttoward overloads (those are
> intentional, you said there is a LWG issue about that).

Yes, that's now https://cplusplus.github.io/LWG/issue3790
The current proposed resolution is to just restore the C++20 functions
and not provide anything for the new types.

> If you want to have <cmath> done in a different way, e.g. the patch
> groups a lot of different function overloads by the floating point type,
> is that ok or do you want to have them one function at a time for all types,
> then next?

No, I think this way makes more sense. Otherwise the line count in the
file will baloon with all the repeated #if #endif directives.

The only comment I have about the <cmath> changes is that I think all
the new functions should be just 'constexpr' not 'inline
_GLIBCXX_CONSTEXPR'. The __STDCPP_FLOATN__ macros are only defined for
C++23, right? So _GLIBCXX_CONSTEXPR is always just 'constexpr' (it's
only something different for C++98), and that already implies 'inline'
too. So just:

constexpr _Float16
log10(_Float16 __x)
{ return _Float16(__builtin_log10f(__x)); }


> I could try to handle <complex> too, but am kind of lost there.
> The paper dropped the explicit std::complex specializations, can they stay
> around as is and should new overloads be added for the
> _Float*/__gnu_cxx::__bfloat16_t types?

The explicit specializations can stay, they do no harm.

I think to handle the new FP types we can modify the primary template
as shown in P1467. I don't think we'll need to add any new function
overloads for the new types.

I can take care of the <complex> changes.

> And I/O etc. support is missing, not sure I'm able to handle that and if it
> is e.g. possible to keep that support out of libstdc++.so.6, because what
> extended floating point types one has on a particular arch could change over
> time (I mean e.g. bfloat16_t support or float16_t support can be added
> etc.).

Yes, I think we can add the I/O functions as always_inline because all
they're going to do is convert the argument to float, double, or long
double and then call the existing overloads. There will be no new
virtual functions.

I can take care of that too.



> --- libstdc++-v3/include/bits/c++config.jj      2022-05-23 21:44:49.082847038 +0200
> +++ libstdc++-v3/include/bits/c++config 2022-10-14 22:32:55.411346463 +0200
> @@ -1,4 +1,4 @@
> -// Predefined symbols and macros -*- C++ -*-
> +       // Predefined symbols and macros -*- C++ -*-

This whitespace change looks accidental.

Apart from that and simplifying 'inline _GLIBCXX_CONSTEXPR' to just
'constexpr' this looks good for trunk.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH] libstdc++, v3: Partial library support for std::float{16,32,64,128}_t and std::bfloat16_t
  2022-10-17 13:07   ` Jonathan Wakely
@ 2022-10-17 16:25     ` Jakub Jelinek
  2022-10-18  9:18       ` Jonathan Wakely
  2022-10-17 21:33     ` [RFC PATCH] libstdc++, v2: Partial library support for std::float{16, 32, 64, 128}_t Joseph Myers
  1 sibling, 1 reply; 8+ messages in thread
From: Jakub Jelinek @ 2022-10-17 16:25 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

Hi!

On Mon, Oct 17, 2022 at 02:07:00PM +0100, Jonathan Wakely wrote:
> Yes, that's now https://cplusplus.github.io/LWG/issue3790
> The current proposed resolution is to just restore the C++20 functions
> and not provide anything for the new types.

Ok.

> > If you want to have <cmath> done in a different way, e.g. the patch
> > groups a lot of different function overloads by the floating point type,
> > is that ok or do you want to have them one function at a time for all types,
> > then next?
> 
> No, I think this way makes more sense. Otherwise the line count in the
> file will baloon with all the repeated #if #endif directives.

Ok, changed.
I've also changed this in limits and std_abs.h (ditto for
_GLIBCXX_USE_CONSTEXPR, _GLIBCXX_USE_NOEXCEPT).

There is one thing I'm not sure about but can be handled incrementally.
What exactly is is_iec559 supposed to be?
Currently for float/double/long double/__float128 it seems to be defined
to true if the type has Inf, qNaN and denormals.
For std::float{16,32,64,128}_t even a note in the spec says they are
true.
Shall it be true only if the type is actually a IEEE754 type
(binary16/32/64/128) and false otherwise, or that + the x86 extended type?
Or if it is IEEE754-like and shall it be true also for
std::bfloat16_t?
Yet another case is the IBM double double, which has infinities, NaNs
and denormals, but for that one it is hard to claim it is even IEEE754-like
(variable precision).

> > I could try to handle <complex> too, but am kind of lost there.
> > The paper dropped the explicit std::complex specializations, can they stay
> > around as is and should new overloads be added for the
> > _Float*/__gnu_cxx::__bfloat16_t types?
> 
> The explicit specializations can stay, they do no harm.

Ok.  Shall those specialization also get the P1467 changes for the ctors?
Shall we also have specializations for the extended floating point types,
or only conditionally (say when float is binary have _Complex _Float32
so that we get better code)?

> I can take care of the <complex> changes.

Ok.

> > And I/O etc. support is missing, not sure I'm able to handle that and if it
> > is e.g. possible to keep that support out of libstdc++.so.6, because what
> > extended floating point types one has on a particular arch could change over
> > time (I mean e.g. bfloat16_t support or float16_t support can be added
> > etc.).
> 
> Yes, I think we can add the I/O functions as always_inline because all
> they're going to do is convert the argument to float, double, or long
> double and then call the existing overloads. There will be no new
> virtual functions.
> 
> I can take care of that too.

Thanks.

Here is an updated patch that I'll test overnight (but can't commit
until the builtins patch is reviewed as it depends on that;
well, I could comment out the std::float128_t cmath support if
long double is not IEEE quad and commit that only once the builtins
patch is in).

2022-10-17  Jakub Jelinek  <jakub@redhat.com>

	* include/std/stdfloat: New file.
	* include/std/numbers (__glibcxx_numbers): Define and use it
	for __float128 explicit instantiations as well as
	_Float{16,32,64,128} and __gnu_cxx::__bfloat16_t.
	* include/std/atomic (atomic<_Float16>, atomic<_Float32>,
	atomic<_Float64>, atomic<_Float128>, atomic<__gnu_cxx::__bfloat16_t>):
	New explicit instantiations.
	* include/std/type_traits (__is_floating_point_helper<_Float16>,
	__is_floating_point_helper<_Float32>,
	__is_floating_point_helper<_Float64>,
	__is_floating_point_helper<_Float128>,
	__is_floating_point_helper<__gnu_cxx::__bfloat16_t>): Likewise.
	* include/std/limits (__glibcxx_concat3_, __glibcxx_concat3,
	__glibcxx_float_n): Define.
	(numeric_limits<_Float16>, numeric_limits<_Float32>,
	numeric_limits<_Float64>, numeric_limits<_Float128>,
	numeric_limits<__gnu_cxx::__bfloat16_t>): New explicit instantiations.
	* include/bits/std_abs.h (abs): New overloads for
	_Float{16,32,64,128} and __gnu_cxx::__bfloat16_t.
	* include/bits/c++config (_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128): Define
	if long double is IEEE quad.
	(__gnu_cxx::__bfloat16_t): New using.
	* include/c_global/cmath (acos, asin, atan, atan2, ceil, cos, cosh,
	exp, fabs, floor, fmod, frexp, ldexp, log, log10, modf, pow, sin,
	sinh, sqrt, tan, tanh, fpclassify, isfinite, isinf, isnan, isnormal,
	signbit, isgreater, isgreaterequal, isless, islessequal,
	islessgreater, isunordered, acosh, asinh, atanh, cbrt, copysign, erf,
	erfc, exp2, expm1, fdim, fma, fmax, fmin, hypot, ilogb, lgamma,
	llrint, llround, log1p, log2, logb, lrint, lround, nearbyint,
	nextafter, remainder, rint, round, scalbln, scalbn, tgamma, trunc,
	lerp): New overloads with _Float{16,32,64,128} or
	__gnu_cxx::__bfloat16_t types.
	* config/os/gnu-linux/os_defines.h (_GLIBCXX_HAVE_FLOAT128_MATH):
	Define if glibc 2.26 and later implements *f128 APIs.
	* include/ext/type_traits.h (__promote<_Float16>, __promote<_Float32>,
	__promote<_Float64>, __promote<_Float128>,
	__promote<__gnu_cxx::__bfloat16_t>): New specializations.
	* include/Makefile.am (std_headers): Add stdfloat.
	* include/Makefile.in: Regenerated.
	* include/precompiled/stdc++.h: Include stdfloat.
	* testsuite/18_support/headers/stdfloat/types_std.cc: New test.
	* testsuite/18_support/headers/limits/synopsis_cxx23.cc: New test.
	* testsuite/26_numerics/headers/cmath/c99_classification_macros_c++23.cc:
	New test.
	* testsuite/26_numerics/headers/cmath/functions_std_c++23.cc: New test.
	* testsuite/26_numerics/numbers/4.cc: New test.
	* testsuite/29_atomics/atomic_float/requirements_cxx23.cc: New test.

--- libstdc++-v3/include/std/stdfloat.jj	2022-10-14 22:32:55.409346491 +0200
+++ libstdc++-v3/include/std/stdfloat	2022-10-14 22:32:55.408346505 +0200
@@ -0,0 +1,62 @@
+// <stdfloat> -*- C++ -*-
+
+// Copyright (C) 2022 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 include/stdfloat
+ *  This is a Standard C++ Library header.
+ */
+
+#ifndef _GLIBCXX_STDFLOAT
+#define _GLIBCXX_STDFLOAT 1
+
+#if __cplusplus > 202002L
+#include <bits/c++config.h>
+
+namespace std
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  #ifdef __STDCPP_FLOAT16_T__
+  using float16_t = _Float16;
+  #endif
+
+  #ifdef __STDCPP_FLOAT32_T__
+  using float32_t = _Float32;
+  #endif
+
+  #ifdef __STDCPP_FLOAT64_T__
+  using float64_t = _Float64;
+  #endif
+
+  #ifdef __STDCPP_FLOAT128_T__
+  using float128_t = _Float128;
+  #endif
+
+  #ifdef __STDCPP_BFLOAT16_T__
+  using bfloat16_t = __gnu_cxx::__bfloat16_t;
+  #endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // C++23
+#endif // _GLIBCXX_STDFLOAT
--- libstdc++-v3/include/std/numbers.jj	2022-09-29 22:16:25.227338468 +0200
+++ libstdc++-v3/include/std/numbers	2022-10-14 22:32:55.409346491 +0200
@@ -133,72 +133,98 @@ namespace numbers
   inline constexpr double egamma = egamma_v<double>;
   inline constexpr double phi = phi_v<double>;
 
+#define __glibcxx_numbers(TYPE, SUFFIX) \
+  /* e */						\
+  template<>						\
+    inline constexpr TYPE e_v<TYPE>			\
+      = 2.718281828459045235360287471352662498##SUFFIX;	\
+							\
+  /* log_2 e */						\
+  template<>						\
+    inline constexpr TYPE log2e_v<TYPE>			\
+      = 1.442695040888963407359924681001892137##SUFFIX;	\
+							\
+  /* log_10 e */					\
+  template<>						\
+    inline constexpr TYPE log10e_v<TYPE>		\
+      = 0.434294481903251827651128918916605082##SUFFIX;	\
+							\
+  /* pi */						\
+  template<>						\
+    inline constexpr TYPE pi_v<TYPE>			\
+      = 3.141592653589793238462643383279502884##SUFFIX;	\
+							\
+  /* 1/pi */						\
+  template<>						\
+    inline constexpr TYPE inv_pi_v<TYPE>		\
+      = 0.318309886183790671537767526745028724##SUFFIX;	\
+							\
+  /* 1/sqrt(pi) */					\
+  template<>						\
+    inline constexpr TYPE inv_sqrtpi_v<TYPE>		\
+      = 0.564189583547756286948079451560772586##SUFFIX;	\
+							\
+  /* log_e 2 */						\
+  template<>						\
+    inline constexpr TYPE ln2_v<TYPE>			\
+      = 0.693147180559945309417232121458176568##SUFFIX;	\
+							\
+  /* log_e 10 */					\
+  template<>						\
+    inline constexpr TYPE ln10_v<TYPE>			\
+      = 2.302585092994045684017991454684364208##SUFFIX;	\
+							\
+  /* sqrt(2) */						\
+  template<>						\
+    inline constexpr TYPE sqrt2_v<TYPE>			\
+      = 1.414213562373095048801688724209698079##SUFFIX;	\
+							\
+  /* sqrt(3) */						\
+  template<>						\
+    inline constexpr TYPE sqrt3_v<TYPE>			\
+      = 1.732050807568877293527446341505872367##SUFFIX;	\
+							\
+  /* 1/sqrt(3) */					\
+  template<>						\
+    inline constexpr TYPE inv_sqrt3_v<TYPE>		\
+      = 0.577350269189625764509148780501957456##SUFFIX;	\
+							\
+  /* The Euler-Mascheroni constant */			\
+  template<>						\
+    inline constexpr TYPE egamma_v<TYPE>		\
+      = 0.577215664901532860606512090082402431##SUFFIX;	\
+							\
+  /* The golden ratio, (1+sqrt(5))/2 */			\
+  template<>						\
+    inline constexpr TYPE phi_v<TYPE>			\
+      = 1.618033988749894848204586834365638118##SUFFIX
+
+#ifdef __STDCPP_FLOAT16_T__
+__glibcxx_numbers (_Float16, F16);
+#endif
+
+#ifdef __STDCPP_FLOAT32_T__
+__glibcxx_numbers (_Float32, F32);
+#endif
+
+#ifdef __STDCPP_FLOAT64_T__
+__glibcxx_numbers (_Float64, F64);
+#endif
+
+#ifdef __STDCPP_FLOAT128_T__
+__glibcxx_numbers (_Float128, F128);
+#endif
+
+#ifdef __STDCPP_BFLOAT128_T__
+__glibcxx_numbers (__gnu_cxx::__bfloat16_t, BF16);
+#endif
+
 #if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
-  template<>
-    inline constexpr __float128 e_v<__float128>
-      = 2.718281828459045235360287471352662498Q;
-
-  /// log_2 e
-  template<>
-    inline constexpr __float128 log2e_v<__float128>
-      = 1.442695040888963407359924681001892137Q;
-
-  /// log_10 e
-  template<>
-    inline constexpr __float128 log10e_v<__float128>
-      = 0.434294481903251827651128918916605082Q;
-
-  /// pi
-  template<>
-    inline constexpr __float128 pi_v<__float128>
-      = 3.141592653589793238462643383279502884Q;
-
-  /// 1/pi
-  template<>
-    inline constexpr __float128 inv_pi_v<__float128>
-      = 0.318309886183790671537767526745028724Q;
-
-  /// 1/sqrt(pi)
-  template<>
-    inline constexpr __float128 inv_sqrtpi_v<__float128>
-      = 0.564189583547756286948079451560772586Q;
-
-  /// log_e 2
-  template<>
-    inline constexpr __float128 ln2_v<__float128>
-      = 0.693147180559945309417232121458176568Q;
-
-  /// log_e 10
-  template<>
-    inline constexpr __float128 ln10_v<__float128>
-      = 2.302585092994045684017991454684364208Q;
-
-  /// sqrt(2)
-  template<>
-    inline constexpr __float128 sqrt2_v<__float128>
-      = 1.414213562373095048801688724209698079Q;
-
-  /// sqrt(3)
-  template<>
-    inline constexpr __float128 sqrt3_v<__float128>
-      = 1.732050807568877293527446341505872367Q;
-
-  /// 1/sqrt(3)
-  template<>
-    inline constexpr __float128 inv_sqrt3_v<__float128>
-      = 0.577350269189625764509148780501957456Q;
-
-  /// The Euler-Mascheroni constant
-  template<>
-    inline constexpr __float128 egamma_v<__float128>
-      = 0.577215664901532860606512090082402431Q;
-
-  /// The golden ratio, (1+sqrt(5))/2
-  template<>
-    inline constexpr __float128 phi_v<__float128>
-      = 1.618033988749894848204586834365638118Q;
+__glibcxx_numbers (__float128, Q);
 #endif // USE_FLOAT128
 
+#undef __glibcxx_numbers
+
 } // namespace numbers
 /// @}
 _GLIBCXX_END_NAMESPACE_VERSION
--- libstdc++-v3/include/std/atomic.jj	2022-09-29 22:16:25.227338468 +0200
+++ libstdc++-v3/include/std/atomic	2022-10-14 22:32:55.410346477 +0200
@@ -1625,6 +1625,91 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using __atomic_float<long double>::operator=;
     };
 
+#ifdef __STDCPP_FLOAT16_T__
+  template<>
+    struct atomic<_Float16> : __atomic_float<_Float16>
+    {
+      atomic() noexcept = default;
+
+      constexpr
+      atomic(_Float16 __fp) noexcept : __atomic_float<_Float16>(__fp)
+      { }
+
+      atomic& operator=(const atomic&) volatile = delete;
+      atomic& operator=(const atomic&) = delete;
+
+      using __atomic_float<_Float16>::operator=;
+    };
+#endif
+
+#ifdef __STDCPP_FLOAT32_T__
+  template<>
+    struct atomic<_Float32> : __atomic_float<_Float32>
+    {
+      atomic() noexcept = default;
+
+      constexpr
+      atomic(_Float32 __fp) noexcept : __atomic_float<_Float32>(__fp)
+      { }
+
+      atomic& operator=(const atomic&) volatile = delete;
+      atomic& operator=(const atomic&) = delete;
+
+      using __atomic_float<_Float32>::operator=;
+    };
+#endif
+
+#ifdef __STDCPP_FLOAT64_T__
+  template<>
+    struct atomic<_Float64> : __atomic_float<_Float64>
+    {
+      atomic() noexcept = default;
+
+      constexpr
+      atomic(_Float64 __fp) noexcept : __atomic_float<_Float64>(__fp)
+      { }
+
+      atomic& operator=(const atomic&) volatile = delete;
+      atomic& operator=(const atomic&) = delete;
+
+      using __atomic_float<_Float64>::operator=;
+    };
+#endif
+
+#ifdef __STDCPP_FLOAT128_T__
+  template<>
+    struct atomic<_Float128> : __atomic_float<_Float128>
+    {
+      atomic() noexcept = default;
+
+      constexpr
+      atomic(_Float128 __fp) noexcept : __atomic_float<_Float128>(__fp)
+      { }
+
+      atomic& operator=(const atomic&) volatile = delete;
+      atomic& operator=(const atomic&) = delete;
+
+      using __atomic_float<_Float128>::operator=;
+    };
+#endif
+
+#ifdef __STDCPP_BFLOAT16_T__
+  template<>
+    struct atomic<__gnu_cxx::__bfloat16_t> : __atomic_float<__gnu_cxx::__bfloat16_t>
+    {
+      atomic() noexcept = default;
+
+      constexpr
+      atomic(__gnu_cxx::__bfloat16_t __fp) noexcept : __atomic_float<__gnu_cxx::__bfloat16_t>(__fp)
+      { }
+
+      atomic& operator=(const atomic&) volatile = delete;
+      atomic& operator=(const atomic&) = delete;
+
+      using __atomic_float<__gnu_cxx::__bfloat16_t>::operator=;
+    };
+#endif
+
 #define __cpp_lib_atomic_ref 201806L
 
   /// Class template to provide atomic operations on a non-atomic variable.
--- libstdc++-v3/include/std/type_traits.jj	2022-10-11 12:10:42.236890466 +0200
+++ libstdc++-v3/include/std/type_traits	2022-10-14 22:32:55.410346477 +0200
@@ -459,6 +459,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __is_floating_point_helper<long double>
     : public true_type { };
 
+#ifdef __STDCPP_FLOAT16_T__
+  template<>
+    struct __is_floating_point_helper<_Float16>
+    : public true_type { };
+#endif
+
+#ifdef __STDCPP_FLOAT32_T__
+  template<>
+    struct __is_floating_point_helper<_Float32>
+    : public true_type { };
+#endif
+
+#ifdef __STDCPP_FLOAT64_T__
+  template<>
+    struct __is_floating_point_helper<_Float64>
+    : public true_type { };
+#endif
+
+#ifdef __STDCPP_FLOAT128_T__
+  template<>
+    struct __is_floating_point_helper<_Float128>
+    : public true_type { };
+#endif
+
+#ifdef __STDCPP_BFLOAT16_T__
+  template<>
+    struct __is_floating_point_helper<__gnu_cxx::__bfloat16_t>
+    : public true_type { };
+#endif
+
 #if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
   template<>
     struct __is_floating_point_helper<__float128>
--- libstdc++-v3/include/std/limits.jj	2022-10-05 21:23:02.984826675 +0200
+++ libstdc++-v3/include/std/limits	2022-10-17 18:00:11.977914383 +0200
@@ -1890,6 +1890,190 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #undef __glibcxx_long_double_traps
 #undef __glibcxx_long_double_tinyness_before
 
+#if __cplusplus > 202202L
+
+#define __glibcxx_concat3_(P,M,S) P ## M ## S
+#define __glibcxx_concat3(P,M,S) __glibcxx_concat3_ (P,M,S)
+
+#define __glibcxx_float_n(BITSIZE)					\
+  __extension__								\
+  template<>								\
+    struct numeric_limits<_Float##BITSIZE>				\
+    {									\
+      static constexpr bool is_specialized = true;			\
+									\
+      static constexpr _Float##BITSIZE					\
+      min() noexcept							\
+      { return __glibcxx_concat3 (__FLT, BITSIZE, _MIN__); }		\
+									\
+      static constexpr _Float##BITSIZE					\
+      max() noexcept							\
+      { return __glibcxx_concat3 (__FLT, BITSIZE, _MAX__); }		\
+									\
+      static constexpr _Float##BITSIZE					\
+      lowest() noexcept							\
+      { return -__glibcxx_concat3 (__FLT, BITSIZE, _MAX__); }		\
+									\
+      static constexpr int digits					\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MANT_DIG__);		\
+      static constexpr int digits10					\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _DIG__);			\
+      static constexpr int max_digits10					\
+	= __glibcxx_max_digits10 (__glibcxx_concat3 (__FLT, BITSIZE,	\
+						     _MANT_DIG__));	\
+      static constexpr bool is_signed = true;				\
+      static constexpr bool is_integer = false;				\
+      static constexpr bool is_exact = false;				\
+      static constexpr int radix					\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _RADIX__);			\
+									\
+      static constexpr _Float##BITSIZE					\
+      epsilon() noexcept						\
+      { return __glibcxx_concat3 (__FLT, BITSIZE, _EPSILON__); }	\
+									\
+      static constexpr _Float##BITSIZE 					\
+      round_error() noexcept { return 0.5F##BITSIZE; }			\
+									\
+      static constexpr int min_exponent					\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MIN_EXP__);		\
+      static constexpr int min_exponent10				\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MIN_10_EXP__);		\
+      static constexpr int max_exponent					\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MAX_EXP__);		\
+      static constexpr int max_exponent10				\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MAX_10_EXP__);		\
+									\
+      static constexpr bool has_infinity				\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _HAS_INFINITY__);		\
+      static constexpr bool has_quiet_NaN				\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _HAS_QUIET_NAN__);		\
+      static constexpr bool has_signaling_NaN				\
+	= has_quiet_NaN;						\
+      static constexpr float_denorm_style has_denorm			\
+	= bool(__glibcxx_concat3 (__FLT, BITSIZE, _HAS_DENORM__))	\
+	  ? denorm_present : denorm_absent;				\
+      static constexpr bool has_denorm_loss = false;			\
+									\
+      static constexpr _Float##BITSIZE					\
+      infinity() noexcept						\
+      { return __builtin_huge_valf##BITSIZE(); }			\
+									\
+      static constexpr _Float##BITSIZE					\
+      quiet_NaN() noexcept						\
+      { return __builtin_nanf##BITSIZE(""); }				\
+									\
+      static constexpr _Float##BITSIZE					\
+      signaling_NaN() noexcept						\
+      { return __builtin_nansf##BITSIZE(""); }				\
+									\
+      static constexpr _Float##BITSIZE					\
+      denorm_min() noexcept						\
+      { return __glibcxx_concat3 (__FLT, BITSIZE, _DENORM_MIN__); }	\
+									\
+      static constexpr bool is_iec559					\
+	= has_infinity && has_quiet_NaN && has_denorm == denorm_present;\
+      static constexpr bool is_bounded = true; 				\
+      static constexpr bool is_modulo = false; 				\
+									\
+      static constexpr bool traps = false; 				\
+      static constexpr bool tinyness_before = false; 			\
+      static constexpr float_round_style round_style 			\
+	= round_to_nearest; 						\
+    }; 									\
+
+#ifdef __STDCPP_FLOAT16_T__
+__glibcxx_float_n(16)
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+__glibcxx_float_n(32)
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+__glibcxx_float_n(64)
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+__glibcxx_float_n(128)
+#endif
+#undef __glibcxx_float_n
+#undef __glibcxx_concat3
+#undef __glibcxx_concat3_
+
+#ifdef __STDCPP_BFLOAT16_T__
+  __extension__
+  template<>
+    struct numeric_limits<__gnu_cxx::__bfloat16_t>
+    {
+      static constexpr bool is_specialized = true;
+
+      static constexpr __gnu_cxx::__bfloat16_t
+      min() noexcept
+      { return __BFLT16_MIN__; }
+
+      static constexpr __gnu_cxx::__bfloat16_t
+      max() noexcept
+      { return __BFLT16_MAX__; }
+
+      static constexpr __gnu_cxx::__bfloat16_t
+      lowest() noexcept
+      { return -__BFLT16_MAX__; }
+
+      static constexpr int digits = __BFLT16_MANT_DIG__;
+      static constexpr int digits10 = __BFLT16_DIG__;
+      static constexpr int max_digits10
+	= __glibcxx_max_digits10 (__BFLT16_MANT_DIG__);
+      static constexpr bool is_signed = true;
+      static constexpr bool is_integer = false;
+      static constexpr bool is_exact = false;
+      static constexpr int radix = __BFLT16_RADIX__;
+
+      static constexpr __gnu_cxx::__bfloat16_t
+      epsilon() noexcept
+      { return __BFLT16_EPSILON__; }
+
+      static constexpr __gnu_cxx::__bfloat16_t
+      round_error() noexcept { return 0.5BF16; }
+
+      static constexpr int min_exponent = __BFLT16_MIN_EXP__;
+      static constexpr int min_exponent10 = __BFLT16_MIN_10_EXP__;
+      static constexpr int max_exponent = __BFLT16_MAX_EXP__;
+      static constexpr int max_exponent10 = __BFLT16_MAX_10_EXP__;
+
+      static constexpr bool has_infinity = __BFLT16_HAS_INFINITY__;
+      static constexpr bool has_quiet_NaN = __BFLT16_HAS_QUIET_NAN__;
+      static constexpr bool has_signaling_NaN = has_quiet_NaN;
+      static constexpr float_denorm_style has_denorm
+	= bool(__BFLT16_HAS_DENORM__)
+	  ? denorm_present : denorm_absent;
+      static constexpr bool has_denorm_loss = false;
+
+      static constexpr __gnu_cxx::__bfloat16_t
+      infinity() noexcept
+      { return __gnu_cxx::__bfloat16_t(__builtin_huge_valf()); }
+
+      static constexpr __gnu_cxx::__bfloat16_t
+      quiet_NaN() noexcept
+      { return __gnu_cxx::__bfloat16_t(__builtin_nanf("")); }
+
+      static constexpr __gnu_cxx::__bfloat16_t
+      signaling_NaN() noexcept
+      { return __builtin_nansf16b(""); }
+
+      static constexpr __gnu_cxx::__bfloat16_t
+      denorm_min() noexcept
+      { return __BFLT16_DENORM_MIN__; }
+
+      static constexpr bool is_iec559
+	= has_infinity && has_quiet_NaN && has_denorm == denorm_present;
+      static constexpr bool is_bounded = true;
+      static constexpr bool is_modulo = false;
+
+      static constexpr bool traps = false;
+      static constexpr bool tinyness_before = false;
+      static constexpr float_round_style round_style = round_to_nearest;
+    };
+#endif
+
+#endif
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
--- libstdc++-v3/include/bits/std_abs.h.jj	2022-01-11 22:31:41.490757144 +0100
+++ libstdc++-v3/include/bits/std_abs.h	2022-10-14 22:32:55.411346463 +0200
@@ -97,6 +97,40 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   abs(__GLIBCXX_TYPE_INT_N_3 __x) { return __x >= 0 ? __x : -__x; }
 #endif
 
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  constexpr _Float16
+  abs(_Float16 __x)
+  { return _Float16(__builtin_fabsf(__x)); }
+#endif
+
+#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  constexpr _Float32
+  abs(_Float32 __x)
+  { return __builtin_fabsf(__x); }
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+  constexpr _Float64
+  abs(_Float64 __x)
+  { return __builtin_fabs(__x); }
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128)
+  constexpr _Float128
+  abs(_Float128 __x)
+  { return __builtin_fabsl(__x); }
+#elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH)
+  constexpr _Float128
+  abs(_Float128 __x)
+  { return __builtin_fabsf128(__x); }
+#endif
+
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  constexpr __gnu_cxx::__bfloat16_t
+  abs(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_fabsf(__x)); }
+#endif
+
 #if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
   __extension__ inline _GLIBCXX_CONSTEXPR
   __float128
--- libstdc++-v3/include/bits/c++config.jj	2022-05-23 21:44:49.082847038 +0200
+++ libstdc++-v3/include/bits/c++config	2022-10-14 22:32:55.411346463 +0200
@@ -796,6 +796,20 @@ namespace std
 # define _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 1
 #endif
 
+// Define if long double has the IEEE binary128 format.
+#if __LDBL_MANT_DIG__ == 113 \
+  && __LDBL_MIN_EXP__ == -16381 \
+  && __LDBL_MAX_EXP__ == 16384
+# define _GLIBCXX_LDOUBLE_IS_IEEE_BINARY128 1
+#endif
+
+#ifdef __STDCPP_BFLOAT16_T__
+namespace __gnu_cxx
+{
+  using __bfloat16_t = decltype(0.0bf16);
+}
+#endif
+
 #ifdef __has_builtin
 # ifdef __is_identifier
 // Intel and older Clang require !__is_identifier for some built-ins:
--- libstdc++-v3/include/c_global/cmath.jj	2022-10-03 22:45:46.093435123 +0200
+++ libstdc++-v3/include/c_global/cmath	2022-10-14 22:32:55.412346449 +0200
@@ -515,6 +515,564 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     tanh(_Tp __x)
     { return __builtin_tanh(__x); }
 
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  constexpr _Float16
+  acos(_Float16 __x)
+  { return _Float16(__builtin_acosf(__x)); }
+
+  constexpr _Float16
+  asin(_Float16 __x)
+  { return _Float16(__builtin_asinf(__x)); }
+
+  constexpr _Float16
+  atan(_Float16 __x)
+  { return _Float16(__builtin_atanf(__x)); }
+
+  constexpr _Float16
+  atan2(_Float16 __y, _Float16 __x)
+  { return _Float16(__builtin_atan2f(__y, __x)); }
+
+  constexpr _Float16
+  ceil(_Float16 __x)
+  { return _Float16(__builtin_ceilf(__x)); }
+
+  constexpr _Float16
+  cos(_Float16 __x)
+  { return _Float16(__builtin_cosf(__x)); }
+
+  constexpr _Float16
+  cosh(_Float16 __x)
+  { return _Float16(__builtin_coshf(__x)); }
+
+  constexpr _Float16
+  exp(_Float16 __x)
+  { return _Float16(__builtin_expf(__x)); }
+
+  constexpr _Float16
+  fabs(_Float16 __x)
+  { return _Float16(__builtin_fabsf(__x)); }
+
+  constexpr _Float16
+  floor(_Float16 __x)
+  { return _Float16(__builtin_floorf(__x)); }
+
+  constexpr _Float16
+  fmod(_Float16 __x, _Float16 __y)
+  { return _Float16(__builtin_fmodf(__x, __y)); }
+
+  inline _Float16
+  frexp(_Float16 __x, int* __exp)
+  { return _Float16(__builtin_frexpf(__x, __exp)); }
+
+  constexpr _Float16
+  ldexp(_Float16 __x, int __exp)
+  { return _Float16(__builtin_ldexpf(__x, __exp)); }
+
+  constexpr _Float16
+  log(_Float16 __x)
+  { return _Float16(__builtin_logf(__x)); }
+
+  constexpr _Float16
+  log10(_Float16 __x)
+  { return _Float16(__builtin_log10f(__x)); }
+
+  inline _Float16
+  modf(_Float16 __x, _Float16* __iptr)
+  {
+    float __i, __ret = __builtin_modff(__x, &__i);
+    *__iptr = _Float16(__i);
+    return _Float16(__ret);
+  }
+
+  constexpr _Float16
+  pow(_Float16 __x, _Float16 __y)
+  { return _Float16(__builtin_powf(__x, __y)); }
+
+  constexpr _Float16
+  sin(_Float16 __x)
+  { return _Float16(__builtin_sinf(__x)); }
+
+  constexpr _Float16
+  sinh(_Float16 __x)
+  { return _Float16(__builtin_sinhf(__x)); }
+
+  constexpr _Float16
+  sqrt(_Float16 __x)
+  { return _Float16(__builtin_sqrtf(__x)); }
+
+  constexpr _Float16
+  tan(_Float16 __x)
+  { return _Float16(__builtin_tanf(__x)); }
+
+  constexpr _Float16
+  tanh(_Float16 __x)
+  { return _Float16(__builtin_tanhf(__x)); }
+#endif
+
+#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  constexpr _Float32
+  acos(_Float32 __x)
+  { return __builtin_acosf(__x); }
+
+  constexpr _Float32
+  asin(_Float32 __x)
+  { return __builtin_asinf(__x); }
+
+  constexpr _Float32
+  atan(_Float32 __x)
+  { return __builtin_atanf(__x); }
+
+  constexpr _Float32
+  atan2(_Float32 __y, _Float32 __x)
+  { return __builtin_atan2f(__y, __x); }
+
+  constexpr _Float32
+  ceil(_Float32 __x)
+  { return __builtin_ceilf(__x); }
+
+  constexpr _Float32
+  cos(_Float32 __x)
+  { return __builtin_cosf(__x); }
+
+  constexpr _Float32
+  cosh(_Float32 __x)
+  { return __builtin_coshf(__x); }
+
+  constexpr _Float32
+  exp(_Float32 __x)
+  { return __builtin_expf(__x); }
+
+  constexpr _Float32
+  fabs(_Float32 __x)
+  { return __builtin_fabsf(__x); }
+
+  constexpr _Float32
+  floor(_Float32 __x)
+  { return __builtin_floorf(__x); }
+
+  constexpr _Float32
+  fmod(_Float32 __x, _Float32 __y)
+  { return __builtin_fmodf(__x, __y); }
+
+  inline _Float32
+  frexp(_Float32 __x, int* __exp)
+  { return __builtin_frexpf(__x, __exp); }
+
+  constexpr _Float32
+  ldexp(_Float32 __x, int __exp)
+  { return __builtin_ldexpf(__x, __exp); }
+
+  constexpr _Float32
+  log(_Float32 __x)
+  { return __builtin_logf(__x); }
+
+  constexpr _Float32
+  log10(_Float32 __x)
+  { return __builtin_log10f(__x); }
+
+  inline _Float32
+  modf(_Float32 __x, _Float32* __iptr)
+  {
+    float __i, __ret = __builtin_modff(__x, &__i);
+    *__iptr = __i;
+    return __ret;
+  }
+
+  constexpr _Float32
+  pow(_Float32 __x, _Float32 __y)
+  { return __builtin_powf(__x, __y); }
+
+  constexpr _Float32
+  sin(_Float32 __x)
+  { return __builtin_sinf(__x); }
+
+  constexpr _Float32
+  sinh(_Float32 __x)
+  { return __builtin_sinhf(__x); }
+
+  constexpr _Float32
+  sqrt(_Float32 __x)
+  { return __builtin_sqrtf(__x); }
+
+  constexpr _Float32
+  tan(_Float32 __x)
+  { return __builtin_tanf(__x); }
+
+  constexpr _Float32
+  tanh(_Float32 __x)
+  { return __builtin_tanhf(__x); }
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+  constexpr _Float64
+  acos(_Float64 __x)
+  { return __builtin_acos(__x); }
+
+  constexpr _Float64
+  asin(_Float64 __x)
+  { return __builtin_asin(__x); }
+
+  constexpr _Float64
+  atan(_Float64 __x)
+  { return __builtin_atan(__x); }
+
+  constexpr _Float64
+  atan2(_Float64 __y, _Float64 __x)
+  { return __builtin_atan2(__y, __x); }
+
+  constexpr _Float64
+  ceil(_Float64 __x)
+  { return __builtin_ceil(__x); }
+
+  constexpr _Float64
+  cos(_Float64 __x)
+  { return __builtin_cos(__x); }
+
+  constexpr _Float64
+  cosh(_Float64 __x)
+  { return __builtin_cosh(__x); }
+
+  constexpr _Float64
+  exp(_Float64 __x)
+  { return __builtin_exp(__x); }
+
+  constexpr _Float64
+  fabs(_Float64 __x)
+  { return __builtin_fabs(__x); }
+
+  constexpr _Float64
+  floor(_Float64 __x)
+  { return __builtin_floor(__x); }
+
+  constexpr _Float64
+  fmod(_Float64 __x, _Float64 __y)
+  { return __builtin_fmod(__x, __y); }
+
+  inline _Float64
+  frexp(_Float64 __x, int* __exp)
+  { return __builtin_frexp(__x, __exp); }
+
+  constexpr _Float64
+  ldexp(_Float64 __x, int __exp)
+  { return __builtin_ldexp(__x, __exp); }
+
+  constexpr _Float64
+  log(_Float64 __x)
+  { return __builtin_log(__x); }
+
+  constexpr _Float64
+  log10(_Float64 __x)
+  { return __builtin_log10(__x); }
+
+  inline _Float64
+  modf(_Float64 __x, _Float64* __iptr)
+  {
+    double __i, __ret = __builtin_modf(__x, &__i);
+    *__iptr = __i;
+    return __ret;
+  }
+
+  constexpr _Float64
+  pow(_Float64 __x, _Float64 __y)
+  { return __builtin_pow(__x, __y); }
+
+  constexpr _Float64
+  sin(_Float64 __x)
+  { return __builtin_sin(__x); }
+
+  constexpr _Float64
+  sinh(_Float64 __x)
+  { return __builtin_sinh(__x); }
+
+  constexpr _Float64
+  sqrt(_Float64 __x)
+  { return __builtin_sqrt(__x); }
+
+  constexpr _Float64
+  tan(_Float64 __x)
+  { return __builtin_tan(__x); }
+
+  constexpr _Float64
+  tanh(_Float64 __x)
+  { return __builtin_tanh(__x); }
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128)
+  constexpr _Float128
+  acos(_Float128 __x)
+  { return __builtin_acosl(__x); }
+
+  constexpr _Float128
+  asin(_Float128 __x)
+  { return __builtin_asinl(__x); }
+
+  constexpr _Float128
+  atan(_Float128 __x)
+  { return __builtin_atanl(__x); }
+
+  constexpr _Float128
+  atan2(_Float128 __y, _Float128 __x)
+  { return __builtin_atan2l(__y, __x); }
+
+  constexpr _Float128
+  ceil(_Float128 __x)
+  { return __builtin_ceill(__x); }
+
+  constexpr _Float128
+  cos(_Float128 __x)
+  { return __builtin_cosl(__x); }
+
+  constexpr _Float128
+  cosh(_Float128 __x)
+  { return __builtin_coshl(__x); }
+
+  constexpr _Float128
+  exp(_Float128 __x)
+  { return __builtin_expl(__x); }
+
+  constexpr _Float128
+  fabs(_Float128 __x)
+  { return __builtin_fabsl(__x); }
+
+  constexpr _Float128
+  floor(_Float128 __x)
+  { return __builtin_floorl(__x); }
+
+  constexpr _Float128
+  fmod(_Float128 __x, _Float128 __y)
+  { return __builtin_fmodl(__x, __y); }
+
+  inline _Float128
+  frexp(_Float128 __x, int* __exp)
+  { return __builtin_frexpl(__x, __exp); }
+
+  constexpr _Float128
+  ldexp(_Float128 __x, int __exp)
+  { return __builtin_ldexpl(__x, __exp); }
+
+  constexpr _Float128
+  log(_Float128 __x)
+  { return __builtin_logl(__x); }
+
+  constexpr _Float128
+  log10(_Float128 __x)
+  { return __builtin_log10l(__x); }
+
+  inline _Float128
+  modf(_Float128 __x, _Float128* __iptr)
+  {
+    long double __i, __ret = __builtin_modfl(__x, &__i);
+    *__iptr = __i;
+    return __ret;
+  }
+
+  constexpr _Float128
+  pow(_Float128 __x, _Float128 __y)
+  { return __builtin_powl(__x, __y); }
+
+  constexpr _Float128
+  sin(_Float128 __x)
+  { return __builtin_sinl(__x); }
+
+  constexpr _Float128
+  sinh(_Float128 __x)
+  { return __builtin_sinhl(__x); }
+
+  constexpr _Float128
+  sqrt(_Float128 __x)
+  { return __builtin_sqrtl(__x); }
+
+  constexpr _Float128
+  tan(_Float128 __x)
+  { return __builtin_tanl(__x); }
+
+  constexpr _Float128
+  tanh(_Float128 __x)
+  { return __builtin_tanhl(__x); }
+#elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH)
+  constexpr _Float128
+  acos(_Float128 __x)
+  { return __builtin_acosf128(__x); }
+
+  constexpr _Float128
+  asin(_Float128 __x)
+  { return __builtin_asinf128(__x); }
+
+  constexpr _Float128
+  atan(_Float128 __x)
+  { return __builtin_atanf128(__x); }
+
+  constexpr _Float128
+  atan2(_Float128 __y, _Float128 __x)
+  { return __builtin_atan2f128(__y, __x); }
+
+  constexpr _Float128
+  ceil(_Float128 __x)
+  { return __builtin_ceilf128(__x); }
+
+  constexpr _Float128
+  cos(_Float128 __x)
+  { return __builtin_cosf128(__x); }
+
+  constexpr _Float128
+  cosh(_Float128 __x)
+  { return __builtin_coshf128(__x); }
+
+  constexpr _Float128
+  exp(_Float128 __x)
+  { return __builtin_expf128(__x); }
+
+  constexpr _Float128
+  fabs(_Float128 __x)
+  { return __builtin_fabsf128(__x); }
+
+  constexpr _Float128
+  floor(_Float128 __x)
+  { return __builtin_floorf128(__x); }
+
+  constexpr _Float128
+  fmod(_Float128 __x, _Float128 __y)
+  { return __builtin_fmodf128(__x, __y); }
+
+  inline _Float128
+  frexp(_Float128 __x, int* __exp)
+  { return __builtin_frexpf128(__x, __exp); }
+
+  constexpr _Float128
+  ldexp(_Float128 __x, int __exp)
+  { return __builtin_ldexpf128(__x, __exp); }
+
+  constexpr _Float128
+  log(_Float128 __x)
+  { return __builtin_logf128(__x); }
+
+  constexpr _Float128
+  log10(_Float128 __x)
+  { return __builtin_log10f128(__x); }
+
+  inline _Float128
+  modf(_Float128 __x, _Float128* __iptr)
+  { return __builtin_modff128(__x, __iptr); }
+
+  constexpr _Float128
+  pow(_Float128 __x, _Float128 __y)
+  { return __builtin_powf128(__x, __y); }
+
+  constexpr _Float128
+  sin(_Float128 __x)
+  { return __builtin_sinf128(__x); }
+
+  constexpr _Float128
+  sinh(_Float128 __x)
+  { return __builtin_sinhf128(__x); }
+
+  constexpr _Float128
+  sqrt(_Float128 __x)
+  { return __builtin_sqrtf128(__x); }
+
+  constexpr _Float128
+  tan(_Float128 __x)
+  { return __builtin_tanf128(__x); }
+
+  constexpr _Float128
+  tanh(_Float128 __x)
+  { return __builtin_tanhf128(__x); }
+#endif
+
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  constexpr __gnu_cxx::__bfloat16_t
+  acos(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_acosf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  asin(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_asinf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  atan(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_atanf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  atan2(__gnu_cxx::__bfloat16_t __y, __gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_atan2f(__y, __x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  ceil(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_ceilf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  cos(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_cosf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  cosh(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_coshf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  exp(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_expf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  fabs(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_fabsf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  floor(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_floorf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  fmod(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __gnu_cxx::__bfloat16_t(__builtin_fmodf(__x, __y)); }
+
+  inline __gnu_cxx::__bfloat16_t
+  frexp(__gnu_cxx::__bfloat16_t __x, int* __exp)
+  { return __gnu_cxx::__bfloat16_t(__builtin_frexpf(__x, __exp)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  ldexp(__gnu_cxx::__bfloat16_t __x, int __exp)
+  { return __gnu_cxx::__bfloat16_t(__builtin_ldexpf(__x, __exp)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  log(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_logf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  log10(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_log10f(__x)); }
+
+  inline __gnu_cxx::__bfloat16_t
+  modf(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t* __iptr)
+  {
+    float __i, __ret = __builtin_modff(__x, &__i);
+    *__iptr = __gnu_cxx::__bfloat16_t(__i);
+    return __gnu_cxx::__bfloat16_t(__ret);
+  }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  pow(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __gnu_cxx::__bfloat16_t(__builtin_powf(__x, __y)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  sin(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_sinf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  sinh(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_sinhf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  sqrt(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_sqrtf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  tan(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_tanf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  tanh(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_tanhf(__x)); }
+#endif
+
 #if _GLIBCXX_USE_C99_MATH
 #if !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
 
@@ -948,6 +1506,262 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
 #endif // C++11
+
+#ifdef __STDCPP_FLOAT16_T__
+  constexpr int
+  fpclassify(_Float16 __x)
+  { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
+				FP_SUBNORMAL, FP_ZERO, __x); }
+
+  constexpr bool
+  isfinite(_Float16 __x)
+  { return __builtin_isfinite(__x); }
+
+  constexpr bool
+  isinf(_Float16 __x)
+  { return __builtin_isinf(__x); }
+
+  constexpr bool
+  isnan(_Float16 __x)
+  { return __builtin_isnan(__x); }
+
+  constexpr bool
+  isnormal(_Float16 __x)
+  { return __builtin_isnormal(__x); }
+
+  constexpr bool
+  signbit(_Float16 __x)
+  { return __builtin_signbit(__x); }
+
+  constexpr bool
+  isgreater(_Float16 __x, _Float16 __y)
+  { return __builtin_isgreater(__x, __y); }
+
+  constexpr bool
+  isgreaterequal(_Float16 __x, _Float16 __y)
+  { return __builtin_isgreaterequal(__x, __y); }
+
+  constexpr bool
+  isless(_Float16 __x, _Float16 __y)
+  { return __builtin_isless(__x, __y); }
+
+  constexpr bool
+  islessequal(_Float16 __x, _Float16 __y)
+  { return __builtin_islessequal(__x, __y); }
+
+  constexpr bool
+  islessgreater(_Float16 __x, _Float16 __y)
+  { return __builtin_islessgreater(__x, __y); }
+
+  constexpr bool
+  isunordered(_Float16 __x, _Float16 __y)
+  { return __builtin_isunordered(__x, __y); }
+#endif
+
+#ifdef __STDCPP_FLOAT32_T__
+  constexpr int
+  fpclassify(_Float32 __x)
+  { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
+				FP_SUBNORMAL, FP_ZERO, __x); }
+
+  constexpr bool
+  isfinite(_Float32 __x)
+  { return __builtin_isfinite(__x); }
+
+  constexpr bool
+  isinf(_Float32 __x)
+  { return __builtin_isinf(__x); }
+
+  constexpr bool
+  isnan(_Float32 __x)
+  { return __builtin_isnan(__x); }
+
+  constexpr bool
+  isnormal(_Float32 __x)
+  { return __builtin_isnormal(__x); }
+
+  constexpr bool
+  signbit(_Float32 __x)
+  { return __builtin_signbit(__x); }
+
+  constexpr bool
+  isgreater(_Float32 __x, _Float32 __y)
+  { return __builtin_isgreater(__x, __y); }
+
+  constexpr bool
+  isgreaterequal(_Float32 __x, _Float32 __y)
+  { return __builtin_isgreaterequal(__x, __y); }
+
+  constexpr bool
+  isless(_Float32 __x, _Float32 __y)
+  { return __builtin_isless(__x, __y); }
+
+  constexpr bool
+  islessequal(_Float32 __x, _Float32 __y)
+  { return __builtin_islessequal(__x, __y); }
+
+  constexpr bool
+  islessgreater(_Float32 __x, _Float32 __y)
+  { return __builtin_islessgreater(__x, __y); }
+
+  constexpr bool
+  isunordered(_Float32 __x, _Float32 __y)
+  { return __builtin_isunordered(__x, __y); }
+#endif
+
+#ifdef __STDCPP_FLOAT64_T__
+  constexpr int
+  fpclassify(_Float64 __x)
+  { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
+				FP_SUBNORMAL, FP_ZERO, __x); }
+
+  constexpr bool
+  isfinite(_Float64 __x)
+  { return __builtin_isfinite(__x); }
+
+  constexpr bool
+  isinf(_Float64 __x)
+  { return __builtin_isinf(__x); }
+
+  constexpr bool
+  isnan(_Float64 __x)
+  { return __builtin_isnan(__x); }
+
+  constexpr bool
+  isnormal(_Float64 __x)
+  { return __builtin_isnormal(__x); }
+
+  constexpr bool
+  signbit(_Float64 __x)
+  { return __builtin_signbit(__x); }
+
+  constexpr bool
+  isgreater(_Float64 __x, _Float64 __y)
+  { return __builtin_isgreater(__x, __y); }
+
+  constexpr bool
+  isgreaterequal(_Float64 __x, _Float64 __y)
+  { return __builtin_isgreaterequal(__x, __y); }
+
+  constexpr bool
+  isless(_Float64 __x, _Float64 __y)
+  { return __builtin_isless(__x, __y); }
+
+  constexpr bool
+  islessequal(_Float64 __x, _Float64 __y)
+  { return __builtin_islessequal(__x, __y); }
+
+  constexpr bool
+  islessgreater(_Float64 __x, _Float64 __y)
+  { return __builtin_islessgreater(__x, __y); }
+
+  constexpr bool
+  isunordered(_Float64 __x, _Float64 __y)
+  { return __builtin_isunordered(__x, __y); }
+#endif
+
+#ifdef __STDCPP_FLOAT128_T__
+  constexpr int
+  fpclassify(_Float128 __x)
+  { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
+				FP_SUBNORMAL, FP_ZERO, __x); }
+
+  constexpr bool
+  isfinite(_Float128 __x)
+  { return __builtin_isfinite(__x); }
+
+  constexpr bool
+  isinf(_Float128 __x)
+  { return __builtin_isinf(__x); }
+
+  constexpr bool
+  isnan(_Float128 __x)
+  { return __builtin_isnan(__x); }
+
+  constexpr bool
+  isnormal(_Float128 __x)
+  { return __builtin_isnormal(__x); }
+
+  constexpr bool
+  signbit(_Float128 __x)
+  { return __builtin_signbit(__x); }
+
+  constexpr bool
+  isgreater(_Float128 __x, _Float128 __y)
+  { return __builtin_isgreater(__x, __y); }
+
+  constexpr bool
+  isgreaterequal(_Float128 __x, _Float128 __y)
+  { return __builtin_isgreaterequal(__x, __y); }
+
+  constexpr bool
+  isless(_Float128 __x, _Float128 __y)
+  { return __builtin_isless(__x, __y); }
+
+  constexpr bool
+  islessequal(_Float128 __x, _Float128 __y)
+  { return __builtin_islessequal(__x, __y); }
+
+  constexpr bool
+  islessgreater(_Float128 __x, _Float128 __y)
+  { return __builtin_islessgreater(__x, __y); }
+
+  constexpr bool
+  isunordered(_Float128 __x, _Float128 __y)
+  { return __builtin_isunordered(__x, __y); }
+#endif
+
+#ifdef __STDCPP_BFLOAT16_T__
+  constexpr int
+  fpclassify(__gnu_cxx::__bfloat16_t __x)
+  { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
+				FP_SUBNORMAL, FP_ZERO, __x); }
+
+  constexpr bool
+  isfinite(__gnu_cxx::__bfloat16_t __x)
+  { return __builtin_isfinite(__x); }
+
+  constexpr bool
+  isinf(__gnu_cxx::__bfloat16_t __x)
+  { return __builtin_isinf(__x); }
+
+  constexpr bool
+  isnan(__gnu_cxx::__bfloat16_t __x)
+  { return __builtin_isnan(__x); }
+
+  constexpr bool
+  isnormal(__gnu_cxx::__bfloat16_t __x)
+  { return __builtin_isnormal(__x); }
+
+  constexpr bool
+  signbit(__gnu_cxx::__bfloat16_t __x)
+  { return __builtin_signbit(__x); }
+
+  constexpr bool
+  isgreater(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __builtin_isgreater(__x, __y); }
+
+  constexpr bool
+  isgreaterequal(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __builtin_isgreaterequal(__x, __y); }
+
+  constexpr bool
+  isless(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __builtin_isless(__x, __y); }
+
+  constexpr bool
+  islessequal(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __builtin_islessequal(__x, __y); }
+
+  constexpr bool
+  islessgreater(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __builtin_islessgreater(__x, __y); }
+
+  constexpr bool
+  isunordered(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __builtin_isunordered(__x, __y); }
+#endif
+
 #endif /* _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC */
 #endif /* _GLIBCXX_USE_C99_MATH */
 
@@ -1843,6 +2657,811 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { return __builtin_trunc(__x); }
 #endif
 
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  constexpr _Float16
+  acosh(_Float16 __x)
+  { return _Float16(__builtin_acoshf(__x)); }
+
+  constexpr _Float16
+  asinh(_Float16 __x)
+  { return _Float16(__builtin_asinhf(__x)); }
+
+  constexpr _Float16
+  atanh(_Float16 __x)
+  { return _Float16(__builtin_atanhf(__x)); }
+
+  constexpr _Float16
+  cbrt(_Float16 __x)
+  { return _Float16(__builtin_cbrtf(__x)); }
+
+  constexpr _Float16
+  copysign(_Float16 __x, _Float16 __y)
+  { return __builtin_copysignf16(__x, __y); }
+
+  constexpr _Float16
+  erf(_Float16 __x)
+  { return _Float16(__builtin_erff(__x)); }
+
+  constexpr _Float16
+  erfc(_Float16 __x)
+  { return _Float16(__builtin_erfcf(__x)); }
+
+  constexpr _Float16
+  exp2(_Float16 __x)
+  { return _Float16(__builtin_exp2f(__x)); }
+
+  constexpr _Float16
+  expm1(_Float16 __x)
+  { return _Float16(__builtin_expm1f(__x)); }
+
+  constexpr _Float16
+  fdim(_Float16 __x, _Float16 __y)
+  { return _Float16(__builtin_fdimf(__x, __y)); }
+
+  constexpr _Float16
+  fma(_Float16 __x, _Float16 __y, _Float16 __z)
+  { return _Float16(__builtin_fmaf(__x, __y, __z)); }
+
+  constexpr _Float16
+  fmax(_Float16 __x, _Float16 __y)
+  { return _Float16(__builtin_fmaxf(__x, __y)); }
+
+  constexpr _Float16
+  fmin(_Float16 __x, _Float16 __y)
+  { return _Float16(__builtin_fminf(__x, __y)); }
+
+  constexpr _Float16
+  hypot(_Float16 __x, _Float16 __y)
+  { return _Float16(__builtin_hypotf(__x, __y)); }
+
+  constexpr int
+  ilogb(_Float16 __x)
+  { return _Float16(__builtin_ilogbf(__x)); }
+
+  constexpr _Float16
+  lgamma(_Float16 __x)
+  { return _Float16(__builtin_lgammaf(__x)); }
+
+  constexpr long long
+  llrint(_Float16 __x)
+  { return _Float16(__builtin_llrintf(__x)); }
+
+  constexpr long long
+  llround(_Float16 __x)
+  { return _Float16(__builtin_llroundf(__x)); }
+
+  constexpr _Float16
+  log1p(_Float16 __x)
+  { return _Float16(__builtin_log1pf(__x)); }
+
+  // DR 568.
+  constexpr _Float16
+  log2(_Float16 __x)
+  { return _Float16(__builtin_log2f(__x)); }
+
+  constexpr _Float16
+  logb(_Float16 __x)
+  { return _Float16(__builtin_logbf(__x)); }
+
+  constexpr long
+  lrint(_Float16 __x)
+  { return _Float16(__builtin_lrintf(__x)); }
+
+  constexpr long
+  lround(_Float16 __x)
+  { return _Float16(__builtin_lroundf(__x)); }
+
+  constexpr _Float16
+  nearbyint(_Float16 __x)
+  { return _Float16(__builtin_nearbyintf(__x)); }
+
+  // nextafter not implemented so far.
+
+  constexpr _Float16
+  remainder(_Float16 __x, _Float16 __y)
+  { return _Float16(__builtin_remainderf(__x, __y)); }
+
+  inline _Float16
+  remquo(_Float16 __x, _Float16 __y, int* __pquo)
+  { return _Float16(__builtin_remquof(__x, __y, __pquo)); }
+
+  constexpr _Float16
+  rint(_Float16 __x)
+  { return _Float16(__builtin_rintf(__x)); }
+
+  constexpr _Float16
+  round(_Float16 __x)
+  { return _Float16(__builtin_roundf(__x)); }
+
+  constexpr _Float16
+  scalbln(_Float16 __x, long __ex)
+  { return _Float16(__builtin_scalblnf(__x, __ex)); }
+
+  constexpr _Float16
+  scalbn(_Float16 __x, int __ex)
+  { return _Float16(__builtin_scalbnf(__x, __ex)); }
+
+  constexpr _Float16
+  tgamma(_Float16 __x)
+  { return _Float16(__builtin_tgammaf(__x)); }
+
+  constexpr _Float16
+  trunc(_Float16 __x)
+  { return _Float16(__builtin_truncf(__x)); }
+#endif
+
+#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  constexpr _Float32
+  acosh(_Float32 __x)
+  { return __builtin_acoshf(__x); }
+
+  constexpr _Float32
+  asinh(_Float32 __x)
+  { return __builtin_asinhf(__x); }
+
+  constexpr _Float32
+  atanh(_Float32 __x)
+  { return __builtin_atanhf(__x); }
+
+  constexpr _Float32
+  cbrt(_Float32 __x)
+  { return __builtin_cbrtf(__x); }
+
+  constexpr _Float32
+  copysign(_Float32 __x, _Float32 __y)
+  { return __builtin_copysignf(__x, __y); }
+
+  constexpr _Float32
+  erf(_Float32 __x)
+  { return __builtin_erff(__x); }
+
+  constexpr _Float32
+  erfc(_Float32 __x)
+  { return __builtin_erfcf(__x); }
+
+  constexpr _Float32
+  exp2(_Float32 __x)
+  { return __builtin_exp2f(__x); }
+
+  constexpr _Float32
+  expm1(_Float32 __x)
+  { return __builtin_expm1f(__x); }
+
+  constexpr _Float32
+  fdim(_Float32 __x, _Float32 __y)
+  { return __builtin_fdimf(__x, __y); }
+
+  constexpr _Float32
+  fma(_Float32 __x, _Float32 __y, _Float32 __z)
+  { return __builtin_fmaf(__x, __y, __z); }
+
+  constexpr _Float32
+  fmax(_Float32 __x, _Float32 __y)
+  { return __builtin_fmaxf(__x, __y); }
+
+  constexpr _Float32
+  fmin(_Float32 __x, _Float32 __y)
+  { return __builtin_fminf(__x, __y); }
+
+  constexpr _Float32
+  hypot(_Float32 __x, _Float32 __y)
+  { return __builtin_hypotf(__x, __y); }
+
+  constexpr int
+  ilogb(_Float32 __x)
+  { return __builtin_ilogbf(__x); }
+
+  constexpr _Float32
+  lgamma(_Float32 __x)
+  { return __builtin_lgammaf(__x); }
+
+  constexpr long long
+  llrint(_Float32 __x)
+  { return __builtin_llrintf(__x); }
+
+  constexpr long long
+  llround(_Float32 __x)
+  { return __builtin_llroundf(__x); }
+
+  constexpr _Float32
+  log1p(_Float32 __x)
+  { return __builtin_log1pf(__x); }
+
+  // DR 568.
+  constexpr _Float32
+  log2(_Float32 __x)
+  { return __builtin_log2f(__x); }
+
+  constexpr _Float32
+  logb(_Float32 __x)
+  { return __builtin_logbf(__x); }
+
+  constexpr long
+  lrint(_Float32 __x)
+  { return __builtin_lrintf(__x); }
+
+  constexpr long
+  lround(_Float32 __x)
+  { return __builtin_lroundf(__x); }
+
+  constexpr _Float32
+  nearbyint(_Float32 __x)
+  { return __builtin_nearbyintf(__x); }
+
+  constexpr _Float32
+  nextafter(_Float32 __x, _Float32 __y)
+  { return __builtin_nextafterf(__x, __y); }
+
+  constexpr _Float32
+  remainder(_Float32 __x, _Float32 __y)
+  { return __builtin_remainderf(__x, __y); }
+
+  inline _Float32
+  remquo(_Float32 __x, _Float32 __y, int* __pquo)
+  { return __builtin_remquof(__x, __y, __pquo); }
+
+  constexpr _Float32
+  rint(_Float32 __x)
+  { return __builtin_rintf(__x); }
+
+  constexpr _Float32
+  round(_Float32 __x)
+  { return __builtin_roundf(__x); }
+
+  constexpr _Float32
+  scalbln(_Float32 __x, long __ex)
+  { return __builtin_scalblnf(__x, __ex); }
+
+  constexpr _Float32
+  scalbn(_Float32 __x, int __ex)
+  { return __builtin_scalbnf(__x, __ex); }
+
+  constexpr _Float32
+  tgamma(_Float32 __x)
+  { return __builtin_tgammaf(__x); }
+
+  constexpr _Float32
+  trunc(_Float32 __x)
+  { return __builtin_truncf(__x); }
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+  constexpr _Float64
+  acosh(_Float64 __x)
+  { return __builtin_acosh(__x); }
+
+  constexpr _Float64
+  asinh(_Float64 __x)
+  { return __builtin_asinh(__x); }
+
+  constexpr _Float64
+  atanh(_Float64 __x)
+  { return __builtin_atanh(__x); }
+
+  constexpr _Float64
+  cbrt(_Float64 __x)
+  { return __builtin_cbrt(__x); }
+
+  constexpr _Float64
+  copysign(_Float64 __x, _Float64 __y)
+  { return __builtin_copysign(__x, __y); }
+
+  constexpr _Float64
+  erf(_Float64 __x)
+  { return __builtin_erf(__x); }
+
+  constexpr _Float64
+  erfc(_Float64 __x)
+  { return __builtin_erfc(__x); }
+
+  constexpr _Float64
+  exp2(_Float64 __x)
+  { return __builtin_exp2(__x); }
+
+  constexpr _Float64
+  expm1(_Float64 __x)
+  { return __builtin_expm1(__x); }
+
+  constexpr _Float64
+  fdim(_Float64 __x, _Float64 __y)
+  { return __builtin_fdim(__x, __y); }
+
+  constexpr _Float64
+  fma(_Float64 __x, _Float64 __y, _Float64 __z)
+  { return __builtin_fma(__x, __y, __z); }
+
+  constexpr _Float64
+  fmax(_Float64 __x, _Float64 __y)
+  { return __builtin_fmax(__x, __y); }
+
+  constexpr _Float64
+  fmin(_Float64 __x, _Float64 __y)
+  { return __builtin_fmin(__x, __y); }
+
+  constexpr _Float64
+  hypot(_Float64 __x, _Float64 __y)
+  { return __builtin_hypot(__x, __y); }
+
+  constexpr int
+  ilogb(_Float64 __x)
+  { return __builtin_ilogb(__x); }
+
+  constexpr _Float64
+  lgamma(_Float64 __x)
+  { return __builtin_lgamma(__x); }
+
+  constexpr long long
+  llrint(_Float64 __x)
+  { return __builtin_llrint(__x); }
+
+  constexpr long long
+  llround(_Float64 __x)
+  { return __builtin_llround(__x); }
+
+  constexpr _Float64
+  log1p(_Float64 __x)
+  { return __builtin_log1p(__x); }
+
+  // DR 568.
+  constexpr _Float64
+  log2(_Float64 __x)
+  { return __builtin_log2(__x); }
+
+  constexpr _Float64
+  logb(_Float64 __x)
+  { return __builtin_logb(__x); }
+
+  constexpr long
+  lrint(_Float64 __x)
+  { return __builtin_lrint(__x); }
+
+  constexpr long
+  lround(_Float64 __x)
+  { return __builtin_lround(__x); }
+
+  constexpr _Float64
+  nearbyint(_Float64 __x)
+  { return __builtin_nearbyint(__x); }
+
+  constexpr _Float64
+  nextafter(_Float64 __x, _Float64 __y)
+  { return __builtin_nextafter(__x, __y); }
+
+  constexpr _Float64
+  remainder(_Float64 __x, _Float64 __y)
+  { return __builtin_remainder(__x, __y); }
+
+  inline _Float64
+  remquo(_Float64 __x, _Float64 __y, int* __pquo)
+  { return __builtin_remquo(__x, __y, __pquo); }
+
+  constexpr _Float64
+  rint(_Float64 __x)
+  { return __builtin_rint(__x); }
+
+  constexpr _Float64
+  round(_Float64 __x)
+  { return __builtin_round(__x); }
+
+  constexpr _Float64
+  scalbln(_Float64 __x, long __ex)
+  { return __builtin_scalbln(__x, __ex); }
+
+  constexpr _Float64
+  scalbn(_Float64 __x, int __ex)
+  { return __builtin_scalbn(__x, __ex); }
+
+  constexpr _Float64
+  tgamma(_Float64 __x)
+  { return __builtin_tgamma(__x); }
+
+  constexpr _Float64
+  trunc(_Float64 __x)
+  { return __builtin_trunc(__x); }
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128)
+  constexpr _Float128
+  acosh(_Float128 __x)
+  { return __builtin_acoshl(__x); }
+
+  constexpr _Float128
+  asinh(_Float128 __x)
+  { return __builtin_asinhl(__x); }
+
+  constexpr _Float128
+  atanh(_Float128 __x)
+  { return __builtin_atanhl(__x); }
+
+  constexpr _Float128
+  cbrt(_Float128 __x)
+  { return __builtin_cbrtl(__x); }
+
+  constexpr _Float128
+  copysign(_Float128 __x, _Float128 __y)
+  { return __builtin_copysignl(__x, __y); }
+
+  constexpr _Float128
+  erf(_Float128 __x)
+  { return __builtin_erfl(__x); }
+
+  constexpr _Float128
+  erfc(_Float128 __x)
+  { return __builtin_erfcl(__x); }
+
+  constexpr _Float128
+  exp2(_Float128 __x)
+  { return __builtin_exp2l(__x); }
+
+  constexpr _Float128
+  expm1(_Float128 __x)
+  { return __builtin_expm1l(__x); }
+
+  constexpr _Float128
+  fdim(_Float128 __x, _Float128 __y)
+  { return __builtin_fdiml(__x, __y); }
+
+  constexpr _Float128
+  fma(_Float128 __x, _Float128 __y, _Float128 __z)
+  { return __builtin_fmal(__x, __y, __z); }
+
+  constexpr _Float128
+  fmax(_Float128 __x, _Float128 __y)
+  { return __builtin_fmaxl(__x, __y); }
+
+  constexpr _Float128
+  fmin(_Float128 __x, _Float128 __y)
+  { return __builtin_fminl(__x, __y); }
+
+  constexpr _Float128
+  hypot(_Float128 __x, _Float128 __y)
+  { return __builtin_hypotl(__x, __y); }
+
+  constexpr int
+  ilogb(_Float128 __x)
+  { return __builtin_ilogbl(__x); }
+
+  constexpr _Float128
+  lgamma(_Float128 __x)
+  { return __builtin_lgammal(__x); }
+
+  constexpr long long
+  llrint(_Float128 __x)
+  { return __builtin_llrintl(__x); }
+
+  constexpr long long
+  llround(_Float128 __x)
+  { return __builtin_llroundl(__x); }
+
+  constexpr _Float128
+  log1p(_Float128 __x)
+  { return __builtin_log1pl(__x); }
+
+  // DR 568.
+  constexpr _Float128
+  log2(_Float128 __x)
+  { return __builtin_log2l(__x); }
+
+  constexpr _Float128
+  logb(_Float128 __x)
+  { return __builtin_logbl(__x); }
+
+  constexpr long
+  lrint(_Float128 __x)
+  { return __builtin_lrintl(__x); }
+
+  constexpr long
+  lround(_Float128 __x)
+  { return __builtin_lroundl(__x); }
+
+  constexpr _Float128
+  nearbyint(_Float128 __x)
+  { return __builtin_nearbyintl(__x); }
+
+  constexpr _Float128
+  nextafter(_Float128 __x, _Float128 __y)
+  { return __builtin_nextafterl(__x, __y); }
+
+  constexpr _Float128
+  remainder(_Float128 __x, _Float128 __y)
+  { return __builtin_remainderl(__x, __y); }
+
+  inline _Float128
+  remquo(_Float128 __x, _Float128 __y, int* __pquo)
+  { return __builtin_remquol(__x, __y, __pquo); }
+
+  constexpr _Float128
+  rint(_Float128 __x)
+  { return __builtin_rintl(__x); }
+
+  constexpr _Float128
+  round(_Float128 __x)
+  { return __builtin_roundl(__x); }
+
+  constexpr _Float128
+  scalbln(_Float128 __x, long __ex)
+  { return __builtin_scalblnl(__x, __ex); }
+
+  constexpr _Float128
+  scalbn(_Float128 __x, int __ex)
+  { return __builtin_scalbnl(__x, __ex); }
+
+  constexpr _Float128
+  tgamma(_Float128 __x)
+  { return __builtin_tgammal(__x); }
+
+  constexpr _Float128
+  trunc(_Float128 __x)
+  { return __builtin_truncl(__x); }
+#elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH)
+  constexpr _Float128
+  acosh(_Float128 __x)
+  { return __builtin_acoshf128(__x); }
+
+  constexpr _Float128
+  asinh(_Float128 __x)
+  { return __builtin_asinhf128(__x); }
+
+  constexpr _Float128
+  atanh(_Float128 __x)
+  { return __builtin_atanhf128(__x); }
+
+  constexpr _Float128
+  cbrt(_Float128 __x)
+  { return __builtin_cbrtf128(__x); }
+
+  constexpr _Float128
+  copysign(_Float128 __x, _Float128 __y)
+  { return __builtin_copysignf128(__x, __y); }
+
+  constexpr _Float128
+  erf(_Float128 __x)
+  { return __builtin_erff128(__x); }
+
+  constexpr _Float128
+  erfc(_Float128 __x)
+  { return __builtin_erfcf128(__x); }
+
+  constexpr _Float128
+  exp2(_Float128 __x)
+  { return __builtin_exp2f128(__x); }
+
+  constexpr _Float128
+  expm1(_Float128 __x)
+  { return __builtin_expm1f128(__x); }
+
+  constexpr _Float128
+  fdim(_Float128 __x, _Float128 __y)
+  { return __builtin_fdimf128(__x, __y); }
+
+  constexpr _Float128
+  fma(_Float128 __x, _Float128 __y, _Float128 __z)
+  { return __builtin_fmaf128(__x, __y, __z); }
+
+  constexpr _Float128
+  fmax(_Float128 __x, _Float128 __y)
+  { return __builtin_fmaxf128(__x, __y); }
+
+  constexpr _Float128
+  fmin(_Float128 __x, _Float128 __y)
+  { return __builtin_fminf128(__x, __y); }
+
+  constexpr _Float128
+  hypot(_Float128 __x, _Float128 __y)
+  { return __builtin_hypotf128(__x, __y); }
+
+  constexpr int
+  ilogb(_Float128 __x)
+  { return __builtin_ilogbf128(__x); }
+
+  constexpr _Float128
+  lgamma(_Float128 __x)
+  { return __builtin_lgammaf128(__x); }
+
+  constexpr long long
+  llrint(_Float128 __x)
+  { return __builtin_llrintf128(__x); }
+
+  constexpr long long
+  llround(_Float128 __x)
+  { return __builtin_llroundf128(__x); }
+
+  constexpr _Float128
+  log1p(_Float128 __x)
+  { return __builtin_log1pf128(__x); }
+
+  // DR 568.
+  constexpr _Float128
+  log2(_Float128 __x)
+  { return __builtin_log2f128(__x); }
+
+  constexpr _Float128
+  logb(_Float128 __x)
+  { return __builtin_logbf128(__x); }
+
+  constexpr long
+  lrint(_Float128 __x)
+  { return __builtin_lrintf128(__x); }
+
+  constexpr long
+  lround(_Float128 __x)
+  { return __builtin_lroundf128(__x); }
+
+  constexpr _Float128
+  nearbyint(_Float128 __x)
+  { return __builtin_nearbyintf128(__x); }
+
+  constexpr _Float128
+  nextafter(_Float128 __x, _Float128 __y)
+  { return __builtin_nextafterf128(__x, __y); }
+
+  constexpr _Float128
+  remainder(_Float128 __x, _Float128 __y)
+  { return __builtin_remainderf128(__x, __y); }
+
+  inline _Float128
+  remquo(_Float128 __x, _Float128 __y, int* __pquo)
+  { return __builtin_remquof128(__x, __y, __pquo); }
+
+  constexpr _Float128
+  rint(_Float128 __x)
+  { return __builtin_rintf128(__x); }
+
+  constexpr _Float128
+  round(_Float128 __x)
+  { return __builtin_roundf128(__x); }
+
+  constexpr _Float128
+  scalbln(_Float128 __x, long __ex)
+  { return __builtin_scalblnf128(__x, __ex); }
+
+  constexpr _Float128
+  scalbn(_Float128 __x, int __ex)
+  { return __builtin_scalbnf128(__x, __ex); }
+
+  constexpr _Float128
+  tgamma(_Float128 __x)
+  { return __builtin_tgammaf128(__x); }
+
+  constexpr _Float128
+  trunc(_Float128 __x)
+  { return __builtin_truncf128(__x); }
+#endif
+
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  constexpr __gnu_cxx::__bfloat16_t
+  acosh(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_acoshf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  asinh(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_asinhf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  atanh(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_atanhf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  cbrt(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_cbrtf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  copysign(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __gnu_cxx::__bfloat16_t(__builtin_copysignf(__x, __y)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  erf(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_erff(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  erfc(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_erfcf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  exp2(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_exp2f(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  expm1(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_expm1f(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  fdim(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __gnu_cxx::__bfloat16_t(__builtin_fdimf(__x, __y)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  fma(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y, __gnu_cxx::__bfloat16_t __z)
+  { return __gnu_cxx::__bfloat16_t(__builtin_fmaf(__x, __y, __z)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  fmax(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __gnu_cxx::__bfloat16_t(__builtin_fmaxf(__x, __y)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  fmin(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __gnu_cxx::__bfloat16_t(__builtin_fminf(__x, __y)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  hypot(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __gnu_cxx::__bfloat16_t(__builtin_hypotf(__x, __y)); }
+
+  constexpr int
+  ilogb(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_ilogbf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  lgamma(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_lgammaf(__x)); }
+
+  constexpr long long
+  llrint(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_llrintf(__x)); }
+
+  constexpr long long
+  llround(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_llroundf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  log1p(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_log1pf(__x)); }
+
+  // DR 568.
+  constexpr __gnu_cxx::__bfloat16_t
+  log2(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_log2f(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  logb(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_logbf(__x)); }
+
+  constexpr long
+  lrint(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_lrintf(__x)); }
+
+  constexpr long
+  lround(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_lroundf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  nearbyint(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_nearbyintf(__x)); }
+
+  // nextafter not implemented so far.
+
+  constexpr __gnu_cxx::__bfloat16_t
+  remainder(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+  { return __gnu_cxx::__bfloat16_t(__builtin_remainderf(__x, __y)); }
+
+  inline __gnu_cxx::__bfloat16_t
+  remquo(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y, int* __pquo)
+  { return __gnu_cxx::__bfloat16_t(__builtin_remquof(__x, __y, __pquo)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  rint(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_rintf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  round(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_roundf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  scalbln(__gnu_cxx::__bfloat16_t __x, long __ex)
+  { return __gnu_cxx::__bfloat16_t(__builtin_scalblnf(__x, __ex)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  scalbn(__gnu_cxx::__bfloat16_t __x, int __ex)
+  { return __gnu_cxx::__bfloat16_t(__builtin_scalbnf(__x, __ex)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  tgamma(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_tgammaf(__x)); }
+
+  constexpr __gnu_cxx::__bfloat16_t
+  trunc(__gnu_cxx::__bfloat16_t __x)
+  { return __gnu_cxx::__bfloat16_t(__builtin_truncf(__x)); }
+#endif
+
+
 #endif // _GLIBCXX_USE_C99_MATH_TR1
 #endif // C++11
 
@@ -1885,6 +3504,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using __type = __gnu_cxx::__promoted_t<_Tp, _Up, _Vp>;
       return std::__hypot3<__type>(__x, __y, __z);
     }
+
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  inline _Float16
+  hypot(_Float16 __x, _Float16 __y, _Float16 __z)
+  { return std::__hypot3<_Float16>(__x, __y, __z); }
+#endif
+
+#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  inline _Float32
+  hypot(_Float32 __x, _Float32 __y, _Float32 __z)
+  { return std::__hypot3<_Float32>(__x, __y, __z); }
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+  inline _Float64
+  hypot(_Float64 __x, _Float64 __y, _Float64 __z)
+  { return std::__hypot3<_Float64>(__x, __y, __z); }
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__) \
+    && (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \
+	|| defined(_GLIBCXX_HAVE_FLOAT128_MATH))
+  inline _Float128
+  hypot(_Float128 __x, _Float128 __y, _Float128 __z)
+  { return std::__hypot3<_Float128>(__x, __y, __z); }
+#endif
+
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  inline __gnu_cxx::__bfloat16_t
+  hypot(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y, __gnu_cxx::__bfloat16_t __z)
+  { return std::__hypot3<__gnu_cxx::__bfloat16_t>(__x, __y, __z); }
+#endif
+
 #endif // C++17
 
 #if __cplusplus >= 202002L
@@ -1928,6 +3580,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using __type = __gnu_cxx::__promoted_t<_Tp, _Up, _Vp>;
       return std::__lerp<__type>(__x, __y, __z);
     }
+
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  inline _Float16
+  lerp(_Float16 __x, _Float16 __y, _Float16 __z) noexcept
+  { return std::__lerp<_Float16>(__x, __y, __z); }
+#endif
+
+#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  inline _Float32
+  lerp(_Float32 __x, _Float32 __y, _Float32 __z) noexcept
+  { return std::__lerp<_Float32>(__x, __y, __z); }
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+  inline _Float64
+  lerp(_Float64 __x, _Float64 __y, _Float64 __z) noexcept
+  { return std::__lerp<_Float64>(__x, __y, __z); }
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__) \
+    && (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \
+	|| defined(_GLIBCXX_HAVE_FLOAT128_MATH))
+  inline _Float128
+  lerp(_Float128 __x, _Float128 __y, _Float128 __z) noexcept
+  { return std::__lerp<_Float128>(__x, __y, __z); }
+#endif
+
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  inline __gnu_cxx::__bfloat16_t
+  lerp(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y, __gnu_cxx::__bfloat16_t __z) noexcept
+  { return std::__lerp<__gnu_cxx::__bfloat16_t>(__x, __y, __z); }
+#endif
+
 #endif // C++20
 
 _GLIBCXX_END_NAMESPACE_VERSION
--- libstdc++-v3/include/ext/type_traits.h.jj	2022-01-11 22:31:41.519756736 +0100
+++ libstdc++-v3/include/ext/type_traits.h	2022-10-15 11:08:49.897857492 +0200
@@ -190,6 +190,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __promote<float>
     { typedef float __type; };
 
+#ifdef __STDCPP_FLOAT16_T__
+  template<>
+    struct __promote<_Float16>
+    { typedef _Float16 __type; };
+#endif
+
+#ifdef __STDCPP_FLOAT32_T__
+  template<>
+    struct __promote<_Float32>
+    { typedef _Float32 __type; };
+#endif
+
+#ifdef __STDCPP_FLOAT64_T__
+  template<>
+    struct __promote<_Float64>
+    { typedef _Float64 __type; };
+#endif
+
+#ifdef __STDCPP_FLOAT128_T__
+  template<>
+    struct __promote<_Float128>
+    { typedef _Float128 __type; };
+#endif
+
+#ifdef __STDCPP_BFLOAT16_T__
+  template<>
+    struct __promote<__gnu_cxx::__bfloat16_t>
+    { typedef __gnu_cxx::__bfloat16_t __type; };
+#endif
+
 #if __cpp_fold_expressions
 
   template<typename... _Tp>
--- libstdc++-v3/include/Makefile.am.jj	2022-10-03 22:45:46.092435137 +0200
+++ libstdc++-v3/include/Makefile.am	2022-10-14 22:32:55.413346435 +0200
@@ -95,6 +95,7 @@ std_headers = \
 	${std_srcdir}/stack \
 	${std_srcdir}/stacktrace \
 	${std_srcdir}/stdexcept \
+	${std_srcdir}/stdfloat \
 	${std_srcdir}/stop_token \
 	${std_srcdir}/streambuf \
 	${std_srcdir}/string \
--- libstdc++-v3/include/Makefile.in.jj	2022-10-11 22:35:26.387468956 +0200
+++ libstdc++-v3/include/Makefile.in	2022-10-14 22:32:55.413346435 +0200
@@ -452,6 +452,7 @@ std_freestanding = \
 @GLIBCXX_HOSTED_TRUE@	${std_srcdir}/stack \
 @GLIBCXX_HOSTED_TRUE@	${std_srcdir}/stacktrace \
 @GLIBCXX_HOSTED_TRUE@	${std_srcdir}/stdexcept \
+@GLIBCXX_HOSTED_TRUE@	${std_srcdir}/stdfloat \
 @GLIBCXX_HOSTED_TRUE@	${std_srcdir}/stop_token \
 @GLIBCXX_HOSTED_TRUE@	${std_srcdir}/streambuf \
 @GLIBCXX_HOSTED_TRUE@	${std_srcdir}/string \
--- libstdc++-v3/include/precompiled/stdc++.h.jj	2022-10-03 22:45:46.100435029 +0200
+++ libstdc++-v3/include/precompiled/stdc++.h	2022-10-14 22:32:55.413346435 +0200
@@ -228,6 +228,7 @@
 # include <stacktrace>
 #endif
 #include <stdatomic.h>
+#include <stdfloat>
 #endif
 
 #endif // HOSTED
--- libstdc++-v3/config/os/gnu-linux/os_defines.h.jj	2022-01-11 22:31:41.469757439 +0100
+++ libstdc++-v3/config/os/gnu-linux/os_defines.h	2022-10-14 22:32:55.414346421 +0200
@@ -49,6 +49,17 @@
 // version dynamically in case it has changed since libstdc++ was configured.
 #define _GLIBCXX_NO_OBSOLETE_ISINF_ISNAN_DYNAMIC __GLIBC_PREREQ(2,23)
 
+// Glibc 2.26 on i?86/x86-64/ia64/ppc64le added *f128 support.
+// Glibc 2.27 added it also on many other arches but those have IEEE quad
+// long double.
+#if __GLIBC_PREREQ(2, 26) \
+    && (defined(__i386__) || defined(__x86_64__) || defined (__ia64__) \
+	|| (defined(__powerpc__) && defined(_ARCH_PWR8) \
+	    && defined(__LITTLE_ENDIAN__) && (_CALL_ELF == 2) \
+	    && defined(__FLOAT128__)))
+# define _GLIBCXX_HAVE_FLOAT128_MATH 1
+#endif
+
 #if __GLIBC_PREREQ(2, 27)
 // Since glibc 2.27 pthread_self() is usable without linking to libpthread.
 # define _GLIBCXX_NATIVE_THREAD_ID pthread_self()
--- libstdc++-v3/testsuite/18_support/headers/stdfloat/types_std.cc.jj	2022-10-14 22:32:55.414346421 +0200
+++ libstdc++-v3/testsuite/18_support/headers/stdfloat/types_std.cc	2022-10-14 22:32:55.414346421 +0200
@@ -0,0 +1,40 @@
+// { dg-options "-std=gnu++2b" }
+// { dg-do compile { target c++23 } }
+
+// Copyright (C) 2022 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <stdfloat>
+
+namespace gnu
+{
+#if defined(__STDCPP_FLOAT16_T__)
+  typedef std::float16_t t1;
+#endif
+#if defined(__STDCPP_FLOAT32_T__)
+  typedef std::float32_t t2;
+#endif
+#if defined(__STDCPP_FLOAT64_T__)
+  typedef std::float64_t t3;
+#endif
+#if defined(__STDCPP_FLOAT128_T__)
+  typedef std::float128_t t4;
+#endif
+#if defined(__STDCPP_BFLOAT16_T__)
+  typedef std::bfloat16_t t5;
+#endif
+}
--- libstdc++-v3/testsuite/18_support/headers/limits/synopsis_cxx23.cc.jj	2022-10-14 22:32:55.415346407 +0200
+++ libstdc++-v3/testsuite/18_support/headers/limits/synopsis_cxx23.cc	2022-10-14 22:32:55.415346407 +0200
@@ -0,0 +1,43 @@
+// { dg-options "-std=gnu++2b" }
+// { dg-do compile { target c++23 } }
+// { dg-require-normal-namespace "" }
+
+// Copyright (C) 2022 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <limits>
+#include <stdfloat>
+
+namespace std {
+  template<class T> class numeric_limits;
+
+#if defined(__STDCPP_FLOAT16_T__)
+  template<> class numeric_limits<float16_t>;
+#endif
+#if defined(__STDCPP_FLOAT32_T__)
+  template<> class numeric_limits<float32_t>;
+#endif
+#if defined(__STDCPP_FLOAT64_T__)
+  template<> class numeric_limits<float64_t>;
+#endif
+#if defined(__STDCPP_FLOAT128_T__)
+  template<> class numeric_limits<float128_t>;
+#endif
+#if defined(__STDCPP_BFLOAT16_T__)
+  template<> class numeric_limits<bfloat16_t>;
+#endif
+}
--- libstdc++-v3/testsuite/26_numerics/headers/cmath/c99_classification_macros_c++23.cc.jj	2022-10-14 22:32:55.415346407 +0200
+++ libstdc++-v3/testsuite/26_numerics/headers/cmath/c99_classification_macros_c++23.cc	2022-10-14 22:32:55.415346407 +0200
@@ -0,0 +1,96 @@
+// Copyright (C) 2022 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do link { target c++23 } }
+// { dg-excess-errors "" { target uclibc } }
+
+#include <cmath>
+#include <stdfloat>
+
+void fpclassify() { }
+
+void isfinite() { }
+
+void isinf() { }
+
+void isnan() { }
+
+void isnormal() { }
+
+void signbit() { }
+
+void isgreater() { }
+
+void isgreaterequal() { }
+
+void isless() { }
+
+void islessequal() { }
+
+void islessgreater() { }
+
+void isunordered() { }
+
+#if _GLIBCXX_USE_C99_MATH
+template <typename _Tp, typename _Up = _Tp>
+  void test_c99_classify()
+  {
+    typedef _Tp fp_type_one;
+    typedef _Up fp_type_two;
+    fp_type_one f1 = _Tp(1.0);
+    fp_type_two f2 = _Up(3.0);
+    int resi;
+    volatile bool res;
+
+    resi = std::fpclassify(f1);
+    res = std::isfinite(f2);
+    res = std::isinf(f1);
+    res = std::isnan(f2);
+    res = std::isnormal(f1);
+    res = std::signbit(f2);
+    res = std::isgreater(f1, f2);
+    res = std::isgreaterequal(f1, f2);
+    res = std::isless(f1, f2);
+    res = std::islessequal(f1,f2);
+    res = std::islessgreater(f1, f2);
+    res = std::isunordered(f1, f2);
+    resi = resi; // Suppress unused warning.
+    res = res;
+  }
+#endif
+
+int main()
+{
+#if _GLIBCXX_USE_C99_MATH
+#ifdef __STDCPP_FLOAT16_T__
+  test_c99_classify<std::float16_t>();
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+  test_c99_classify<std::float32_t>();
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+  test_c99_classify<std::float64_t>();
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+  test_c99_classify<std::float128_t>();
+#endif
+#ifdef __STDCPP_BFLOAT16_T__
+  test_c99_classify<std::bfloat16_t>();
+#endif
+#endif
+  return 0;
+}
--- libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc.jj	2022-10-14 22:32:55.415346407 +0200
+++ libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc	2022-10-15 11:43:08.107500180 +0200
@@ -0,0 +1,146 @@
+// Copyright (C) 2022 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do link { target c++23 } }
+
+#include <stdfloat>
+#include <cmath>
+
+template <typename T>
+__attribute__((__noipa__)) void
+test_functions (T *p, int *q, long int *r, long long int *s)
+{
+  p[0] = std::acos (p[0]);
+  p[1] = std::asin (p[1]);
+  p[2] = std::atan (p[2]);
+  p[3] = std::cos (p[3]);
+  p[4] = std::sin (p[4]);
+  p[5] = std::tan (p[5]);
+  p[6] = std::acosh (p[6]);
+  p[7] = std::asinh (p[7]);
+  p[8] = std::atanh (p[8]);
+  p[9] = std::cosh (p[9]);
+  p[10] = std::sinh (p[10]);
+  p[11] = std::tanh (p[11]);
+  p[12] = std::exp (p[12]);
+  p[13] = std::exp2 (p[13]);
+  p[14] = std::expm1 (p[14]);
+  p[15] = std::log (p[15]);
+  p[16] = std::log10 (p[16]);
+  p[17] = std::log1p (p[17]);
+  p[18] = std::log2 (p[18]);
+  p[19] = std::logb (p[19]);
+  p[20] = std::cbrt (p[20]);
+  p[21] = std::fabs (p[21]);
+  p[22] = std::sqrt (p[22]);
+  p[23] = std::erf (p[23]);
+  p[24] = std::erfc (p[24]);
+  p[25] = std::lgamma (p[25]);
+  p[26] = std::tgamma (p[26]);
+  p[27] = std::ceil (p[27]);
+  p[28] = std::floor (p[28]);
+  p[29] = std::nearbyint (p[29]);
+  p[30] = std::rint (p[30]);
+  p[31] = std::round (p[31]);
+  p[32] = std::trunc (p[32]);
+  p[33] = std::atan2 (p[33], p[100]);
+  p[34] = std::hypot (p[34], p[101]);
+  p[35] = std::pow (p[35], p[102]);
+  p[36] = std::fmod (p[36], p[103]);
+  p[37] = std::remainder (p[37], p[104]);
+  p[38] = std::copysign (p[38], p[105]);
+//  p[39] = std::nextafter (p[39], p[106]);
+  p[40] = std::fdim (p[40], p[107]);
+  p[41] = std::fmax (p[41], p[108]);
+  p[42] = std::fmin (p[42], p[109]);
+  p[43] = std::atan2 (p[43], p[110]);
+  p[44] = std::frexp (p[44], q + 0);
+  q[1] = std::ilogb (p[45]);
+  p[46] = std::ldexp (p[46], q[2]);
+  p[47] = std::modf (p[47], p + 111);
+  p[48] = std::scalbn (p[48], q[3]);
+  p[49] = std::scalbln (p[49], r[0]);
+  p[50] = std::hypot (p[50], p[111], p[112]);
+  r[1] = std::lrint (p[51]);
+  s[0] = std::llrint (p[52]);
+  r[2] = std::lround (p[53]);
+  s[1] = std::llround (p[54]);
+  p[55] = std::remquo (p[55], p[113], q + 4);
+  p[56] = std::fma (p[56], p[114], p[115]);
+  p[57] = std::lerp (p[57], p[116], p[117]);
+  p[58] = std::assoc_laguerre (q[5], q[6], p[58]);
+  p[59] = std::assoc_legendre (q[7], q[8], p[59]);
+  p[60] = std::beta (p[60], p[118]);
+  p[61] = std::comp_ellint_1 (p[61]);
+  p[62] = std::comp_ellint_2 (p[62]);
+  p[63] = std::comp_ellint_3 (p[63], p[119]);
+  p[64] = std::cyl_bessel_i (p[64], p[120]);
+  p[65] = std::cyl_bessel_j (p[65], p[121]);
+  p[66] = std::cyl_bessel_k (p[66], p[122]);
+  p[67] = std::cyl_neumann (p[67], p[123]);
+  p[68] = std::ellint_1 (p[68], p[124]);
+  p[69] = std::ellint_2 (p[69], p[125]);
+  p[70] = std::ellint_3 (p[70], p[126], p[127]);
+  p[71] = std::expint (p[71]);
+  p[72] = std::hermite (q[9], p[72]);
+  p[73] = std::laguerre (q[10], p[73]);
+  p[74] = std::legendre (q[11], p[72]);
+  p[75] = std::riemann_zeta (p[75]);
+  p[76] = std::sph_bessel (q[12], p[76]);
+  p[77] = std::sph_legendre (q[13], q[14], p[77]);
+  p[78] = std::sph_neumann (q[15], q[16], p[78]);
+}
+
+int
+main ()
+{
+  int q[17] = {};
+  long int r[16] = {};
+  long long int s[16] = {};
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  {
+    std::float16_t p[128] = {};
+    test_functions (p, q, r, s);
+  }
+#endif
+#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  {
+    std::float32_t p[128] = {};
+    test_functions (p, q, r, s);
+  }
+#endif
+#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+  {
+    std::float64_t p[128] = {};
+    test_functions (p, q, r, s);
+  }
+#endif
+#if defined(__STDCPP_FLOAT128_T__) \
+    && (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \
+	|| defined(_GLIBCXX_HAVE_FLOAT128_MATH))
+  {
+    std::float128_t p[128] = {};
+    test_functions (p, q, r, s);
+  }
+#endif
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  {
+    std::bfloat16_t p[128] = {};
+    test_functions (p, q, r, s);
+  }
+#endif
+}
--- libstdc++-v3/testsuite/26_numerics/numbers/4.cc.jj	2022-10-14 22:32:55.415346407 +0200
+++ libstdc++-v3/testsuite/26_numerics/numbers/4.cc	2022-10-14 22:32:55.415346407 +0200
@@ -0,0 +1,122 @@
+// Copyright (C) 2022 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2b" }
+// { dg-do compile { target c++23 } }
+
+#include <numbers>
+#include <stdfloat>
+
+#if defined(__STDCPP_FLOAT16_T__)
+void
+test01()
+{
+  const std::float16_t* d1  = &std::numbers::e_v<std::float16_t>;
+  const std::float16_t* d2  = &std::numbers::log2e_v<std::float16_t>;
+  const std::float16_t* d3  = &std::numbers::log10e_v<std::float16_t>;
+  const std::float16_t* d4  = &std::numbers::pi_v<std::float16_t>;
+  const std::float16_t* d5  = &std::numbers::inv_pi_v<std::float16_t>;
+  const std::float16_t* d6  = &std::numbers::inv_sqrtpi_v<std::float16_t>;
+  const std::float16_t* d7  = &std::numbers::ln2_v<std::float16_t>;
+  const std::float16_t* d8  = &std::numbers::ln10_v<std::float16_t>;
+  const std::float16_t* d9  = &std::numbers::sqrt2_v<std::float16_t>;
+  const std::float16_t* d10 = &std::numbers::sqrt3_v<std::float16_t>;
+  const std::float16_t* d11 = &std::numbers::inv_sqrt3_v<std::float16_t>;
+  const std::float16_t* d12 = &std::numbers::egamma_v<std::float16_t>;
+  const std::float16_t* d13 = &std::numbers::phi_v<std::float16_t>;
+}
+#endif
+
+#if defined(__STDCPP_FLOAT32_T__)
+void
+test02()
+{
+  const std::float32_t* d1  = &std::numbers::e_v<std::float32_t>;
+  const std::float32_t* d2  = &std::numbers::log2e_v<std::float32_t>;
+  const std::float32_t* d3  = &std::numbers::log10e_v<std::float32_t>;
+  const std::float32_t* d4  = &std::numbers::pi_v<std::float32_t>;
+  const std::float32_t* d5  = &std::numbers::inv_pi_v<std::float32_t>;
+  const std::float32_t* d6  = &std::numbers::inv_sqrtpi_v<std::float32_t>;
+  const std::float32_t* d7  = &std::numbers::ln2_v<std::float32_t>;
+  const std::float32_t* d8  = &std::numbers::ln10_v<std::float32_t>;
+  const std::float32_t* d9  = &std::numbers::sqrt2_v<std::float32_t>;
+  const std::float32_t* d10 = &std::numbers::sqrt3_v<std::float32_t>;
+  const std::float32_t* d11 = &std::numbers::inv_sqrt3_v<std::float32_t>;
+  const std::float32_t* d12 = &std::numbers::egamma_v<std::float32_t>;
+  const std::float32_t* d13 = &std::numbers::phi_v<std::float32_t>;
+}
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__)
+void
+test03()
+{
+  const std::float64_t* d1  = &std::numbers::e_v<std::float64_t>;
+  const std::float64_t* d2  = &std::numbers::log2e_v<std::float64_t>;
+  const std::float64_t* d3  = &std::numbers::log10e_v<std::float64_t>;
+  const std::float64_t* d4  = &std::numbers::pi_v<std::float64_t>;
+  const std::float64_t* d5  = &std::numbers::inv_pi_v<std::float64_t>;
+  const std::float64_t* d6  = &std::numbers::inv_sqrtpi_v<std::float64_t>;
+  const std::float64_t* d7  = &std::numbers::ln2_v<std::float64_t>;
+  const std::float64_t* d8  = &std::numbers::ln10_v<std::float64_t>;
+  const std::float64_t* d9  = &std::numbers::sqrt2_v<std::float64_t>;
+  const std::float64_t* d10 = &std::numbers::sqrt3_v<std::float64_t>;
+  const std::float64_t* d11 = &std::numbers::inv_sqrt3_v<std::float64_t>;
+  const std::float64_t* d12 = &std::numbers::egamma_v<std::float64_t>;
+  const std::float64_t* d13 = &std::numbers::phi_v<std::float64_t>;
+}
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__)
+void
+test04()
+{
+  const std::float128_t* d1  = &std::numbers::e_v<std::float128_t>;
+  const std::float128_t* d2  = &std::numbers::log2e_v<std::float128_t>;
+  const std::float128_t* d3  = &std::numbers::log10e_v<std::float128_t>;
+  const std::float128_t* d4  = &std::numbers::pi_v<std::float128_t>;
+  const std::float128_t* d5  = &std::numbers::inv_pi_v<std::float128_t>;
+  const std::float128_t* d6  = &std::numbers::inv_sqrtpi_v<std::float128_t>;
+  const std::float128_t* d7  = &std::numbers::ln2_v<std::float128_t>;
+  const std::float128_t* d8  = &std::numbers::ln10_v<std::float128_t>;
+  const std::float128_t* d9  = &std::numbers::sqrt2_v<std::float128_t>;
+  const std::float128_t* d10 = &std::numbers::sqrt3_v<std::float128_t>;
+  const std::float128_t* d11 = &std::numbers::inv_sqrt3_v<std::float128_t>;
+  const std::float128_t* d12 = &std::numbers::egamma_v<std::float128_t>;
+  const std::float128_t* d13 = &std::numbers::phi_v<std::float128_t>;
+}
+#endif
+
+#if defined(__STDCPP_BFLOAT16_T__)
+void
+test05()
+{
+  const std::bfloat16_t* d1  = &std::numbers::e_v<std::bfloat16_t>;
+  const std::bfloat16_t* d2  = &std::numbers::log2e_v<std::bfloat16_t>;
+  const std::bfloat16_t* d3  = &std::numbers::log10e_v<std::bfloat16_t>;
+  const std::bfloat16_t* d4  = &std::numbers::pi_v<std::bfloat16_t>;
+  const std::bfloat16_t* d5  = &std::numbers::inv_pi_v<std::bfloat16_t>;
+  const std::bfloat16_t* d6  = &std::numbers::inv_sqrtpi_v<std::bfloat16_t>;
+  const std::bfloat16_t* d7  = &std::numbers::ln2_v<std::bfloat16_t>;
+  const std::bfloat16_t* d8  = &std::numbers::ln10_v<std::bfloat16_t>;
+  const std::bfloat16_t* d9  = &std::numbers::sqrt2_v<std::bfloat16_t>;
+  const std::bfloat16_t* d10 = &std::numbers::sqrt3_v<std::bfloat16_t>;
+  const std::bfloat16_t* d11 = &std::numbers::inv_sqrt3_v<std::bfloat16_t>;
+  const std::bfloat16_t* d12 = &std::numbers::egamma_v<std::bfloat16_t>;
+  const std::bfloat16_t* d13 = &std::numbers::phi_v<std::bfloat16_t>;
+}
+#endif
--- libstdc++-v3/testsuite/29_atomics/atomic_float/requirements_cxx23.cc.jj	2022-10-14 22:32:55.416346393 +0200
+++ libstdc++-v3/testsuite/29_atomics/atomic_float/requirements_cxx23.cc	2022-10-14 22:32:55.416346393 +0200
@@ -0,0 +1,112 @@
+// Copyright (C) 2022 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2b" }
+// { dg-do compile { target c++23 } }
+
+#include <atomic>
+#include <stdfloat>
+
+#if defined(__STDCPP_FLOAT16_T__)
+void
+test01()
+{
+  using A = std::atomic<std::float16_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::float16_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif
+
+#if defined(__STDCPP_FLOAT32_T__)
+void
+test02()
+{
+  using A = std::atomic<std::float32_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::float32_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__)
+void
+test03()
+{
+  using A = std::atomic<std::float64_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::float64_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__)
+void
+test04()
+{
+  using A = std::atomic<std::float128_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::float128_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif
+
+#if defined(__STDCPP_BFLOAT16_T__)
+void
+test05()
+{
+  using A = std::atomic<std::bfloat16_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::bfloat16_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif

	Jakub


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH] libstdc++, v2: Partial library support for std::float{16, 32, 64, 128}_t
  2022-10-17 13:07   ` Jonathan Wakely
  2022-10-17 16:25     ` [PATCH] libstdc++, v3: Partial library support for std::float{16,32,64,128}_t and std::bfloat16_t Jakub Jelinek
@ 2022-10-17 21:33     ` Joseph Myers
  2022-10-17 21:45       ` Jonathan Wakely
  2022-10-17 21:50       ` Jakub Jelinek
  1 sibling, 2 replies; 8+ messages in thread
From: Joseph Myers @ 2022-10-17 21:33 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: Jakub Jelinek, libstdc++, gcc-patches

On Mon, 17 Oct 2022, Jonathan Wakely via Gcc-patches wrote:

> > And I/O etc. support is missing, not sure I'm able to handle that and if it
> > is e.g. possible to keep that support out of libstdc++.so.6, because what
> > extended floating point types one has on a particular arch could change over
> > time (I mean e.g. bfloat16_t support or float16_t support can be added
> > etc.).
> 
> Yes, I think we can add the I/O functions as always_inline because all
> they're going to do is convert the argument to float, double, or long
> double and then call the existing overloads. There will be no new
> virtual functions.

As with fma, note that doing conversions from strings to floating-point is 
a case where doing the operation on float and then narrowing is 
technically incorrect because double rounding can occur (the rounded float 
result can be half way between two values of the narrower type, without 
that being the exact mathematical result) but the operation should be 
correctly rounding.  It's fine to use float or double operations in the 
other direction (floating-point to strings), of course.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH] libstdc++, v2: Partial library support for std::float{16, 32, 64, 128}_t
  2022-10-17 21:33     ` [RFC PATCH] libstdc++, v2: Partial library support for std::float{16, 32, 64, 128}_t Joseph Myers
@ 2022-10-17 21:45       ` Jonathan Wakely
  2022-10-17 21:50       ` Jakub Jelinek
  1 sibling, 0 replies; 8+ messages in thread
From: Jonathan Wakely @ 2022-10-17 21:45 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Jonathan Wakely, Jakub Jelinek, libstdc++, gcc-patches

On Mon, 17 Oct 2022 at 22:33, Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Mon, 17 Oct 2022, Jonathan Wakely via Gcc-patches wrote:
>
> > > And I/O etc. support is missing, not sure I'm able to handle that and if it
> > > is e.g. possible to keep that support out of libstdc++.so.6, because what
> > > extended floating point types one has on a particular arch could change over
> > > time (I mean e.g. bfloat16_t support or float16_t support can be added
> > > etc.).
> >
> > Yes, I think we can add the I/O functions as always_inline because all
> > they're going to do is convert the argument to float, double, or long
> > double and then call the existing overloads. There will be no new
> > virtual functions.
>
> As with fma, note that doing conversions from strings to floating-point is
> a case where doing the operation on float and then narrowing is
> technically incorrect because double rounding can occur (the rounded float
> result can be half way between two values of the narrower type, without
> that being the exact mathematical result) but the operation should be
> correctly rounding.  It's fine to use float or double operations in the
> other direction (floating-point to strings), of course.

Yes, this is called out in the C++23 draft:

[ Note: When the extended floating-point type has a floating-point
conversion rank that is not equal to the rank of any standard
floating-point type, then double rounding during the conversion can
result in inaccurate results. from_chars can be used in situations
where maximum accuracy is important. - end note ]

The alternative is an ABI break, which we didn't want to force on
implementors. For libstdc++ we're not going to break the ABI, so we're
going to live with the double rounding.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH] libstdc++, v2: Partial library support for std::float{16, 32, 64, 128}_t
  2022-10-17 21:33     ` [RFC PATCH] libstdc++, v2: Partial library support for std::float{16, 32, 64, 128}_t Joseph Myers
  2022-10-17 21:45       ` Jonathan Wakely
@ 2022-10-17 21:50       ` Jakub Jelinek
  1 sibling, 0 replies; 8+ messages in thread
From: Jakub Jelinek @ 2022-10-17 21:50 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Jonathan Wakely, libstdc++, gcc-patches

On Mon, Oct 17, 2022 at 09:33:02PM +0000, Joseph Myers wrote:
> > > And I/O etc. support is missing, not sure I'm able to handle that and if it
> > > is e.g. possible to keep that support out of libstdc++.so.6, because what
> > > extended floating point types one has on a particular arch could change over
> > > time (I mean e.g. bfloat16_t support or float16_t support can be added
> > > etc.).
> > 
> > Yes, I think we can add the I/O functions as always_inline because all
> > they're going to do is convert the argument to float, double, or long
> > double and then call the existing overloads. There will be no new
> > virtual functions.
> 
> As with fma, note that doing conversions from strings to floating-point is 
> a case where doing the operation on float and then narrowing is 
> technically incorrect because double rounding can occur (the rounded float 
> result can be half way between two values of the narrower type, without 
> that being the exact mathematical result) but the operation should be 
> correctly rounding.  It's fine to use float or double operations in the 
> other direction (floating-point to strings), of course.

That is true, but for istream and ostream that is what the standard
requires.  This is because there are required facets to be called and
they are available just for float/double/long double and it would be
an ABI change to allow more.
For extended floating point wider than long double it is implementation
defined what happens.
And otherwise, there is
[ Note: When the extended floating-point type has a floating-point
conversion rank that is not equal to the rank of any standard floating-point
type, then double rounding during the conversion can result in inaccurate
results.  from_chars can be used in situations where maximum accuracy is
important.  - end note ]
As for <charconv>, I think we'll need to implement both directions,
though perhaps the float16_t or bfloat16_t to_chars can be partly or fully
implemented using the float to_chars.

	Jakub


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] libstdc++, v3: Partial library support for std::float{16,32,64,128}_t and std::bfloat16_t
  2022-10-17 16:25     ` [PATCH] libstdc++, v3: Partial library support for std::float{16,32,64,128}_t and std::bfloat16_t Jakub Jelinek
@ 2022-10-18  9:18       ` Jonathan Wakely
  0 siblings, 0 replies; 8+ messages in thread
From: Jonathan Wakely @ 2022-10-18  9:18 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: libstdc++, gcc-patches

On Mon, 17 Oct 2022 at 17:26, Jakub Jelinek <jakub@redhat.com> wrote:
>
> Hi!
>
> On Mon, Oct 17, 2022 at 02:07:00PM +0100, Jonathan Wakely wrote:
> > Yes, that's now https://cplusplus.github.io/LWG/issue3790
> > The current proposed resolution is to just restore the C++20 functions
> > and not provide anything for the new types.
>
> Ok.
>
> > > If you want to have <cmath> done in a different way, e.g. the patch
> > > groups a lot of different function overloads by the floating point type,
> > > is that ok or do you want to have them one function at a time for all types,
> > > then next?
> >
> > No, I think this way makes more sense. Otherwise the line count in the
> > file will baloon with all the repeated #if #endif directives.
>
> Ok, changed.
> I've also changed this in limits and std_abs.h (ditto for
> _GLIBCXX_USE_CONSTEXPR, _GLIBCXX_USE_NOEXCEPT).
>
> There is one thing I'm not sure about but can be handled incrementally.
> What exactly is is_iec559 supposed to be?

Nobody really knows. numeric_limits is not well specified.

> Currently for float/double/long double/__float128 it seems to be defined
> to true if the type has Inf, qNaN and denormals.
> For std::float{16,32,64,128}_t even a note in the spec says they are
> true.
> Shall it be true only if the type is actually a IEEE754 type
> (binary16/32/64/128) and false otherwise, or that + the x86 extended type?

I think it makes sense to include _Float64x there too.

> Or if it is IEEE754-like and shall it be true also for
> std::bfloat16_t?

It does have NaNs and Infs, so I suppose if double double sets it to
true, then bfloat16_t could as well. I'm unsure what the right choice
is here though.

> Yet another case is the IBM double double, which has infinities, NaNs
> and denormals, but for that one it is hard to claim it is even IEEE754-like
> (variable precision).

Yeah, I think that has is_iec559 == true which is odd.

>
> > > I could try to handle <complex> too, but am kind of lost there.
> > > The paper dropped the explicit std::complex specializations, can they stay
> > > around as is and should new overloads be added for the
> > > _Float*/__gnu_cxx::__bfloat16_t types?
> >
> > The explicit specializations can stay, they do no harm.
>
> Ok.  Shall those specialization also get the P1467 changes for the ctors?
> Shall we also have specializations for the extended floating point types,
> or only conditionally (say when float is binary have _Complex _Float32
> so that we get better code)?

Oh I forgot the primary template doesn't use __complex__ for its data members.

Maybe we want to leave the primary template alone (even though it's
kinda useless for non-FP types) and add a new partial specialization
using concepts to constrain it for FP types:

template<typename _Tp> requires floating_point<_Tp>
class complex;

That would be used for all the new FP types, and we can use
__complex__ in there.
The existing explicit specializations for float/double/longdouble
would be preferred to this new partial specialization. We could
disable them for C++23, or leave them. We can decide that later
anyway.


>
> > I can take care of the <complex> changes.
>
> Ok.
>
> > > And I/O etc. support is missing, not sure I'm able to handle that and if it
> > > is e.g. possible to keep that support out of libstdc++.so.6, because what
> > > extended floating point types one has on a particular arch could change over
> > > time (I mean e.g. bfloat16_t support or float16_t support can be added
> > > etc.).
> >
> > Yes, I think we can add the I/O functions as always_inline because all
> > they're going to do is convert the argument to float, double, or long
> > double and then call the existing overloads. There will be no new
> > virtual functions.
> >
> > I can take care of that too.
>
> Thanks.
>
> Here is an updated patch that I'll test overnight (but can't commit
> until the builtins patch is reviewed as it depends on that;
> well, I could comment out the std::float128_t cmath support if
> long double is not IEEE quad and commit that only once the builtins
> patch is in).

Yes, please comment out the define in os_defines.h for now and push - thanks!


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2022-10-18  9:18 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-27  8:45 [RFC PATCH] libstdc++: Partial library support for std::float{16,32,64,128}_t Jakub Jelinek
2022-10-16 10:20 ` [RFC PATCH] libstdc++, v2: " Jakub Jelinek
2022-10-17 13:07   ` Jonathan Wakely
2022-10-17 16:25     ` [PATCH] libstdc++, v3: Partial library support for std::float{16,32,64,128}_t and std::bfloat16_t Jakub Jelinek
2022-10-18  9:18       ` Jonathan Wakely
2022-10-17 21:33     ` [RFC PATCH] libstdc++, v2: Partial library support for std::float{16, 32, 64, 128}_t Joseph Myers
2022-10-17 21:45       ` Jonathan Wakely
2022-10-17 21:50       ` Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).