about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2016-06-03 21:30:12 +0000
committerJoseph Myers <joseph@codesourcery.com>2016-06-03 21:30:12 +0000
commit8cbd1453ec1c59e54652edcd88256f4023ff77b9 (patch)
treefd75adff737c0b9172a5e59d2307d36e5190afe8
parentcfac4de69cc70fbd6364e58cf77891a7a30f2e09 (diff)
downloadglibc-8cbd1453ec1c59e54652edcd88256f4023ff77b9.tar.gz
glibc-8cbd1453ec1c59e54652edcd88256f4023ff77b9.tar.xz
glibc-8cbd1453ec1c59e54652edcd88256f4023ff77b9.zip
Fix x86/x86_64 nextafterl incrementing negative subnormals (bug 20205).
The x86 / x86_64 implementation of nextafterl (also used for
nexttowardl) produces incorrect results (NaNs) when negative
subnormals, the low 32 bits of whose mantissa are zero, are
incremented towards zero.  This patch fixes this by disabling the
logic to decrement the exponent in that case.

Tested for x86_64 and x86.

	[BZ #20205]
	* sysdeps/i386/fpu/s_nextafterl.c (__nextafterl): Do not adjust
	exponent when incrementing negative subnormal with low mantissa
	word zero.
	* math/libm-test.inc (nextafter_test_data) [TEST_COND_intel96]:
	Add another test.
-rw-r--r--ChangeLog9
-rw-r--r--math/libm-test.inc4
-rw-r--r--sysdeps/i386/fpu/s_nextafterl.c2
3 files changed, 14 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 94a95f3c00..3e16edf9e8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2016-06-03  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #20205]
+	* sysdeps/i386/fpu/s_nextafterl.c (__nextafterl): Do not adjust
+	exponent when incrementing negative subnormal with low mantissa
+	word zero.
+	* math/libm-test.inc (nextafter_test_data) [TEST_COND_intel96]:
+	Add another test.
+
 2016-06-03  Florian Weimer  <fweimer@redhat.com>
 
 	* libio/wstrops.c (_IO_wstr_overflow, enlarge_userbuf): Use
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 8c64c8e758..aaa01488ec 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -9965,6 +9965,10 @@ static const struct test_ff_f_data nextafter_test_data[] =
     TEST_ff_f (nextafter, -min_subnorm_value, 0, minus_zero, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
     TEST_ff_f (nextafter, -min_subnorm_value, minus_zero, minus_zero, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
 
+#if TEST_COND_intel96
+    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),
diff --git a/sysdeps/i386/fpu/s_nextafterl.c b/sysdeps/i386/fpu/s_nextafterl.c
index 188dc2129a..600ad7a8d3 100644
--- a/sysdeps/i386/fpu/s_nextafterl.c
+++ b/sysdeps/i386/fpu/s_nextafterl.c
@@ -86,7 +86,7 @@ long double __nextafterl(long double x, long double y)
 	    if(esy>=0||(esx>esy||((esx==esy)&&(hx>hy||((hx==hy)&&(lx>ly)))))){
 	      /* x < y, x -= ulp */
 		if(lx==0) {
-		    if (hx <= 0x80000000) {
+		    if (hx <= 0x80000000 && esx != 0xffff8000) {
 			esx -= 1;
 			hx = hx - 1;
 			if ((esx&0x7fff) > 0)