aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libstdc++-v3/include/c_global/cmath94
-rw-r--r--libstdc++-v3/include/std/limits7
-rw-r--r--libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc6
-rw-r--r--libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc125
4 files changed, 223 insertions, 9 deletions
diff --git a/libstdc++-v3/include/c_global/cmath b/libstdc++-v3/include/c_global/cmath
index 81635a0..555d644 100644
--- a/libstdc++-v3/include/c_global/cmath
+++ b/libstdc++-v3/include/c_global/cmath
@@ -2755,7 +2755,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
nearbyint(_Float16 __x)
{ return _Float16(__builtin_nearbyintf(__x)); }
- // nextafter not implemented so far.
+ inline _Float16
+ nextafter(_Float16 __x, _Float16 __y)
+ {
+#ifdef __INT16_TYPE__
+ using __float16_int_type = __INT16_TYPE__;
+#else
+ using __float16_int_type = short int;
+#endif
+ __float16_int_type __hx, __hy, __ix, __iy;
+ __builtin_memcpy(&__hx, &__x, sizeof(__x));
+ __builtin_memcpy(&__hy, &__y, sizeof(__x));
+ __ix = __hx & 0x7fff; // |x|
+ __iy = __hy & 0x7fff; // |y|
+ if (__ix > 0x7c00 || __iy > 0x7c00) // x or y is NaN
+ return __x + __y;
+ if (__x == __y)
+ return __y; // x == y, return y
+ if (__ix == 0) // x == 0
+ {
+ __hy = (__hy & 0x8000) | 1; // return +-__FLT16_DENORM_MIN__
+ __builtin_memcpy(&__x, &__hy, sizeof(__x));
+ __builtin_nextafterf(0.0f, 1.0f); // raise underflow
+ return __x;
+ }
+ if (__hx >= 0) // x > 0
+ {
+ if (__hx > __hy) // x > y, x -= ulp
+ --__hx;
+ else // x < y, x += ulp
+ ++__hx;
+ }
+ else // x < 0
+ {
+ if (__hy >= 0 || __hx > __hy) // x < y, x -= ulp
+ --__hx;
+ else // x > y, x += ulp
+ ++__hx;
+ }
+ __hy = __hx & 0x7c00;
+ if (__hy >= 0x7c00)
+ __builtin_nextafterf(__FLT_MAX__, __builtin_inff()); // overflow
+ else if (__hy < 0x0400)
+ __builtin_nextafterf(__FLT_MIN__, 0.0f); // underflow
+ __builtin_memcpy(&__x, &__hx, sizeof(__x));
+ return __x;
+ }
constexpr _Float16
remainder(_Float16 __x, _Float16 __y)
@@ -3426,7 +3471,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
nearbyint(__gnu_cxx::__bfloat16_t __x)
{ return __gnu_cxx::__bfloat16_t(__builtin_nearbyintf(__x)); }
- // nextafter not implemented so far.
+ inline __gnu_cxx::__bfloat16_t
+ nextafter(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
+ {
+#ifdef __INT16_TYPE__
+ using __bfloat16_int_type = __INT16_TYPE__;
+#else
+ using __bfloat16_int_type = short int;
+#endif
+ __bfloat16_int_type __hx, __hy, __ix, __iy;
+ __builtin_memcpy(&__hx, &__x, sizeof(__x));
+ __builtin_memcpy(&__hy, &__y, sizeof(__x));
+ __ix = __hx & 0x7fff; // |x|
+ __iy = __hy & 0x7fff; // |y|
+ if (__ix > 0x7f80 || __iy > 0x7f80) // x or y is NaN
+ return __x + __y;
+ if (__x == __y)
+ return __y; // x == y, return y
+ if (__ix == 0) // x == 0
+ {
+ __hy = (__hy & 0x8000) | 1; // return +-__BFLT16_DENORM_MIN__
+ __builtin_memcpy(&__x, &__hy, sizeof(__x));
+ __builtin_nextafterf(0.0f, 1.0f); // raise underflow
+ return __x;
+ }
+ if (__hx >= 0) // x > 0
+ {
+ if (__hx > __hy) // x > y, x -= ulp
+ --__hx;
+ else // x < y, x += ulp
+ ++__hx;
+ }
+ else // x < 0
+ {
+ if (__hy >= 0 || __hx > __hy) // x < y, x -= ulp
+ --__hx;
+ else // x > y, x += ulp
+ ++__hx;
+ }
+ __hy = __hx & 0x7f80;
+ if (__hy >= 0x7f80)
+ __builtin_nextafterf(__FLT_MAX__, __builtin_inff()); // overflow
+ else if (__hy < 0x0080)
+ __builtin_nextafterf(__FLT_MIN__, 0.0f); // underflow
+ __builtin_memcpy(&__x, &__hx, sizeof(__x));
+ return __x;
+ }
constexpr __gnu_cxx::__bfloat16_t
remainder(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
diff --git a/libstdc++-v3/include/std/limits b/libstdc++-v3/include/std/limits
index 61b6c3b..9dde9f3 100644
--- a/libstdc++-v3/include/std/limits
+++ b/libstdc++-v3/include/std/limits
@@ -1890,7 +1890,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#undef __glibcxx_long_double_traps
#undef __glibcxx_long_double_tinyness_before
-#if __cplusplus > 202202L
+#if __cplusplus > 202002L
#define __glibcxx_concat3_(P,M,S) P ## M ## S
#define __glibcxx_concat3(P,M,S) __glibcxx_concat3_ (P,M,S)
@@ -1924,8 +1924,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
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 int radix = __FLT_RADIX__; \
\
static constexpr _Float##BITSIZE \
epsilon() noexcept \
@@ -2023,7 +2022,7 @@ __glibcxx_float_n(128)
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 int radix = __FLT_RADIX__;
static constexpr __gnu_cxx::__bfloat16_t
epsilon() noexcept
diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc b/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc
index bc88662..190f8d1 100644
--- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc
+++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc
@@ -63,7 +63,7 @@ test_functions (T *p, int *q, long int *r, long long int *s)
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[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]);
@@ -102,13 +102,13 @@ test_functions (T *p, int *q, long int *r, long long int *s)
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]);
+ p[78] = std::sph_neumann (q[15], p[78]);
}
int
main ()
{
- int q[17] = {};
+ int q[16] = {};
long int r[16] = {};
long long int s[16] = {};
#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc b/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc
new file mode 100644
index 0000000..45aa3b7
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc
@@ -0,0 +1,125 @@
+// 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 run { target c++23 } }
+
+#include <stdfloat>
+#include <cmath>
+#include <limits>
+#include <testsuite_hooks.h>
+
+template <typename T>
+void
+test ()
+{
+ using lim = std::numeric_limits<T>;
+ T t0 = std::nextafter(T(-0.0), T(2.0));
+ VERIFY(t0 == lim::denorm_min());
+ T t1 = std::nextafter(T(), T(1.0));
+ VERIFY(t1 == lim::denorm_min());
+ T t2 = std::nextafter(T(), T());
+ VERIFY(t2 == T() && !std::signbit(t2));
+ T t3 = std::nextafter(lim::denorm_min(), T(-2.0));
+ VERIFY(t3 == T() && !std::signbit(t3));
+ T t4 = std::nextafter(lim::min(), T(-0.0));
+ VERIFY(std::fpclassify(t4) == FP_SUBNORMAL && t4 > T());
+ T t5 = std::nextafter(t4, T(1.0));
+ VERIFY(t5 == lim::min());
+ T t6 = std::nextafter(lim::min(), lim::infinity());
+ VERIFY(std::fpclassify(t6) == FP_NORMAL && t6 > lim::min());
+ T t7 = std::nextafter(t6, -lim::infinity());
+ VERIFY(t7 == lim::min());
+ T t8 = std::nextafter(T(16.0), T(16.5));
+ VERIFY(t8 > t7);
+ T t9 = std::nextafter(t8, T(15.5));
+ VERIFY(t9 == T(16.0));
+ T t10 = std::nextafter(lim::max(), T(-0.5));
+ VERIFY(std::fpclassify(t10) == FP_NORMAL && t10 < lim::max());
+ T t11 = std::nextafter(t10, lim::infinity());
+ VERIFY(t11 == lim::max());
+ T t12 = std::nextafter(t11, lim::infinity());
+ VERIFY(std::fpclassify(t12) == FP_INFINITE && !std::signbit(t12));
+ T t13 = std::nextafter(lim::infinity(), t12);
+ VERIFY(t13 == t12);
+ T t14 = std::nextafter(t13, T(1.0));
+ VERIFY(t14 == lim::max());
+ T t15 = std::nextafter(lim::quiet_NaN(), T());
+ VERIFY(std::fpclassify(t15) == FP_NAN);
+ T t16 = std::nextafter(T(17.0), lim::quiet_NaN());
+ VERIFY(std::fpclassify(t16) == FP_NAN);
+ T t17 = std::nextafter(T(), T(-0.0));
+ VERIFY(t17 == T() && std::signbit(t17));
+ T t20 = std::nextafter(T(-0.0), T(-2.0));
+ VERIFY(t20 == -lim::denorm_min());
+ T t21 = std::nextafter(T(), T(-1.0));
+ VERIFY(t21 == -lim::denorm_min());
+ T t22 = std::nextafter(T(-0.0), T(-0.0));
+ VERIFY(t22 == T() && std::signbit(t22));
+ T t23 = std::nextafter(-lim::denorm_min(), T(2.0));
+ VERIFY(t23 == T() && std::signbit(t23));
+ T t24 = std::nextafter(-lim::min(), T());
+ VERIFY(std::fpclassify(t24) == FP_SUBNORMAL && t24 < T());
+ T t25 = std::nextafter(t24, T(-1.0));
+ VERIFY(t25 == -lim::min());
+ T t26 = std::nextafter(-lim::min(), -lim::infinity());
+ VERIFY(std::fpclassify(t26) == FP_NORMAL && t26 < -lim::min());
+ T t27 = std::nextafter(t26, lim::infinity());
+ VERIFY(t27 == -lim::min());
+ T t28 = std::nextafter(T(-16.0), T(-16.5));
+ VERIFY(t28 < t27);
+ T t29 = std::nextafter(t28, T(-15.5));
+ VERIFY(t29 == T(-16.0));
+ T t30 = std::nextafter(-lim::max(), T(0.5));
+ VERIFY(std::fpclassify(t30) == FP_NORMAL && t30 > -lim::max());
+ T t31 = std::nextafter(t30, -lim::infinity());
+ VERIFY(t31 == -lim::max());
+ T t32 = std::nextafter(t31, -lim::infinity());
+ VERIFY(std::fpclassify(t32) == FP_INFINITE && std::signbit(t32));
+ T t33 = std::nextafter(-lim::infinity(), t32);
+ VERIFY(t33 == t32);
+ T t34 = std::nextafter(t33, T(-1.0));
+ VERIFY(t34 == -lim::max());
+ T t35 = std::nextafter(-lim::quiet_NaN(), T());
+ VERIFY(std::fpclassify(t35) == FP_NAN);
+ T t36 = std::nextafter(T(-17.0), lim::quiet_NaN());
+ VERIFY(std::fpclassify(t36) == FP_NAN);
+ T t37 = std::nextafter(T(-0.0), T());
+ VERIFY(t37 == T() && !std::signbit(t37));
+}
+
+int
+main ()
+{
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ test <std::float16_t>();
+#endif
+#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ test <std::float32_t>();
+#endif
+#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+ test <std::float64_t>();
+#endif
+#if defined(__STDCPP_FLOAT128_T__) \
+ && (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \
+ || defined(_GLIBCXX_HAVE_FLOAT128_MATH))
+ test <std::float128_t>();
+#endif
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ test <std::bfloat16_t>();
+#endif
+}