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]

Add libm-test support for ignored return value, add more lrint / llrint / lround / llround tests


For some libm functions on some inputs, the return value isn't
specified although the exceptions raised are.  Specifically, this
applies to lrint / llrint / lround / llround for infinite and NaN
arguments and overflowing finite arguments.

This patch, relative to a tree with
<https://sourceware.org/ml/libc-alpha/2013-11/msg00393.html> and
<https://sourceware.org/ml/libc-alpha/2013-11/msg00408.html> applied,
adds libm-test support for testing such cases, and adds such tests for
infinite and NaN arguments to those functions.  (Tests of overflowing
finite arguments to those functions, as in bug 15470, are still
needed.)

Tested x86_64 and x86.

2013-11-13  Joseph Myers  <joseph@codesourcery.com>

	* math/gen-libm-test.pl (show_exceptions): Take extra argument
	$ignore_result.
	(parse_args): Handle function results specified as IGNORE.
	* math/libm-test.inc (IGNORE_RESULT): New macro.
	(check_float_internal): Do not check numerical result if flag
	IGNORE_RESULT set.
	(check_complex): Pass through IGNORE_RESULT to second
	check_float_internal call.
	(check_int): Do not check numerical result if flag IGNORE_RESULT
	set.
	(check_long): Likewise.
	(check_bool): Likewise.
	(check_longlong): Likewise.
	(lrint_test_data): Add tests of infinite and NaN arguments.
	(lrint_tonearest_test_data): Likewise.
	(lrint_towardzero_test_data): Likewise.
	(lrint_downward_test_data): Likewise.
	(lrint_upward_test_data): Likewise.
	(llrint_test_data): Likewise.
	(llrint_tonearest_test_data): Likewise.
	(llrint_towardzero_test_data): Likewise.
	(llrint_downward_test_data): Likewise.
	(llrint_upward_test_data): Likewise.
	(lround_test_data): Likewise.
	(llround_test_data): Likewise.

