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.
Jakub
@@ -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
@@ -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
@@ -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.
@@ -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>
@@ -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
@@ -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 \
@@ -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 \
@@ -159,4 +159,5 @@
# include <stacktrace>
#endif
#include <stdatomic.h>
+#include <stdfloat>
#endif
@@ -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
+}
@@ -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
+}
@@ -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
@@ -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