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]

Support sNaN testing in libm-test.inc [committed]


This patch adds support in libm-test.inc for tests with signaling NaN
arguments.  gen-libm-test.pl is made to set a flag TEST_SNAN for such
tests, so that they can be disabled automatically when sNaN testing
isn't supported for a given type (at present, for float and double on
32-bit x86 because it's unpredictable when a value might be loaded
into a floating-point register and so automatically converted to long
double with sNaNs converted to quiet NaNs).  -fsignaling-nans is used
where needed.

Tests are added for classification macros, as a starting point; this
is deliberately more conservative than Thomas's patch
<https://sourceware.org/ml/libc-ports/2013-04/msg00008.html>, to allow
more tests to be added, and issues exposed fixed, bit by bit.

Tested for x86_64 and x86.  Committed.

2016-05-26  Joseph Myers  <joseph@codesourcery.com>

	* math/libm-test.inc: Update comment about NaN testing.
	(TEST_SNAN): New macro.
	(snan_value): Likewise.
	(enable_test): Disable tests of sNaNs when SNAN_TESTS fails.
	(fpclassify_test_data): Add sNaN tests.
	(isfinite_test_data): Likewise.
	(isinf_test_data): Likewise.
	(isnan_test_data): Likewise.
	(isnormal_test_data): Likewise.
	(issignaling_test_data): Likewise.
	(signbit_test_data): Likewise.
	* math/gen-libm-test.pl (%beautify): Add snan_value.
	(show_exceptions): Add argument $test_snan.
	(parse_args): Handle snan_value as non-finite.  Update call to
	show_exceptions.
	* math/Makefile (libm-test-no-inline-cflags): Add
	-fsignaling-nans.

diff --git a/math/Makefile b/math/Makefile
index 57c3ec1..f0265bb 100644
--- a/math/Makefile
+++ b/math/Makefile
@@ -187,7 +187,14 @@ CFLAGS-test-float-vlen8-wrappers.c = $(float-vlen8-arch-ext-cflags)
 CFLAGS-test-float-vlen16.c = $(libm-test-vec-cflags)
 CFLAGS-test-float-vlen16-wrappers.c = $(float-vlen16-arch-ext-cflags)
 
-libm-test-no-inline-cflags = -fno-inline -ffloat-store -fno-builtin
+# The no-inline tests use -fsignaling-nans, and thereby use the
+# versions of classification macros that support sNaNs.  The inline
+# function tests use the versions of classification macros that may
+# raise spurious exceptions for sNaNs, but also do not test for
+# exceptions.  Thus both versions of the classification macros are
+# validated.
+libm-test-no-inline-cflags = -fno-inline -ffloat-store -fno-builtin \
+			     -fsignaling-nans
 libm-test-finite-cflags = $(libm-test-no-inline-cflags) \
 			  -U__FINITE_MATH_ONLY__ -D__FINITE_MATH_ONLY__=1
 CFLAGS-test-float.c = $(libm-test-no-inline-cflags)
diff --git a/math/gen-libm-test.pl b/math/gen-libm-test.pl
index 17f17f7..c42a53b 100755
--- a/math/gen-libm-test.pl
+++ b/math/gen-libm-test.pl
@@ -59,6 +59,7 @@ use vars qw (%auto_tests);
     "minus_infty" => "-inf",
     "plus_infty" => "inf",
     "qnan_value" => "qNaN",
+    "snan_value" => "sNaN",
   );
 
 