diff --git a/math/gen-libm-test.pl b/math/gen-libm-test.pl
index b7083a2..98112ed 100755
--- a/math/gen-libm-test.pl
+++ b/math/gen-libm-test.pl
@@ -147,11 +147,12 @@ sub build_complex_beautify {
 # Return the text to put in an initializer for a test's exception
 # information.
 sub show_exceptions {
-  my ($exception) = @_;
+  my ($ignore_result, $exception) = @_;
+  $ignore_result = ($ignore_result ? "IGNORE_RESULT|" : "");
   if (defined $exception) {
-    return ", $exception";
+    return ", ${ignore_result}$exception";
   } else {
-    return ', 0';
+    return ", ${ignore_result}0";
   }
 }
 
@@ -162,6 +163,7 @@ sub parse_args {
   my ($current_arg, $cline, $i);
   my (@special);
   my ($call_args);
+  my ($ignore_result_any, $ignore_result_all);
 
   ($descr_args, $descr_res) = split /_/,$descr, 2;
 
@@ -249,20 +251,47 @@ sub parse_args {
   }
 
   @descr = split //,$descr_res;
+  $ignore_result_any = 0;
+  $ignore_result_all = 1;
   foreach (@descr) {
     if ($_ =~ /b|f|i|l|L/ ) {
-      $cline .= ", $args[$current_arg]";
+      my ($result) = $args[$current_arg];
+      if ($result eq "IGNORE") {
+	$ignore_result_any = 1;
+	$result = "0";
+      } else {
+	$ignore_result_all = 0;
+      }
+      $cline .= ", $result";
       $current_arg++;
     } elsif ($_ eq 'c') {
-      $cline .= ", $args[$current_arg], $args[$current_arg+1]";
+      my ($result1) = $args[$current_arg];
+      if ($result1 eq "IGNORE") {
+	$ignore_result_any = 1;
+	$result1 = "0";
+      } else {
+	$ignore_result_all = 0;
+      }
+      my ($result2) = $args[$current_arg + 1];
+      if ($result2 eq "IGNORE") {
+	$ignore_result_any = 1;
+	$result2 = "0";
+      } else {
+	$ignore_result_all = 0;
+      }
+      $cline .= ", $result1, $result2";
       $current_arg += 2;
     } elsif ($_ eq '1') {
       push @special, $args[$current_arg];
       ++$current_arg;
     }
   }
+  if ($ignore_result_any && !$ignore_result_all) {
+    die ("some but not all function results ignored\n");
+  }
   # Add exceptions.
-  $cline .= show_exceptions (($current_arg <= $#args)
+  $cline .= show_exceptions ($ignore_result_any,
+			     ($current_arg <= $#args)
 			     ? $args[$current_arg]
 			     : undef);
 
diff --git a/math/libm-test.inc b/math/libm-test.inc
index cbc9996..790fcc8 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -178,6 +178,8 @@ struct ulp_data
 #define ERRNO_UNCHANGED			0x1000
 #define ERRNO_EDOM			0x2000
 #define ERRNO_ERANGE			0x4000
+/* Flags generated by gen-libm-test.pl, not entered here manually.  */
+#define IGNORE_RESULT			0x8000
 
 /* Values underflowing only for float.  */
 #ifdef TEST_FLOAT
@@ -726,6 +728,8 @@ check_float_internal (const char *test_name, FLOAT computed, FLOAT expected,
 
   test_exceptions (test_name, exceptions);
   test_errno (test_name, errno_value, exceptions);
+  if (exceptions & IGNORE_RESULT)
+    goto out;
   FLOAT max_ulp = find_test_ulps (test_name);
   if (issignaling (computed) && issignaling (expected))
     ok = 1;
@@ -788,6 +792,7 @@ check_float_internal (const char *test_name, FLOAT computed, FLOAT expected,
     }
   update_stats (ok);
 
+ out:
   fpstack_test (test_name);
   errno = 0;
 }
@@ -827,9 +832,9 @@ check_complex (const char *test_name, __complex__ FLOAT computed,
   part_exp = __imag__ expected;
 
   /* Don't check again for exceptions or errno, just pass through the
-     zero/inf sign test.  */
+     other relevant flags.  */
   check_float_internal (str, part_comp, part_exp,
-			exception & IGNORE_ZERO_INF_SIGN,
+			exception & (IGNORE_ZERO_INF_SIGN | IGNORE_RESULT),
 			&imag_max_error);
   free (str);
 }
@@ -845,6 +850,8 @@ check_int (const char *test_name, int computed, int expected,
 
   test_exceptions (test_name, exceptions);
   test_errno (test_name, errno_value, exceptions);
+  if (exceptions & IGNORE_RESULT)
+    goto out;
   noTests++;
   if (computed == expected)
     ok = 1;
@@ -860,6 +867,7 @@ check_int (const char *test_name, int computed, int expected,
     }
 
   update_stats (ok);
+ out:
   fpstack_test (test_name);
   errno = 0;
 }
@@ -875,6 +883,8 @@ check_long (const char *test_name, long int computed, long int expected,
 
   test_exceptions (test_name, exceptions);
   test_errno (test_name, errno_value, exceptions);
+  if (exceptions & IGNORE_RESULT)
+    goto out;
   noTests++;
   if (computed == expected)
     ok = 1;
@@ -890,6 +900,7 @@ check_long (const char *test_name, long int computed, long int expected,
     }
 
   update_stats (ok);
+ out:
   fpstack_test (test_name);
   errno = 0;
 }
@@ -905,6 +916,8 @@ check_bool (const char *test_name, int computed, int expected,
 
   test_exceptions (test_name, exceptions);
   test_errno (test_name, errno_value, exceptions);
+  if (exceptions & IGNORE_RESULT)
+    goto out;
   noTests++;
   if ((computed == 0) == (expected == 0))
     ok = 1;
@@ -920,6 +933,7 @@ check_bool (const char *test_name, int computed, int expected,
     }
 
   update_stats (ok);
+ out:
   fpstack_test (test_name);
   errno = 0;
 }
@@ -936,6 +950,8 @@ check_longlong (const char *test_name, long long int computed,
 
   test_exceptions (test_name, exceptions);
   test_errno (test_name, errno_value, exceptions);
+  if (exceptions & IGNORE_RESULT)
+    goto out;
   noTests++;
   if (computed == expected)
     ok = 1;
@@ -951,6 +967,7 @@ check_longlong (const char *test_name, long long int computed,
     }
 
   update_stats (ok);
+ out:
   fpstack_test (test_name);
   errno = 0;
 }
@@ -10112,7 +10129,9 @@ static const struct test_f_l_data lrint_test_data[] =
     /* XXX this test is incomplete.  We need to have a way to specifiy
        the rounding method and test the critical cases.  So far, only
        unproblematic numbers are tested.  */
-    /* TODO: missing +/-Inf as well as qNaN tests.  */
+    TEST_f_l (lrint, plus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_l (lrint, minus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_l (lrint, qnan_value, IGNORE, INVALID_EXCEPTION),
     TEST_f_l (lrint, 0.0, 0, NO_INEXACT_EXCEPTION),
     TEST_f_l (lrint, minus_zero, 0, NO_INEXACT_EXCEPTION),
     TEST_f_l (lrint, 0.2L, 0, INEXACT_EXCEPTION),
@@ -10144,6 +10163,9 @@ lrint_test (void)
 
 static const struct test_f_l_data lrint_tonearest_test_data[] =
   {
+    TEST_f_l (lrint, plus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_l (lrint, minus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_l (lrint, qnan_value, IGNORE, INVALID_EXCEPTION),
     TEST_f_l (lrint, 0.0, 0, NO_INEXACT_EXCEPTION),
     TEST_f_l (lrint, minus_zero, 0, NO_INEXACT_EXCEPTION),
     TEST_f_l (lrint, 0.2L, 0, INEXACT_EXCEPTION),
@@ -10179,6 +10201,9 @@ lrint_test_tonearest (void)
 
 static const struct test_f_l_data lrint_towardzero_test_data[] =
   {
+    TEST_f_l (lrint, plus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_l (lrint, minus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_l (lrint, qnan_value, IGNORE, INVALID_EXCEPTION),
     TEST_f_l (lrint, 0.0, 0, NO_INEXACT_EXCEPTION),
     TEST_f_l (lrint, minus_zero, 0, NO_INEXACT_EXCEPTION),
     TEST_f_l (lrint, 0.2L, 0, INEXACT_EXCEPTION),
@@ -10214,6 +10239,9 @@ lrint_test_towardzero (void)
 
 static const struct test_f_l_data lrint_downward_test_data[] =
   {
+    TEST_f_l (lrint, plus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_l (lrint, minus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_l (lrint, qnan_value, IGNORE, INVALID_EXCEPTION),
     TEST_f_l (lrint, 0.0, 0, NO_INEXACT_EXCEPTION),
     TEST_f_l (lrint, minus_zero, 0, NO_INEXACT_EXCEPTION),
     TEST_f_l (lrint, 0.2L, 0, INEXACT_EXCEPTION),
@@ -10249,6 +10277,9 @@ lrint_test_downward (void)
 
 static const struct test_f_l_data lrint_upward_test_data[] =
   {
+    TEST_f_l (lrint, plus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_l (lrint, minus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_l (lrint, qnan_value, IGNORE, INVALID_EXCEPTION),
     TEST_f_l (lrint, 0.0, 0, NO_INEXACT_EXCEPTION),
     TEST_f_l (lrint, minus_zero, 0, NO_INEXACT_EXCEPTION),
     TEST_f_l (lrint, 0.2L, 1, INEXACT_EXCEPTION),
@@ -10287,7 +10318,9 @@ static const struct test_f_L_data llrint_test_data[] =
     /* XXX this test is incomplete.  We need to have a way to specifiy
        the rounding method and test the critical cases.  So far, only
        unproblematic numbers are tested.  */
-    /* TODO: missing +/-Inf as well as qNaN tests.  */
+    TEST_f_L (llrint, plus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_L (llrint, minus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_L (llrint, qnan_value, IGNORE, INVALID_EXCEPTION),
     TEST_f_L (llrint, 0.0, 0, NO_INEXACT_EXCEPTION),
     TEST_f_L (llrint, minus_zero, 0, NO_INEXACT_EXCEPTION),
     TEST_f_L (llrint, 0.2L, 0, INEXACT_EXCEPTION),
@@ -10423,6 +10456,9 @@ llrint_test (void)
 
 static const struct test_f_L_data llrint_tonearest_test_data[] =
   {
+    TEST_f_L (llrint, plus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_L (llrint, minus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_L (llrint, qnan_value, IGNORE, INVALID_EXCEPTION),
     TEST_f_L (llrint, 0.0, 0, NO_INEXACT_EXCEPTION),
     TEST_f_L (llrint, minus_zero, 0, NO_INEXACT_EXCEPTION),
     TEST_f_L (llrint, 0.2L, 0, INEXACT_EXCEPTION),
@@ -10558,6 +10594,9 @@ llrint_test_tonearest (void)
 
 static const struct test_f_L_data llrint_towardzero_test_data[] =
   {
+    TEST_f_L (llrint, plus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_L (llrint, minus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_L (llrint, qnan_value, IGNORE, INVALID_EXCEPTION),
     TEST_f_L (llrint, 0.0, 0, NO_INEXACT_EXCEPTION),
     TEST_f_L (llrint, minus_zero, 0, NO_INEXACT_EXCEPTION),
     TEST_f_L (llrint, 0.2L, 0, INEXACT_EXCEPTION),
@@ -10693,6 +10732,9 @@ llrint_test_towardzero (void)
 
 static const struct test_f_L_data llrint_downward_test_data[] =
   {
+    TEST_f_L (llrint, plus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_L (llrint, minus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_L (llrint, qnan_value, IGNORE, INVALID_EXCEPTION),
     TEST_f_L (llrint, 0.0, 0, NO_INEXACT_EXCEPTION),
     TEST_f_L (llrint, minus_zero, 0, NO_INEXACT_EXCEPTION),
     TEST_f_L (llrint, 0.2L, 0, INEXACT_EXCEPTION),
@@ -10824,6 +10866,9 @@ llrint_test_downward (void)
 
 static const struct test_f_L_data llrint_upward_test_data[] =
   {
+    TEST_f_L (llrint, plus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_L (llrint, minus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_L (llrint, qnan_value, IGNORE, INVALID_EXCEPTION),
     TEST_f_L (llrint, 0.0, 0, NO_INEXACT_EXCEPTION),
     TEST_f_L (llrint, minus_zero, 0, NO_INEXACT_EXCEPTION),
     TEST_f_L (llrint, 0.2L, 1, INEXACT_EXCEPTION),
@@ -11135,7 +11180,9 @@ logb_test_downward (void)
 
 static const struct test_f_l_data lround_test_data[] =
   {
-    /* TODO: missing +/-Inf as well as qNaN tests.  */
+    TEST_f_l (lround, plus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_l (lround, minus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_l (lround, qnan_value, IGNORE, INVALID_EXCEPTION),
     TEST_f_l (lround, 0, 0),
     TEST_f_l (lround, minus_zero, 0),
     TEST_f_l (lround, 0.2L, 0.0),
@@ -11182,7 +11229,9 @@ lround_test (void)
 
 static const struct test_f_L_data llround_test_data[] =
   {
-    /* TODO: missing +/-Inf as well as qNaN tests.  */
+    TEST_f_L (llround, plus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_L (llround, minus_infty, IGNORE, INVALID_EXCEPTION),
+    TEST_f_L (llround, qnan_value, IGNORE, INVALID_EXCEPTION),
     TEST_f_L (llround, 0, 0),
     TEST_f_L (llround, minus_zero, 0),
     TEST_f_L (llround, 0.2L, 0.0),

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