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.
This commit is contained in:
Joseph Myers 2016-06-03 21:30:12 +00:00
parent cfac4de69c
commit 8cbd1453ec
3 changed files with 14 additions and 1 deletions

View File

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

View File

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

View File

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