]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix ldbl-96 fma (Inf, Inf, finite) (bug 23272).
authorJoseph Myers <joseph@codesourcery.com>
Mon, 11 Jun 2018 16:33:42 +0000 (16:33 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Mon, 11 Jun 2018 16:33:42 +0000 (16:33 +0000)
As reported in bug 23272, the ldbl-96 implementation of fma (fma for
double, in terms of ldbl-96 as the internal arithmetic type, as used
on 32-bit x86) is missing some of the special-case handling for
non-finite arguments, resulting in incorrect NaN results when the
first two arguments are infinities, the third is finite and so the
infinities go through the logic for finite arguments.  This patch
fixes it by handling all cases of non-finite arguments up front, with
additional fma tests for the problem cases being added to the
testsuite.

Tested for x86_64 and x86.

[BZ #23272]
* sysdeps/ieee754/ldbl-96/s_fma.c (__fma): Start by handling all
cases of non-finite arguments.
* math/libm-test-fma.inc (fma_test_data): Add more tests.

ChangeLog
math/libm-test-fma.inc
sysdeps/ieee754/ldbl-96/s_fma.c

index 0a4c0ff6d9be8bcb51f0da4791ad4811714c48da..f238908fe8135a065b2611ee310422467ed8a667 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2018-06-11  Joseph Myers  <joseph@codesourcery.com>
+
+       [BZ #23272]
+       * sysdeps/ieee754/ldbl-96/s_fma.c (__fma): Start by handling all
+       cases of non-finite arguments.
+       * math/libm-test-fma.inc (fma_test_data): Add more tests.
+
 2018-06-10  John David Anglin  <danglin@gcc.gnu.org>
 
        [BZ #23174]
index 655267b507c461da2889903bf74eda034deb75ee..5b29fb820194e0553eb467b62ed1f720e311b4d6 100644 (file)
@@ -113,6 +113,39 @@ static const struct test_fff_f_data fma_test_data[] =
     TEST_fff_f (fma, plus_infty, minus_infty, minus_infty, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_fff_f (fma, minus_infty, plus_infty, minus_infty, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
+    TEST_fff_f (fma, plus_infty, plus_infty, plus_zero, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, plus_infty, plus_infty, minus_zero, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, plus_infty, plus_infty, min_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, plus_infty, plus_infty, -min_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, plus_infty, plus_infty, min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, plus_infty, plus_infty, -min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, plus_infty, plus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, plus_infty, plus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, plus_infty, minus_infty, plus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, plus_infty, minus_infty, minus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, plus_infty, minus_infty, min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, plus_infty, minus_infty, -min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, plus_infty, minus_infty, min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, plus_infty, minus_infty, -min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, plus_infty, minus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, plus_infty, minus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, minus_infty, plus_infty, plus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, minus_infty, plus_infty, minus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, minus_infty, plus_infty, min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, minus_infty, plus_infty, -min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, minus_infty, plus_infty, min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, minus_infty, plus_infty, -min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, minus_infty, plus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, minus_infty, plus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, minus_infty, minus_infty, plus_zero, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, minus_infty, minus_infty, minus_zero, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, minus_infty, minus_infty, min_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, minus_infty, minus_infty, -min_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, minus_infty, minus_infty, min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, minus_infty, minus_infty, -min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, minus_infty, minus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fff_f (fma, minus_infty, minus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
     AUTO_TESTS_fff_f (fma),
   };
 
index f7f4dfd28d2e8235884fea15fca4ae40d137fbf4..986879cda5835c6e64c8e3670542c0ec48b2ba9e 100644 (file)
 double
 __fma (double x, double y, double z)
 {
-  if (__glibc_unlikely (isinf (z)))
-    {
-      /* If z is Inf, but x and y are finite, the result should be
-        z rather than NaN.  */
-      if (isfinite (x) && isfinite (y))
-       return (z + x) + y;
-      return (x * y) + z;
-    }
+  if (__glibc_unlikely (!isfinite (x) || !isfinite (y)))
+    return x * y + z;
+  else if (__glibc_unlikely (!isfinite (z)))
+    /* If z is Inf, but x and y are finite, the result should be z
+       rather than NaN.  */
+    return (z + x) + y;
 
   /* Ensure correct sign of exact 0 + 0.  */
   if (__glibc_unlikely ((x == 0 || y == 0) && z == 0))