libstdc++: Partial library support for std::float{16,32,64,128}_t and std::bfloat16_t

The following patch is partial support for std::float{16,32,64,128}_t
and std::bfloat16_t in libstdc++.
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1467r9.html
says that <ostream>, <istream>, <charconv> and <complex>
need changes toom, but that isn't implemented so far.
In <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).
Also, this patch has the glibc 2.26+ std::float128_t support for platforms
where long double isn't IEEE quad format temporarily disabled
because it depends on
https://gcc.gnu.org/pipermail/gcc-patches/2022-October/603665.html
changes which aren't in yet.

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

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

	PR c++/106652
	* 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):
	Prepare for definition if glibc 2.26 and later implements *f128 APIs
	but comment out the actual definition for now.
	* 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.
This commit is contained in:
Jakub Jelinek 2022-10-18 11:37:13 +02:00
parent 4dda30e991
commit a23225fb4f
19 changed files with 2786 additions and 63 deletions

View file

@ -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()

View file

@ -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 \

View file

@ -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 \

View file

@ -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:

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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>

View file

@ -228,6 +228,7 @@
# include <stacktrace>
#endif
#include <stdatomic.h>
#include <stdfloat>
#endif
#endif // HOSTED

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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>

View file

@ -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
}

View file

@ -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
}

View file

@ -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;
}

View file

@ -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
}

View file

@ -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

View file

@ -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