This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Test signs of NaNs in libm-test.inc where appropriate


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]