]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix ldbl-128ibm remainderl equality test for zero low part (bug 19677).
authorJoseph Myers <joseph@codesourcery.com>
Tue, 8 Mar 2016 00:27:21 +0000 (00:27 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Tue, 8 Mar 2016 00:27:21 +0000 (00:27 +0000)
The ldbl-128ibm implementation of remainderl has logic resulting in
incorrect tests for equality of the absolute values of the arguments
in the case of zero low parts.  If the low parts are both zero but
with different signs, this can wrongly cause equal arguments to be
treated as different, resulting in turn in incorrect signs of zero
result in nondefault rounding modes arising from the subtractions done
when the arguments are not equal.

This patch fixes the logic to convert -0 low parts into +0 before the
comparison (remquo already has separate logic to deal with signs of
zero results, so doesn't need such a change).  Tests are added for
remainderl and remquol similar to that for fmodl, and based on a
refactoring of it, since the bug depends on low parts which should not
be relied upon in tests not setting the representation explicitly
(although in fact the bug shows up in test-ldouble with current GCC).
Tested for powerpc.

[BZ #19677]
* sysdeps/ieee754/ldbl-128ibm/e_remainderl.c
(__ieee754_remainderl): Put zero low parts in canonical form.
* sysdeps/ieee754/ldbl-128ibm/test-fmodrem-ldbl-128ibm.c: New
file.  Based on
sysdeps/ieee754/ldbl-128ibm/test-fmodl-ldbl-128ibm.c.
* sysdeps/ieee754/ldbl-128ibm/test-fmodl-ldbl-128ibm.c: Replace
with wrapper round test-fmodrem-ldbl-128ibm.c.
* sysdeps/ieee754/ldbl-128ibm/test-remainderl-ldbl-128ibm.c: New
file.
* sysdeps/ieee754/ldbl-128ibm/test-remquol-ldbl-128ibm.c:
Likewise.
* sysdeps/ieee754/ldbl-128ibm/Makefile (tests): Add
test-remainderl-ldbl-128ibm and test-remquol-ldbl-128ibm.

ChangeLog
sysdeps/ieee754/ldbl-128ibm/Makefile
sysdeps/ieee754/ldbl-128ibm/e_remainderl.c
sysdeps/ieee754/ldbl-128ibm/test-fmodl-ldbl-128ibm.c
sysdeps/ieee754/ldbl-128ibm/test-fmodrem-ldbl-128ibm.c [new file with mode: 0644]
sysdeps/ieee754/ldbl-128ibm/test-remainderl-ldbl-128ibm.c [new file with mode: 0644]
sysdeps/ieee754/ldbl-128ibm/test-remquol-ldbl-128ibm.c [new file with mode: 0644]

index 50e32e0853994ad3dee10e21f520b7d474b99d7d..3cb82bc1151cbf8f32048b4e4a9e0bf7c450a665 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2016-03-08  Joseph Myers  <joseph@codesourcery.com>
+
+       [BZ #19677]
+       * sysdeps/ieee754/ldbl-128ibm/e_remainderl.c
+       (__ieee754_remainderl): Put zero low parts in canonical form.
+       * sysdeps/ieee754/ldbl-128ibm/test-fmodrem-ldbl-128ibm.c: New
+       file.  Based on
+       sysdeps/ieee754/ldbl-128ibm/test-fmodl-ldbl-128ibm.c.
+       * sysdeps/ieee754/ldbl-128ibm/test-fmodl-ldbl-128ibm.c: Replace
+       with wrapper round test-fmodrem-ldbl-128ibm.c.
+       * sysdeps/ieee754/ldbl-128ibm/test-remainderl-ldbl-128ibm.c: New
+       file.
+       * sysdeps/ieee754/ldbl-128ibm/test-remquol-ldbl-128ibm.c:
+       Likewise.
+       * sysdeps/ieee754/ldbl-128ibm/Makefile (tests): Add
+       test-remainderl-ldbl-128ibm and test-remquol-ldbl-128ibm.
+
 2016-03-07  Florian Weimer  <fweimer@redhat.com>
 
        [BZ #19610]
index b633172721d506663599d53678ae321174a03bce..6242edda41050dd8ac844d50d95e0aa28c13f450 100644 (file)
@@ -10,5 +10,6 @@ $(objpfx)tst-strtold-ldbl-128ibm: $(libm)
 endif
 
 ifeq ($(subdir),math)
-tests += test-fmodl-ldbl-128ibm
+tests += test-fmodl-ldbl-128ibm test-remainderl-ldbl-128ibm \
+        test-remquol-ldbl-128ibm
 endif
index 1dc59a4785a8c5ec6df642f3aae9ab2294160e0f..68b8fb3519087934749eb6ec97f0ca385c645310 100644 (file)
@@ -46,6 +46,10 @@ __ieee754_remainderl(long double x, long double p)
        hp &= 0x7fffffffffffffffLL;
        lx ^= sx;
        hx &= 0x7fffffffffffffffLL;
+       if (lp == 0x8000000000000000ULL)
+         lp = 0;
+       if (lx == 0x8000000000000000ULL)
+         lx = 0;
 
     /* purge off exception values */
        if(hp==0) return (x*p)/(x*p);   /* p = 0 */
index 3717c90abaa1a85cbcbec76a3ced1821634284a6..73d4bc1632e8541c49d4f69507d5a662d12f4dec 100644 (file)
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <float.h>
-#include <math.h>
-#include <stdio.h>
-
-union u
-{
-  long double ld;
-  double d[2];
-};
-
-volatile union u p1 = { .d = { DBL_MIN, 0.0 } };
-volatile union u p2 = { .d = { DBL_MIN, -0.0 } };
-volatile union u m1 = { .d = { -DBL_MIN, 0.0 } };
-volatile union u m2 = { .d = { -DBL_MIN, -0.0 } };
-
-static int
-test_fmodl (const char *s, long double x, long double y, long double expected)
-{
-  volatile long double r;
-  r = fmodl (x, y);
-  if (r != expected || copysignl (1.0, r) != copysignl (1.0, expected))
-    {
-      printf ("FAIL: fmodl (%s)\n", s);
-      return 1;
-    }
-  else
-    {
-      printf ("PASS: fmodl (%s)\n", s);
-      return 0;
-    }
-}
-
-#define TEST_FMODL(a, b, e) test_fmodl (#a ", " #b, a, b, e)
-
-static int
-do_test (void)
-{
-  int result = 0;
-  result |= TEST_FMODL (p1.ld, p1.ld, 0.0L);
-  result |= TEST_FMODL (p1.ld, p2.ld, 0.0L);
-  result |= TEST_FMODL (p1.ld, m1.ld, 0.0L);
-  result |= TEST_FMODL (p1.ld, m2.ld, 0.0L);
-  result |= TEST_FMODL (p2.ld, p1.ld, 0.0L);
-  result |= TEST_FMODL (p2.ld, p2.ld, 0.0L);
-  result |= TEST_FMODL (p2.ld, m1.ld, 0.0L);
-  result |= TEST_FMODL (p2.ld, m2.ld, 0.0L);
-  result |= TEST_FMODL (m1.ld, p1.ld, -0.0L);
-  result |= TEST_FMODL (m1.ld, p2.ld, -0.0L);
-  result |= TEST_FMODL (m1.ld, m1.ld, -0.0L);
-  result |= TEST_FMODL (m1.ld, m2.ld, -0.0L);
-  result |= TEST_FMODL (m2.ld, p1.ld, -0.0L);
-  result |= TEST_FMODL (m2.ld, p2.ld, -0.0L);
-  result |= TEST_FMODL (m2.ld, m1.ld, -0.0L);
-  result |= TEST_FMODL (m2.ld, m2.ld, -0.0L);
-  return result;
-}
-
-#define TEST_FUNCTION do_test ()
-#include "../../../test-skeleton.c"
+#define FUNC fmodl
+#define SETUP
+#include "test-fmodrem-ldbl-128ibm.c"
diff --git a/sysdeps/ieee754/ldbl-128ibm/test-fmodrem-ldbl-128ibm.c b/sysdeps/ieee754/ldbl-128ibm/test-fmodrem-ldbl-128ibm.c
new file mode 100644 (file)
index 0000000..4e1640c
--- /dev/null
@@ -0,0 +1,84 @@
+/* Test for ldbl-128ibm fmodl etc. handling of equal values.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <fenv.h>
+#include <float.h>
+#include <math.h>
+#include <stdio.h>
+
+/* FUNC is defined to be the name of the function to test.  */
+#define STRX(x) #x
+#define STR(x) STRX (x)
+#define SFUNC STR (FUNC)
+
+union u
+{
+  long double ld;
+  double d[2];
+};
+
+volatile union u p1 = { .d = { DBL_MIN, 0.0 } };
+volatile union u p2 = { .d = { DBL_MIN, -0.0 } };
+volatile union u m1 = { .d = { -DBL_MIN, 0.0 } };
+volatile union u m2 = { .d = { -DBL_MIN, -0.0 } };
+
+static int
+test_func (const char *s, long double x, long double y, long double expected)
+{
+  volatile long double r;
+  r = FUNC (x, y);
+  if (r != expected || copysignl (1.0, r) != copysignl (1.0, expected))
+    {
+      printf ("FAIL: " SFUNC " (%s)\n", s);
+      return 1;
+    }
+  else
+    {
+      printf ("PASS: " SFUNC " (%s)\n", s);
+      return 0;
+    }
+}
+
+#define TEST_FUNC(a, b, e) test_func (#a ", " #b, a, b, e)
+
+static int
+do_test (void)
+{
+  int result = 0;
+  SETUP;
+  result |= TEST_FUNC (p1.ld, p1.ld, 0.0L);
+  result |= TEST_FUNC (p1.ld, p2.ld, 0.0L);
+  result |= TEST_FUNC (p1.ld, m1.ld, 0.0L);
+  result |= TEST_FUNC (p1.ld, m2.ld, 0.0L);
+  result |= TEST_FUNC (p2.ld, p1.ld, 0.0L);
+  result |= TEST_FUNC (p2.ld, p2.ld, 0.0L);
+  result |= TEST_FUNC (p2.ld, m1.ld, 0.0L);
+  result |= TEST_FUNC (p2.ld, m2.ld, 0.0L);
+  result |= TEST_FUNC (m1.ld, p1.ld, -0.0L);
+  result |= TEST_FUNC (m1.ld, p2.ld, -0.0L);
+  result |= TEST_FUNC (m1.ld, m1.ld, -0.0L);
+  result |= TEST_FUNC (m1.ld, m2.ld, -0.0L);
+  result |= TEST_FUNC (m2.ld, p1.ld, -0.0L);
+  result |= TEST_FUNC (m2.ld, p2.ld, -0.0L);
+  result |= TEST_FUNC (m2.ld, m1.ld, -0.0L);
+  result |= TEST_FUNC (m2.ld, m2.ld, -0.0L);
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../../../test-skeleton.c"
diff --git a/sysdeps/ieee754/ldbl-128ibm/test-remainderl-ldbl-128ibm.c b/sysdeps/ieee754/ldbl-128ibm/test-remainderl-ldbl-128ibm.c
new file mode 100644 (file)
index 0000000..767a670
--- /dev/null
@@ -0,0 +1,21 @@
+/* Test for ldbl-128ibm remainderl handling of equal values (bug 19677).
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define FUNC remainderl
+#define SETUP fesetround (FE_DOWNWARD)
+#include "test-fmodrem-ldbl-128ibm.c"
diff --git a/sysdeps/ieee754/ldbl-128ibm/test-remquol-ldbl-128ibm.c b/sysdeps/ieee754/ldbl-128ibm/test-remquol-ldbl-128ibm.c
new file mode 100644 (file)
index 0000000..b691e3f
--- /dev/null
@@ -0,0 +1,30 @@
+/* Test for ldbl-128ibm remquol handling of equal values (bug 19677).
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+
+static long double
+wrap_remquol (long double x, long double y)
+{
+  int quo;
+  return remquol (x, y, &quo);
+}
+
+#define FUNC wrap_remquol
+#define SETUP fesetround (FE_DOWNWARD)
+#include "test-fmodrem-ldbl-128ibm.c"