This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Fix dbl-64 remainder sign of zero result (bug 19201) [committed]
- From: Joseph Myers <joseph at codesourcery dot com>
- To: <libc-alpha at sourceware dot org>
- Date: Tue, 3 Nov 2015 00:12:44 +0000
- Subject: Fix dbl-64 remainder sign of zero result (bug 19201) [committed]
- Authentication-results: sourceware.org; auth=none
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. Committed.
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.
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 1267b81..2645ccc 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -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
diff --git a/sysdeps/ieee754/dbl-64/e_remainder.c b/sysdeps/ieee754/dbl-64/e_remainder.c
index 7f3a02b..4818091 100644
--- a/sysdeps/ieee754/dbl-64/e_remainder.c
+++ b/sysdeps/ieee754/dbl-64/e_remainder.c
@@ -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;
}
--
Joseph S. Myers
joseph@codesourcery.com