@@ -141,13 +142,14 @@ sub build_complex_beautify {
 # Return the text to put in an initializer for a test's exception
 # information.
 sub show_exceptions {
-  my ($ignore_result, $non_finite, $exception) = @_;
+  my ($ignore_result, $non_finite, $test_snan, $exception) = @_;
   $ignore_result = ($ignore_result ? "IGNORE_RESULT|" : "");
   $non_finite = ($non_finite ? "NON_FINITE|" : "");
+  $test_snan = ($test_snan ? "TEST_SNAN|" : "");
   if (defined $exception) {
-    return ", ${ignore_result}${non_finite}$exception";
+    return ", ${ignore_result}${non_finite}${test_snan}$exception";
   } else {
-    return ", ${ignore_result}${non_finite}0";
+    return ", ${ignore_result}${non_finite}${test_snan}0";
   }
 }
 
@@ -163,7 +165,7 @@ sub parse_args {
   my (@plus_oflow, @minus_oflow, @plus_uflow, @minus_uflow);
   my (@errno_plus_oflow, @errno_minus_oflow);
   my (@errno_plus_uflow, @errno_minus_uflow);
-  my ($non_finite);
+  my ($non_finite, $test_snan);
 
   ($descr_args, $descr_res) = split /_/,$descr, 2;
 
@@ -310,10 +312,12 @@ sub parse_args {
     }
     # Determine whether any arguments or results, for any rounding
     # mode, are non-finite.
-    $non_finite = ($args =~ /qnan_value|plus_infty|minus_infty/);
+    $non_finite = ($args =~ /qnan_value|snan_value|plus_infty|minus_infty/);
+    $test_snan = ($args =~ /snan_value/);
     # Add exceptions.
     $cline_res .= show_exceptions ($ignore_result_any,
 				   $non_finite,
+				   $test_snan,
 				   ($current_arg <= $#args_res)
 				   ? $args_res[$current_arg]
 				   : undef);
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 169be7e..7d29700 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -79,8 +79,7 @@
    against.  These implemented tests should check all cases that are
    specified in ISO C99.
 
-   NaN values: There exist signalling and quiet NaNs.  This implementation
-   only uses quiet NaN as parameter.  The payload of NaNs is not examined.
+   NaN values: The payload of NaNs is not examined.
 
    Inline functions: Inlining functions should give an improvement in
    speed - but not in precission.  The inlined functions return
@@ -182,6 +181,7 @@ struct ulp_data
 /* Flags generated by gen-libm-test.pl, not entered here manually.  */
 #define IGNORE_RESULT			0x20000
 #define NON_FINITE			0x40000
+#define TEST_SNAN			0x80000
 
 /* Values underflowing only for float.  */
 #ifdef TEST_FLOAT
@@ -311,6 +311,7 @@ static int ignore_max_ulp;	/* Should we ignore max_ulp?  */
 #define minus_infty	CHOOSE (-HUGE_VALL, -HUGE_VAL, -HUGE_VALF,	\
 				-HUGE_VALL, -HUGE_VAL, -HUGE_VALF)
 #define qnan_value	FUNC (__builtin_nan) ("")
+#define snan_value	FUNC (__builtin_nans) ("")
 #define max_value	CHOOSE (LDBL_MAX, DBL_MAX, FLT_MAX,	\
 				LDBL_MAX, DBL_MAX, FLT_MAX)
 #define min_value	CHOOSE (LDBL_MIN, DBL_MIN, FLT_MIN,	\
@@ -1050,6 +1051,8 @@ enable_test (int exceptions)
     return 0;
   if (TEST_FINITE && (exceptions & NON_FINITE) != 0)
     return 0;
+  if (!SNAN_TESTS (FLOAT) && (exceptions & TEST_SNAN) != 0)
+    return 0;
   return 1;
 }
 
@@ -7691,6 +7694,8 @@ static const struct test_f_i_data fpclassify_test_data[] =
   {
     TEST_f_i (fpclassify, qnan_value, FP_NAN, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_i (fpclassify, -qnan_value, FP_NAN, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_i (fpclassify, snan_value, FP_NAN, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_i (fpclassify, -snan_value, FP_NAN, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_i (fpclassify, plus_infty, FP_INFINITE, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_i (fpclassify, minus_infty, FP_INFINITE, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_i (fpclassify, plus_zero, FP_ZERO, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
@@ -7932,6 +7937,8 @@ static const struct test_f_i_data isfinite_test_data[] =
     TEST_f_b (isfinite, minus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_b (isfinite, qnan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_b (isfinite, -qnan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_b (isfinite, snan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_b (isfinite, -snan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
   };
 
 static void
@@ -8032,6 +8039,8 @@ static const struct test_f_i_data isinf_test_data[] =
     TEST_f_b (isinf, minus_infty, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_b (isinf, qnan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_b (isinf, -qnan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_b (isinf, snan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_b (isinf, -snan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
   };
 
 static void
@@ -8160,6 +8169,8 @@ static const struct test_f_i_data isnan_test_data[] =
     TEST_f_b (isnan, minus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_b (isnan, qnan_value, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_b (isnan, -qnan_value, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_b (isnan, snan_value, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_b (isnan, -snan_value, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
   };
 
 static void
@@ -8183,6 +8194,8 @@ static const struct test_f_i_data isnormal_test_data[] =
     TEST_f_b (isnormal, minus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_b (isnormal, qnan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_b (isnormal, -qnan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_b (isnormal, snan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_b (isnormal, -snan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
   };
 
 static void
@@ -8206,6 +8219,8 @@ static const struct test_f_i_data issignaling_test_data[] =
     TEST_f_b (issignaling, minus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_b (issignaling, qnan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_b (issignaling, -qnan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_b (issignaling, snan_value, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_b (issignaling, -snan_value, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
   };
 
 static void
@@ -11245,6 +11260,8 @@ static const struct test_f_i_data signbit_test_data[] =
     TEST_f_b (signbit, minus_infty, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_b (signbit, qnan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_b (signbit, -qnan_value, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_b (signbit, snan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_b (signbit, -snan_value, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
     /* signbit (x) != 0 for x < 0.  */
     TEST_f_b (signbit, -1, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),

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