Fix dbl-64/wordsize-64 remquo (bug 17569).
authorJoseph Myers <joseph@codesourcery.com>
Fri, 13 Feb 2015 21:54:44 +0000 (21:54 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Fri, 13 Feb 2015 21:54:44 +0000 (21:54 +0000)
The dbl-64/wordsize-64 remquo implementation follows similar logic to
various other implementations, but where that logic computes some
absolute values, it wrongly uses a previously computed bit-pattern for
the absolute value of the first argument, where actually it needs the
absolute value of the first argument mod 8 times the second.  This
patch fixes it to compute the correct absolute value.

The integer quotient result of remquo is only specified mod 8
(including its sign); architecture-specific versions may well vary in
what results they give for higher bits of that result (and indeed bug
17569 gives an example correct result from __builtin_remquo giving 9
for that result, where the particular glibc implementation used in
that bug report would give 1 after this fix).  Thus, this patch adapts
the tests of remquo to test that result only mod 8, to allow for such
variation when tests with higher quotient are included.

Tested for x86_64 and x86.

[BZ #17569]
* sysdeps/ieee754/dbl-64/wordsize-64/s_remquo.c (__remquo):
Compute absolute value of x as modified by fmod, not original
value of x.
* math/libm-test.inc (RUN_TEST_ffI_f1): Rename to
RUN_TEST_ffI_f1_mod8.  Check extra return value mod 8.
(RUN_TEST_LOOP_ffI_f1): Rename to RUN_TEST_LOOP_ffI_f1_mod8.  Call
RUN_TEST_ffI_f1_mod8.
(remquo_test_data): Add more tests.

ChangeLog
NEWS
math/libm-test.inc
sysdeps/ieee754/dbl-64/wordsize-64/s_remquo.c

index 4456bc90d642a76a16a1a7a50a097aa95358a7dd..74d1a1a48cfd21a85c6f5faae6b3ac85bc699448 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2015-02-13  Joseph Myers  <joseph@codesourcery.com>
+
+       [BZ #17569]
+       * sysdeps/ieee754/dbl-64/wordsize-64/s_remquo.c (__remquo):
+       Compute absolute value of x as modified by fmod, not original
+       value of x.
+       * math/libm-test.inc (RUN_TEST_ffI_f1): Rename to
+       RUN_TEST_ffI_f1_mod8.  Check extra return value mod 8.
+       (RUN_TEST_LOOP_ffI_f1): Rename to RUN_TEST_LOOP_ffI_f1_mod8.  Call
+       RUN_TEST_ffI_f1_mod8.
+       (remquo_test_data): Add more tests.
+
 2015-02-13  Roland McGrath  <roland@hack.frob.com>
 
        * sysdeps/init_array/pt-crti.S: New file.
diff --git a/NEWS b/NEWS
index b95f5e6d251b3334de1bf067aca8dbbe6364b1f0..89e48c868a4f42e2380e6f6dfaecc75d1b8b9fd2 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -9,8 +9,8 @@ Version 2.22
 
 * The following bugs are resolved with this release:
 
-  4719, 15467, 15790, 16560, 17912, 17932, 17944, 17949, 17964, 17965,
-  17967, 17969.
+  4719, 15467, 15790, 16560, 17569, 17912, 17932, 17944, 17949, 17964,
+  17965, 17967, 17969.
 \f
 Version 2.21
 
index aa7ba2b765f0b94edbaa35a8b36418de31fda021..2f3902a4451aa4f7d215bdcd838541c7e2b81c67 100644 (file)
@@ -1461,9 +1461,9 @@ struct test_fFF_11_data
                      (ARRAY)[i].RM_##ROUNDING_MODE.extra_test,         \
                      (ARRAY)[i].RM_##ROUNDING_MODE.extra_expected);    \
   ROUND_RESTORE_ ## ROUNDING_MODE
-#define RUN_TEST_ffI_f1(ARG_STR, FUNC_NAME, ARG1, ARG2, EXPECTED,      \
-                       EXCEPTIONS, EXTRA_VAR, EXTRA_TEST,              \
-                       EXTRA_EXPECTED)                                 \
+#define RUN_TEST_ffI_f1_mod8(ARG_STR, FUNC_NAME, ARG1, ARG2, EXPECTED, \
+                            EXCEPTIONS, EXTRA_VAR, EXTRA_TEST,         \
+                            EXTRA_EXPECTED)                            \
   do                                                                   \
     if (enable_test (EXCEPTIONS))                                      \
       {                                                                        \
@@ -1474,22 +1474,22 @@ struct test_fFF_11_data
                     EXPECTED, EXCEPTIONS);                             \
        EXTRA_OUTPUT_TEST_SETUP (ARG_STR, 1);                           \
        if (EXTRA_TEST)                                                 \
-         check_int (extra1_name, EXTRA_VAR, EXTRA_EXPECTED, 0);        \
+         check_int (extra1_name, (EXTRA_VAR) % 8, EXTRA_EXPECTED, 0);  \
        EXTRA_OUTPUT_TEST_CLEANUP (1);                                  \
        COMMON_TEST_CLEANUP;                                            \
       }                                                                        \
   while (0)
