This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Test signs of NaNs in libm-test.inc where appropriate
- From: "Joseph S. Myers" <joseph at codesourcery dot com>
- To: <libc-alpha at sourceware dot org>
- Date: Thu, 14 Nov 2013 16:51:33 +0000
- Subject: Test signs of NaNs in libm-test.inc where appropriate
- Authentication-results: sourceware.org; auth=none
libm-test.inc does not check the signs of NaN results. This is
correct for most functions, where the sign of a NaN result is
unspecified, but for fabs and copysign the sign of the result is
specified even when it's a NaN. This patch (relative to a tree with
<https://sourceware.org/ml/libc-alpha/2013-11/msg00393.html>,
<https://sourceware.org/ml/libc-alpha/2013-11/msg00408.html> and
<https://sourceware.org/ml/libc-alpha/2013-11/msg00409.html> applied)
adds a TEST_NAN_SIGN flag tests can use to check the signs of NaN
results, uses it for fabs and copysign tests as applicable, and adds
more tests of NaN inputs for those functions and signbit.
Tested x86_64 and x86.
2013-11-14 Joseph Myers <joseph@codesourcery.com>
* math/libm-test.inc (TEST_NAN_SIGN): New macro.
(NO_TEST_INLINE): Update value.
(ERRNO_UNCHANGED): Likewise.
(ERRNO_EDOM): Likewise.
(ERRNO_ERANGE): Likewise.
(IGNORE_RESULT): Likewise.
(check_float_internal): Check signs of NaN results if
TEST_NAN_SIGN used.
(check_complex): Pass TEST_NAN_SIGN flag through to second
check_float_internal call.
(copysign_test_data): Add tests with quiet NaNs as second
argument. Use TEST_NAN_SIGN.
(fabs_test_data): Add test of negative quiet NaN argument. Use
TEST_NAN_SIGN.
(signbit_test_data): Add tests of quiet NaN argument.
* math/gen-libm-test.pl (parse_args): Handle TEST_NAN_SIGN.
diff --git a/math/gen-libm-test.pl b/math/gen-libm-test.pl
index 98112ed..bd701d7 100755
--- a/math/gen-libm-test.pl
+++ b/math/gen-libm-test.pl
@@ -218,7 +218,7 @@ sub parse_args {
# consistency check
if ($current_arg == $#args) {
die ("wrong number of arguments")
- unless ($args[$current_arg] =~ /EXCEPTION|ERRNO|IGNORE_ZERO_INF_SIGN|NO_TEST_INLINE/);
+ unless ($args[$current_arg] =~ /EXCEPTION|ERRNO|IGNORE_ZERO_INF_SIGN|TEST_NAN_SIGN|NO_TEST_INLINE/);
} elsif ($current_arg < $#args) {
die ("wrong number of arguments");
} elsif ($current_arg > ($#args+1)) {
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 790fcc8..0c88abc 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -173,13 +173,14 @@ struct ulp_data
#define EXCEPTIONS_OK INVALID_EXCEPTION_OK+DIVIDE_BY_ZERO_EXCEPTION_OK
/* Some special test flags, passed together with exceptions. */
#define IGNORE_ZERO_INF_SIGN 0x400
-#define NO_TEST_INLINE 0x800
+#define TEST_NAN_SIGN 0x800
+#define NO_TEST_INLINE 0x1000
/* Indicate errno settings required or disallowed. */
-#define ERRNO_UNCHANGED 0x1000
-#define ERRNO_EDOM 0x2000
-#define ERRNO_ERANGE 0x4000
+#define ERRNO_UNCHANGED 0x2000
+#define ERRNO_EDOM 0x4000
+#define ERRNO_ERANGE 0x8000
/* Flags generated by gen-libm-test.pl, not entered here manually. */
-#define IGNORE_RESULT 0x8000
+#define IGNORE_RESULT 0x10000
/* Values underflowing only for float. */
#ifdef TEST_FLOAT
@@ -732,11 +733,29 @@ check_float_internal (const char *test_name, FLOAT computed, FLOAT expected,
goto out;
FLOAT max_ulp = find_test_ulps (test_name);
if (issignaling (computed) && issignaling (expected))
- ok = 1;
+ {
+ if ((exceptions & TEST_NAN_SIGN) != 0
+ && signbit (computed) != signbit (expected))
+ {
+ ok = 0;
+ printf ("signaling NaN has wrong sign.\n");
+ }
+ else
+ ok = 1;
+ }
else if (issignaling (computed) || issignaling (expected))
ok = 0;
else if (isnan (computed) && isnan (expected))
- ok = 1;
+ {
+ if ((exceptions & TEST_NAN_SIGN) != 0
+ && signbit (computed) != signbit (expected))
+ {
+ ok = 0;
+ printf ("quiet NaN has wrong sign.\n");
+ }
+ else
+ ok = 1;
+ }
else if (isinf (computed) && isinf (expected))
{
/* Test for sign of infinities. */
@@ -834,7 +853,9 @@ check_complex (const char *test_name, __complex__ FLOAT computed,
/* Don't check again for exceptions or errno, just pass through the
other relevant flags. */
check_float_internal (str, part_comp, part_exp,
- exception & (IGNORE_ZERO_INF_SIGN | IGNORE_RESULT),
+ exception & (IGNORE_ZERO_INF_SIGN
+ | TEST_NAN_SIGN
+ | IGNORE_RESULT),
&imag_max_error);
free (str);
}
@@ -6815,11 +6836,15 @@ static const struct test_ff_f_data copysign_test_data[] =
TEST_ff_f (copysign, minus_zero, plus_infty, 0, NO_INEXACT_EXCEPTION),
TEST_ff_f (copysign, minus_zero, minus_zero, minus_zero, NO_INEXACT_EXCEPTION),
- /* XXX More correctly we would have to check the sign of the NaN. */
- TEST_ff_f (copysign, qnan_value, 0, qnan_value, NO_INEXACT_EXCEPTION),
- TEST_ff_f (copysign, qnan_value, minus_zero, qnan_value, NO_INEXACT_EXCEPTION),
- TEST_ff_f (copysign, -qnan_value, 0, qnan_value, NO_INEXACT_EXCEPTION),
- TEST_ff_f (copysign, -qnan_value, minus_zero, qnan_value, NO_INEXACT_EXCEPTION),
+ TEST_ff_f (copysign, 0, qnan_value, 0, NO_INEXACT_EXCEPTION),
+ TEST_ff_f (copysign, 0, -qnan_value, minus_zero, NO_INEXACT_EXCEPTION),
+ TEST_ff_f (copysign, minus_zero, qnan_value, 0, NO_INEXACT_EXCEPTION),
+ TEST_ff_f (copysign, minus_zero, -qnan_value, minus_zero, NO_INEXACT_EXCEPTION),
+
+ TEST_ff_f (copysign, qnan_value, 0, qnan_value, NO_INEXACT_EXCEPTION|TEST_NAN_SIGN),
+ TEST_ff_f (copysign, qnan_value, minus_zero, -qnan_value, NO_INEXACT_EXCEPTION|TEST_NAN_SIGN),
+ TEST_ff_f (copysign, -qnan_value, 0, qnan_value, NO_INEXACT_EXCEPTION|TEST_NAN_SIGN),
+ TEST_ff_f (copysign, -qnan_value, minus_zero, -qnan_value, NO_INEXACT_EXCEPTION|TEST_NAN_SIGN),
};
static void
@@ -8196,7 +8221,8 @@ static const struct test_f_f_data fabs_test_data[] =
TEST_f_f (fabs, plus_infty, plus_infty, NO_INEXACT_EXCEPTION),
TEST_f_f (fabs, minus_infty, plus_infty, NO_INEXACT_EXCEPTION),
- TEST_f_f (fabs, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
+ TEST_f_f (fabs, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|TEST_NAN_SIGN),
+ TEST_f_f (fabs, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|TEST_NAN_SIGN),
TEST_f_f (fabs, 38.0, 38.0, NO_INEXACT_EXCEPTION),
TEST_f_f (fabs, -M_El, M_El, NO_INEXACT_EXCEPTION),
@@ -13347,11 +13373,12 @@ scalbln_test (void)
static const struct test_f_i_data signbit_test_data[] =
{
- /* TODO: missing qNaN tests. */
TEST_f_b (signbit, 0, 0, NO_INEXACT_EXCEPTION),
TEST_f_b (signbit, minus_zero, 1, NO_INEXACT_EXCEPTION),
TEST_f_b (signbit, plus_infty, 0, NO_INEXACT_EXCEPTION),
TEST_f_b (signbit, minus_infty, 1, NO_INEXACT_EXCEPTION),
+ TEST_f_b (signbit, qnan_value, 0, NO_INEXACT_EXCEPTION),
+ TEST_f_b (signbit, -qnan_value, 1, NO_INEXACT_EXCEPTION),
/* signbit (x) != 0 for x < 0. */
TEST_f_b (signbit, -1, 1, NO_INEXACT_EXCEPTION),
--
Joseph S. Myers
joseph@codesourcery.com