summaryrefslogtreecommitdiff
path: root/math
diff options
context:
space:
mode:
authorRajalakshmi Srinivasaraghavan <raji@linux.vnet.ibm.com>2016-06-16 21:21:26 +0530
committerRajalakshmi Srinivasaraghavan <raji@linux.vnet.ibm.com>2016-06-16 21:37:45 +0530
commit41a359e22f3a85a570bd5fd94496d02959fe8394 (patch)
treeb07e8945a063a025f34f92e910bf8fb1e2e220d5 /math
parentf45eb078922a5c64343a8da2d17fec54c27f8704 (diff)
downloadglibc-41a359e22f3a85a570bd5fd94496d02959fe8394.tar.gz
Add nextup and nextdown math functions
TS 18661 adds nextup and nextdown functions alongside nextafter to provide support for float128 equivalent to it. This patch adds nextupl, nextup, nextupf, nextdownl, nextdown and nextdownf to libm before float128 support. The nextup functions return the next representable value in the direction of positive infinity and the nextdown functions return the next representable value in the direction of negative infinity. These are currently enabled as GNU extensions.
Diffstat (limited to 'math')
-rw-r--r--math/Makefile2
-rw-r--r--math/Versions4
-rw-r--r--math/bits/mathcalls.h7
-rw-r--r--math/libm-test.inc127
-rw-r--r--math/s_nextdown.c33
-rw-r--r--math/s_nextdownf.c29
-rw-r--r--math/s_nextdownl.c29
-rw-r--r--math/test-tgmath.c22
-rw-r--r--math/tgmath.h7
9 files changed, 253 insertions, 7 deletions
diff --git a/math/Makefile b/math/Makefile
index 6cd3cf1f65..4f141812ba 100644
--- a/math/Makefile
+++ b/math/Makefile
@@ -63,7 +63,7 @@ libm-calls = e_acos e_acosh e_asin e_atan2 e_atanh e_cosh e_exp e_fmod \
s_fma s_lrint s_llrint s_lround s_llround e_exp10 w_log2 \
s_issignaling $(calls:s_%=m_%) x2y2m1 k_casinh \
gamma_product k_standard lgamma_neg lgamma_product \
- w_lgamma_compat
+ w_lgamma_compat s_nextup s_nextdown
dbl-only-routines := branred doasin dosincos halfulp mpa mpatan2 \
mpatan mpexp mplog mpsqrt mptan sincos32 slowexp \
diff --git a/math/Versions b/math/Versions
index e6a597cf23..467d7ed3b5 100644
--- a/math/Versions
+++ b/math/Versions
@@ -210,4 +210,8 @@ libm {
# dynamic symbol for signgam but not __signgam.
lgamma; lgammaf; lgammal; __signgam;
}
+ GLIBC_2.24 {
+ nextup; nextupf; nextupl;
+ nextdown; nextdownf; nextdownl;
+ }
}
diff --git a/math/bits/mathcalls.h b/math/bits/mathcalls.h
index 9a7b3f0f18..e2cf49f627 100644
--- a/math/bits/mathcalls.h
+++ b/math/bits/mathcalls.h
@@ -294,6 +294,13 @@ __MATHCALLX (nextafter,, (_Mdouble_ __x, _Mdouble_ __y), (__const__));
__MATHCALLX (nexttoward,, (_Mdouble_ __x, long double __y), (__const__));
# endif
+#ifdef __USE_GNU
+/* Return X - epsilon. */
+__MATHCALL (nextdown,, (_Mdouble_ __x));
+/* Return X + epsilon. */
+__MATHCALL (nextup,, (_Mdouble_ __x));
+# endif
+
/* Return the remainder of integer divison X / Y with infinite precision. */
__MATHCALL (remainder,, (_Mdouble_ __x, _Mdouble_ __y));
diff --git a/math/libm-test.inc b/math/libm-test.inc
index d6cad6634c..17d65b40fd 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -10177,11 +10177,28 @@ static const struct test_ff_f_data nextafter_test_data[] =
TEST_ff_f (nextafter, -0x0.fffffffep-16382L, 0.0L, -0x0.fffffffdfffffffep-16382L, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
#endif
-#if MANT_DIG >= 64
- // XXX Enable once gcc is fixed.
- //TEST_ff_f (nextafter, 0x0.00000040000000000000p-16385L, -0.1L, 0x0.0000003ffffffff00000p-16385L),
+#if TEST_COND_binary32
+ TEST_ff_f (nextafter, 1.0, 2.0, 0x1.000002p0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (nextafter, 1.0, 0.9, 0x0.ffffffp0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (nextafter, -1.0, -2.0, -0x1.000002p0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (nextafter, -1.0, 2.0, -0x0.ffffffp0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+#endif
+#if TEST_COND_binary64
+ TEST_ff_f (nextafter, 1.0, 2.0, 0x1.0000000000001p+0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (nextafter, 1.0, 0.9, 0x1.fffffffffffffp-1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (nextafter, -1.0, -2.0, -0x1.0000000000001p+0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (nextafter, -1.0, 2.0, -0x1.fffffffffffffp-1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+#endif
+#if TEST_COND_m68k96 || TEST_COND_intel96
+ TEST_ff_f (nextafter, 1.0L, 2.0L, 0x8.0000000000000010p-3L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (nextafter, 1.0L, -2.0L, 0xf.fffffffffffffff0p-4L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (nextafter, -1.0L, -2.0L, -0x8.0000000000000010p-3L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (nextafter, -1.0L, 2.0L, -0xf.fffffffffffffff0p-4L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+#endif
+#if TEST_COND_m68k96
+ TEST_ff_f (nextafter, -0x0.fffffffep-16383L, 0.0L, -0x0.fffffffdfffffffep-16383L, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
#endif
-#if MANT_DIG == 106
+#if TEST_COND_ibm128
TEST_ff_f (nextafter, 1.0L, -10.0L, 1.0L-0x1p-106L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (nextafter, 1.0L, 10.0L, 1.0L+0x1p-105L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (nextafter, 1.0L-0x1p-106L, 10.0L, 1.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
@@ -10189,6 +10206,12 @@ static const struct test_ff_f_data nextafter_test_data[] =
TEST_ff_f (nextafter, -1.0L, 10.0L, -1.0L+0x1p-106L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (nextafter, -1.0L+0x1p-106L, -10.0L, -1.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
#endif
+#if TEST_COND_binary128
+ TEST_ff_f (nextafter, 1.0L, 10.0L, 0x1.0000000000000000000000000001p0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (nextafter, 1.0L, -10.0L, 0x1.ffffffffffffffffffffffffffffp-1L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (nextafter, -1.0L, 10.0L, -0x1.ffffffffffffffffffffffffffffp-1L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (nextafter, -1.0L, -10.0L, -0x1.0000000000000000000000000001p+0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+#endif
/* XXX We need the hexadecimal FP number representation here for further
tests. */
@@ -10199,6 +10222,100 @@ nextafter_test (void)
{
ALL_RM_TEST (nextafter, 1, nextafter_test_data, RUN_TEST_LOOP_ff_f, END);
}
+static const struct test_f_f_data nextup_test_data[] =
+ {
+ TEST_f_f (nextup, minus_zero, min_subnorm_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextup, 0, min_subnorm_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextup, -min_subnorm_value, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextup, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextup, plus_infty, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextup, minus_infty, -max_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextup, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextup, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextup, snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
+ TEST_f_f (nextup, -snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
+#if TEST_COND_binary32
+ TEST_f_f (nextup, 1.0, 0x1.000002p0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextup, -1.0, -0x0.ffffffp0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+#endif
+#if TEST_COND_binary64
+ TEST_f_f (nextup, 1.0, 0x1.0000000000001p+0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextup, -1.0, -0x1.fffffffffffffp-1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+#endif
+#if TEST_COND_m68k96 || TEST_COND_intel96
+ TEST_f_f (nextup, 1.0L, 0x8.0000000000000010p-3L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextup, -1.0L, -0xf.fffffffffffffff0p-4L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextup, 0xf.fffffffffffffff0p-4L, 1.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+#endif
+#if TEST_COND_intel96
+ TEST_f_f (nextup, -0x0.fffffffep-16382L, -0x0.fffffffdfffffffep-16382L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+#endif
+#if TEST_COND_m68k96
+ TEST_f_f (nextup, -0x0.fffffffep-16383L, -0x0.fffffffdfffffffep-16383L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+#endif
+#if TEST_COND_ibm128
+ TEST_f_f (nextup, 1.0L, 1.0L+0x1p-105L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextup, -1.0L-0x1p-105L, -1.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextup, -1.0L, -1.0L+0x1p-106L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+#endif
+#if TEST_COND_binary128
+ TEST_f_f (nextup, 1.0L, 0x1.0000000000000000000000000001p0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextup, -1.0L, -0x1.ffffffffffffffffffffffffffffp-1L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+#endif
+ };
+
+static void
+nextup_test (void)
+{
+ ALL_RM_TEST (nextup, 1, nextup_test_data, RUN_TEST_LOOP_f_f, END);
+}
+static const struct test_f_f_data nextdown_test_data[] =
+ {
+ TEST_f_f (nextdown, minus_zero, -min_subnorm_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextdown, 0, -min_subnorm_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextdown, min_subnorm_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextdown, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextdown, plus_infty, max_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextdown, minus_infty, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextdown, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextdown, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextdown, snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
+ TEST_f_f (nextdown, -snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
+#if TEST_COND_binary32
+ TEST_f_f (nextdown, 1.0, 0x0.ffffffp0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextdown, -1.0, -0x1.000002p0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+#endif
+#if TEST_COND_binary64
+ TEST_f_f (nextdown, 1.0, 0x1.fffffffffffffp-1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextdown, -1.0, -0x1.0000000000001p+0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+#endif
+#if TEST_COND_m68k96 || TEST_COND_intel96
+ TEST_f_f (nextdown, -1.0L, -0x8.0000000000000010p-3L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextdown, 1.0L, 0xf.fffffffffffffff0p-4L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextdown, 0x8.0000000000000010p-3L, 1.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+#endif
+#if TEST_COND_intel96
+ TEST_f_f (nextdown, -0x0.fffffffdfffffffep-16382L, -0x0.fffffffep-16382L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+#endif
+#if TEST_COND_m68k96
+ TEST_f_f (nextdown, -0x0.fffffffdfffffffep-16383L, -0x0.fffffffep-16383L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+#endif
+#if TEST_COND_ibm128
+ TEST_f_f (nextdown, -1.0L, -1.0L-0x1p-105L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextdown, 1.0L+0x1p-105L, 1.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextdown, 1.0L, 1.0L-0x1p-106L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+#endif
+#if TEST_COND_binary128
+ TEST_f_f (nextdown, 1.0L, 0x1.ffffffffffffffffffffffffffffp-1L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_f_f (nextdown, -1.0L, -0x1.0000000000000000000000000001p+0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+#endif
+ };
+
+static void
+nextdown_test (void)
+{
+ ALL_RM_TEST (nextdown, 1, nextdown_test_data, RUN_TEST_LOOP_f_f, END);
+}
/* Note, the second argument is always typed as long double. The j type
@@ -12335,6 +12452,8 @@ main (int argc, char **argv)
/* Manipulation functions: */
copysign_test ();
+ nextup_test();
+ nextdown_test();
nextafter_test ();
nexttoward_test ();
diff --git a/math/s_nextdown.c b/math/s_nextdown.c
new file mode 100644
index 0000000000..06fd1c9b12
--- /dev/null
+++ b/math/s_nextdown.c
@@ -0,0 +1,33 @@
+/* Return the greatest floating-point number less than X.
+ Copyright (C) 2016 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+/* Return the greatest floating-point number less than X. */
+double
+__nextdown (double x)
+{
+ return -__nextup (-x);
+}
+
+weak_alias (__nextdown, nextdown)
+#ifdef NO_LONG_DOUBLE
+strong_alias (__nextdown, __nextdownl)
+weak_alias (__nextdown, nextdownl)
+#endif
diff --git a/math/s_nextdownf.c b/math/s_nextdownf.c
new file mode 100644
index 0000000000..c0d4585b7f
--- /dev/null
+++ b/math/s_nextdownf.c
@@ -0,0 +1,29 @@
+/* Return the greatest floating-point number less than X.
+ Copyright (C) 2016 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+/* Return the greatest floating-point number less than X. */
+float
+__nextdownf (float x)
+{
+ return -__nextupf (-x);
+}
+
+weak_alias (__nextdownf, nextdownf)
diff --git a/math/s_nextdownl.c b/math/s_nextdownl.c
new file mode 100644
index 0000000000..e7607f5ad0
--- /dev/null
+++ b/math/s_nextdownl.c
@@ -0,0 +1,29 @@
+/* Return the greatest floating-point number less than X.
+ Copyright (C) 2016 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+/* Return the greatest floating-point number less than X. */
+long double
+__nextdownl (long double x)
+{
+ return -__nextupl (-x);
+}
+
+weak_alias (__nextdownl, nextdownl)
diff --git a/math/test-tgmath.c b/math/test-tgmath.c
index 0e978d17c4..70ab42881a 100644
--- a/math/test-tgmath.c
+++ b/math/test-tgmath.c
@@ -50,7 +50,7 @@ int count_cdouble;
int count_cfloat;
int count_cldouble;
-#define NCALLS 115
+#define NCALLS 119
#define NCALLS_INT 4
#define NCCALLS 47
@@ -274,7 +274,9 @@ F(compile_test) (void)
b = lgamma (lgamma (a));
a = rint (rint (x));
b = nextafter (nextafter (a, b), nextafter (c, x));
- a = nexttoward (nexttoward (x, a), c);
+ a = nextdown (nextdown (a));
+ b = nexttoward (nexttoward (x, a), c);
+ a = nextup (nextup (a));
b = remainder (remainder (a, b), remainder (c, x));
a = scalb (scalb (x, a), (TYPE) (6));
k = scalbn (a, 7) + scalbln (c, 10l);
@@ -777,6 +779,14 @@ TYPE
}
TYPE
+(F(nextdown)) (TYPE x)
+{
+ ++count;
+ P ();
+ return x;
+}
+
+TYPE
(F(nexttoward)) (TYPE x, long double y)
{
++count;
@@ -785,6 +795,14 @@ TYPE
}
TYPE
+(F(nextup)) (TYPE x)
+{
+ ++count;
+ P ();
+ return x;
+}
+
+TYPE
(F(remainder)) (TYPE x, TYPE y)
{
++count;
diff --git a/math/tgmath.h b/math/tgmath.h
index ea2b611f15..8916fbe39c 100644
--- a/math/tgmath.h
+++ b/math/tgmath.h
@@ -392,6 +392,13 @@
prevailing rounding mode. */
#define rint(Val) __TGMATH_UNARY_REAL_ONLY (Val, rint)
+#ifdef __USE_GNU
+/* Return X - epsilon. */
+# define nextdown(Val) __TGMATH_UNARY_REAL_ONLY (Val, nextdown)
+/* Return X + epsilon. */
+# define nextup(Val) __TGMATH_UNARY_REAL_ONLY (Val, nextup)
+#endif
+
/* Return X + epsilon if X < Y, X - epsilon if X > Y. */
#define nextafter(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, nextafter)
#define nexttoward(Val1, Val2) \