Fix dbl-64 remainder sign of zero result (bug 19201).

For some large arguments, the dbl-64 implementation of remainder gives
zero results with the wrong sign, resulting from a subtraction that is
mathematically correct but does not guarantee that a zero result has
the sign of the first argument to remainder.  This patch adds an
appropriate check for this case, similar to other implementations of
remainder in the case of equality, and adds tests of remainder on
inputs already used to test remquo.

Tested for x86_64 and x86.

	[BZ #19201]
	* sysdeps/ieee754/dbl-64/e_remainder.c (__ieee754_remainder):
	Check for zero remainder in case of large exponents and ensure
	correct sign of result in that case.
	* math/libm-test.inc (remainder_test_data): Add more tests.
This commit is contained in:
Joseph Myers 2015-11-03 00:11:49 +00:00
parent 85422c2acb
commit 444ec6b8d8
4 changed files with 79 additions and 1 deletions

View File

@ -1,5 +1,11 @@
2015-11-02 Joseph Myers <joseph@codesourcery.com>
[BZ #19201]
* sysdeps/ieee754/dbl-64/e_remainder.c (__ieee754_remainder):
Check for zero remainder in case of large exponents and ensure
correct sign of result in that case.
* math/libm-test.inc (remainder_test_data): Add more tests.
[BZ #6799]
* math/s_nextafter.c: Include <errno.h>.
(__nextafter): Set errno on overflow and underflow.

3
NEWS
View File

@ -21,7 +21,8 @@ Version 2.23
18966, 18967, 18969, 18970, 18977, 18980, 18981, 18982, 18985, 19003,
19007, 19012, 19016, 19018, 19032, 19046, 19048, 19049, 19050, 19059,
19071, 19074, 19076, 19077, 19078, 19079, 19085, 19086, 19088, 19094,
19095, 19124, 19125, 19129, 19134, 19137, 19156, 19174, 19181, 19189.
19095, 19124, 19125, 19129, 19134, 19137, 19156, 19174, 19181, 19189,
19201.
* A defect in the malloc implementation, present since glibc 2.15 (2012) or
glibc 2.10 via --enable-experimental-malloc (2009), could result in the

View File

@ -10318,6 +10318,75 @@ static const struct test_ff_f_data remainder_test_data[] =
#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 56
TEST_ff_f (remainder, -0x1.80000000000002p1L, 2.0, 0x1.fffffffffffff8p-1L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
#endif
TEST_ff_f (remainder, 3419, 360, 179, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -3419, 360, -179, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, 3419, -360, 179, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -3419, -360, -179, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, max_value, max_value, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, max_value, -max_value, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, max_value, min_value, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, max_value, -min_value, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, max_value, min_subnorm_value, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, max_value, -min_subnorm_value, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -max_value, max_value, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -max_value, -max_value, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -max_value, min_value, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -max_value, -min_value, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -max_value, min_subnorm_value, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -max_value, -min_subnorm_value, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, min_value, max_value, min_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, min_value, -max_value, min_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, min_value, min_value, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, min_value, -min_value, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, min_value, min_subnorm_value, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, min_value, -min_subnorm_value, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -min_value, max_value, -min_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -min_value, -max_value, -min_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -min_value, min_value, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -min_value, -min_value, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -min_value, min_subnorm_value, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -min_value, -min_subnorm_value, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, min_subnorm_value, max_value, min_subnorm_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, min_subnorm_value, -max_value, min_subnorm_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, min_subnorm_value, min_value, min_subnorm_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, min_subnorm_value, -min_value, min_subnorm_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, min_subnorm_value, min_subnorm_value, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, min_subnorm_value, -min_subnorm_value, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -min_subnorm_value, max_value, -min_subnorm_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -min_subnorm_value, -max_value, -min_subnorm_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -min_subnorm_value, min_value, -min_subnorm_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -min_subnorm_value, -min_value, -min_subnorm_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -min_subnorm_value, min_subnorm_value, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -min_subnorm_value, -min_subnorm_value, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, 1, max_value, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, 1, -max_value, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, 1, max_value / 2, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, 1, -max_value / 2, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, 1, max_value / 4, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, 1, -max_value / 4, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, 1, max_value / 8, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, 1, -max_value / 8, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -1, max_value, -1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -1, -max_value, -1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -1, max_value / 2, -1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -1, -max_value / 2, -1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -1, max_value / 4, -1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -1, -max_value / 4, -1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -1, max_value / 8, -1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -1, -max_value / 8, -1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, max_value, max_value / 2, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, max_value, -max_value / 2, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -max_value, max_value / 2, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -max_value, -max_value / 2, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, 2, 1, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, 2, -1, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -2, 1, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -2, -1, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
};
static void

View File

@ -130,6 +130,8 @@ __ieee754_remainder (double x, double y)
d = fabs (z);
if (d <= fabs (d - y))
return z;
else if (d == y)
return 0.0 * x;
else
return (z > 0) ? z - y : z + y;
}