-#define RUN_TEST_LOOP_ffI_f1(FUNC_NAME, ARRAY, ROUNDING_MODE,          \
-                            EXTRA_VAR)                                 \
+#define RUN_TEST_LOOP_ffI_f1_mod8(FUNC_NAME, ARRAY, ROUNDING_MODE,     \
+                                 EXTRA_VAR)                            \
   IF_ROUND_INIT_ ## ROUNDING_MODE                                      \
     for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++)    \
-      RUN_TEST_ffI_f1 ((ARRAY)[i].arg_str, FUNC_NAME,                  \
-                      (ARRAY)[i].arg1, (ARRAY)[i].arg2,                \
-                      (ARRAY)[i].RM_##ROUNDING_MODE.expected,          \
-                      (ARRAY)[i].RM_##ROUNDING_MODE.exceptions,        \
-                      EXTRA_VAR,                                       \
-                      (ARRAY)[i].RM_##ROUNDING_MODE.extra_test,        \
-                      (ARRAY)[i].RM_##ROUNDING_MODE.extra_expected);   \
+      RUN_TEST_ffI_f1_mod8 ((ARRAY)[i].arg_str, FUNC_NAME,             \
+                           (ARRAY)[i].arg1, (ARRAY)[i].arg2,           \
+                           (ARRAY)[i].RM_##ROUNDING_MODE.expected,     \
+                           (ARRAY)[i].RM_##ROUNDING_MODE.exceptions,   \
+                           EXTRA_VAR,                                  \
+                           (ARRAY)[i].RM_##ROUNDING_MODE.extra_test,   \
+                           (ARRAY)[i].RM_##ROUNDING_MODE.extra_expected); \
   ROUND_RESTORE_ ## ROUNDING_MODE
 #define RUN_TEST_c_c(ARG_STR, FUNC_NAME, ARGR, ARGC, EXPR, EXPC,       \
                     EXCEPTIONS)                                        \
@@ -8759,6 +8759,11 @@ static const struct test_ffI_f1_data remquo_test_data[] =
 
     TEST_ffI_f1 (remquo, 5, 2, 1, 2, NO_INEXACT_EXCEPTION),
     TEST_ffI_f1 (remquo, 3, 2, -1, 2, NO_INEXACT_EXCEPTION),
+
+    TEST_ffI_f1 (remquo, 3419, 360, 179, 1, NO_INEXACT_EXCEPTION),
+    TEST_ffI_f1 (remquo, -3419, 360, -179, -1, NO_INEXACT_EXCEPTION),
+    TEST_ffI_f1 (remquo, 3419, -360, 179, -1, NO_INEXACT_EXCEPTION),
+    TEST_ffI_f1 (remquo, -3419, -360, -179, 1, NO_INEXACT_EXCEPTION),
   };
 
 static void
@@ -8766,7 +8771,7 @@ remquo_test (void)
 {
   int x;
 
-  ALL_RM_TEST (remquo, 1, remquo_test_data, RUN_TEST_LOOP_ffI_f1, END, x);
+  ALL_RM_TEST (remquo, 1, remquo_test_data, RUN_TEST_LOOP_ffI_f1_mod8, END, x);
 }
 
 static const struct test_f_f_data rint_test_data[] =
index 36fc37c134f5795f6d2701720a5fcfb45c73b67a..5b7142576a9df0a27e900221259ffb45e5a6ef58 100644 (file)
@@ -55,7 +55,7 @@ __remquo (double x, double y, int *quo)
       return zero * x;
     }
 
-  INSERT_WORDS64 (x, hx);
+  x = fabs (x);
   INSERT_WORDS64 (y, hy);
   cquo = 0;