]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix nexttoward overflow in non-default rounding modes (bug 19059).
authorJoseph Myers <joseph@codesourcery.com>
Fri, 2 Oct 2015 17:11:13 +0000 (17:11 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Fri, 2 Oct 2015 17:11:13 +0000 (17:11 +0000)
ISO C requires overflowing results from nexttoward to be the
appropriate infinity independent of the rounding mode, but some
implementations use a rounding-mode-dependent result (this is the same
issue as was fixed for nextafter in bug 16677).  This patch fixes the
problem by making the nexttoward implementations discard the result
from the floating-point computation that forced an overflow exception
and then return the infinity previously computed with integer
arithmetic.

Tested for x86_64, x86, mips64 and powerpc.

[BZ #19059]
* math/s_nexttowardf.c (__nexttowardf): Do not return value from
overflowing computation.
* sysdeps/i386/fpu/s_nexttoward.c (__nexttoward): Likewise.
* sysdeps/i386/fpu/s_nexttowardf.c (__nexttowardf): Likewise.
* sysdeps/ieee754/ldbl-128/s_nexttoward.c (__nexttoward):
Likewise.
* sysdeps/ieee754/ldbl-128/s_nexttowardf.c (__nexttowardf):
Likewise.
* sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c (__nexttoward):
Likewise.
* sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c (__nexttowardf):
Likewise.
* sysdeps/ieee754/ldbl-96/s_nexttoward.c (__nexttoward): Likewise.
* sysdeps/ieee754/ldbl-96/s_nexttowardf.c (__nexttowardf):
Likewise.
* sysdeps/ieee754/ldbl-opt/s_nexttowardfd.c (__nldbl_nexttowardf):
Likewise.
* math/libm-test.inc (nexttoward_test_data): Add more tests.

13 files changed:
ChangeLog
NEWS
math/libm-test.inc
math/s_nexttowardf.c
sysdeps/i386/fpu/s_nexttoward.c
sysdeps/i386/fpu/s_nexttowardf.c
sysdeps/ieee754/ldbl-128/s_nexttoward.c
sysdeps/ieee754/ldbl-128/s_nexttowardf.c
sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c
sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c
sysdeps/ieee754/ldbl-96/s_nexttoward.c
sysdeps/ieee754/ldbl-96/s_nexttowardf.c
sysdeps/ieee754/ldbl-opt/s_nexttowardfd.c

index 51476e69790cdc004ede000c7363706b7e96bf1b..e03132aebabfd8bc9a014d10f300987e5e1476e8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,25 @@
 2015-10-02  Joseph Myers  <joseph@codesourcery.com>
 
+       [BZ #19059]
+       * math/s_nexttowardf.c (__nexttowardf): Do not return value from
+       overflowing computation.
+       * sysdeps/i386/fpu/s_nexttoward.c (__nexttoward): Likewise.
+       * sysdeps/i386/fpu/s_nexttowardf.c (__nexttowardf): Likewise.
+       * sysdeps/ieee754/ldbl-128/s_nexttoward.c (__nexttoward):
+       Likewise.
+       * sysdeps/ieee754/ldbl-128/s_nexttowardf.c (__nexttowardf):
+       Likewise.
+       * sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c (__nexttoward):
+       Likewise.
+       * sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c (__nexttowardf):
+       Likewise.
+       * sysdeps/ieee754/ldbl-96/s_nexttoward.c (__nexttoward): Likewise.
+       * sysdeps/ieee754/ldbl-96/s_nexttowardf.c (__nexttowardf):
+       Likewise.
+       * sysdeps/ieee754/ldbl-opt/s_nexttowardfd.c (__nldbl_nexttowardf):
+       Likewise.
+       * math/libm-test.inc (nexttoward_test_data): Add more tests.
+
        * nss/rewrite_field.c (__nss_rewrite_field): Use
        internal_function.
        * nss/valid_field.c (__nss_valid_field): Likewise.
diff --git a/NEWS b/NEWS
index 4634b74ebf6b3b5c83583837f1c54a301624ff63..05d962221bd2b49e6a5214f918c28c8dccd57424 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -17,7 +17,7 @@ Version 2.23
   18778, 18781, 18787, 18789, 18790, 18795, 18796, 18803, 18820, 18823,
   18824, 18825, 18857, 18863, 18870, 18872, 18873, 18875, 18887, 18921,
   18951, 18952, 18956, 18961, 18966, 18967, 18969, 18970, 18977, 18980,
-  18981, 18985, 19003, 19016, 19032, 19046.
+  18981, 18985, 19003, 19016, 19032, 19046, 19059.
 
 * The obsolete header <regexp.h> has been removed.  Programs that require
   this header must be updated to use <regex.h> instead.
index f627296d66153016d812519f9adc6cce437d85ed..ac1fe85fc1a069f02db9801e5a56ff9245694ddb 100644 (file)
@@ -8536,6 +8536,10 @@ static const struct test_ff_f_data_nexttoward nexttoward_test_data[] =
     TEST_ff_f (nexttoward, 1.1L, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_ff_f (nexttoward, qnan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
+    /* Bug 6799: errno setting may be missing.  */
+    TEST_ff_f (nexttoward, max_value, plus_infty, plus_infty, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
+    TEST_ff_f (nexttoward, -max_value, minus_infty, minus_infty, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
+
 #ifdef TEST_FLOAT
     TEST_ff_f (nexttoward, 1.0, 1.1L, 0x1.000002p0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_ff_f (nexttoward, 1.0, LDBL_MAX, 0x1.000002p0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
index 06e1bb10cbc330b58676c7bb1bc40b3cc50d7cd9..06350d47bfd2fcc70ce5957fd4715cfb9908c354 100644 (file)
@@ -59,8 +59,8 @@ float __nexttowardf(float x, long double y)
        }
        hy = hx&0x7f800000;
        if(hy>=0x7f800000) {
-         x = math_narrow_eval (x+x);   /* overflow  */
-         return x;
+         float u = x+x;                        /* overflow  */
+         math_force_eval (u);
        }
        if(hy<0x00800000) {
            float u = x*x;                      /* underflow */
index be65b8ce2977e557a9f24700dbdf1af3beebb990..839efe6c05232b0d777a24c328760d349ea1cb5c 100644 (file)
@@ -73,8 +73,8 @@ double __nexttoward(double x, long double y)
        }
        hy = hx&0x7ff00000;
        if(hy>=0x7ff00000) {
-         x = math_narrow_eval (x+x);   /* overflow  */
-         return x;
+         double u = x+x;                       /* overflow  */
+         math_force_eval (u);
        }
        if(hy<0x00100000) {
            double u = x*x;                     /* underflow */
index 8379eff8b8e472e9603cedbdc3e1663ff05c4994..29b4f12775a6ba5c759b9541d08f41256a99b797 100644 (file)
@@ -61,8 +61,8 @@ float __nexttowardf(float x, long double y)
        }
        hy = hx&0x7f800000;
        if(hy>=0x7f800000) {
-         x = math_narrow_eval (x+x);   /* overflow  */
-         return x;
+         float u = x+x;                        /* overflow  */
+         math_force_eval (u);
        }
        if(hy<0x00800000) {
            float u = x*x;                      /* underflow */
index e62ca3fef8341a6babd891e6caeba62311c325dd..2ee7a1be5cf0df992184e70302799f9fff14b1aa 100644 (file)
@@ -73,8 +73,8 @@ double __nexttoward(double x, long double y)
        }
        hy = hx&0x7ff00000;
        if(hy>=0x7ff00000) {
-         x = math_narrow_eval (x+x);   /* overflow  */
-         return x;
+         double u = x+x;                       /* overflow  */
+         math_force_eval (u);
        }
        if(hy<0x00100000) {
            double u = x*x;                     /* underflow */
index ccd49d235d33dc9b22c8aa43dbb48abececd4d75..9c9c7e5283ab9a765b36c842c624a8355f2f718c 100644 (file)
@@ -59,7 +59,10 @@ float __nexttowardf(float x, long double y)
            }
        }
        hy = hx&0x7f800000;
-       if(hy>=0x7f800000) return x+x;  /* overflow  */
+       if(hy>=0x7f800000) {
+         float u = x+x;                /* overflow  */
+         math_force_eval (u);
+       }
        if(hy<0x00800000) {
            float u = x*x;              /* underflow */
            math_force_eval (u);        /* raise underflow flag */
index 85140c1d02824b5a2765b4117f9e84cff0393c04..8c6119825e9d9fa266caefa9efe49ae5f1e0bf4a 100644 (file)
@@ -74,8 +74,8 @@ double __nexttoward(double x, long double y)
        }
        hy = hx&0x7ff00000;
        if(hy>=0x7ff00000) {
-         x = math_narrow_eval (x+x);   /* overflow  */
-         return x;
+         double u = x+x;                       /* overflow  */
+         math_force_eval (u);
        }
        if(hy<0x00100000) {
            double u = x*x;                     /* underflow */
index b27f0bb380a97d131cafef45f25dc6417ccc8943..4000a93e690281047c6dcdd18d435f1c66a08d09 100644 (file)
@@ -63,8 +63,8 @@ float __nexttowardf(float x, long double y)
        }
        hy = hx&0x7f800000;
        if(hy>=0x7f800000) {
-         x = math_narrow_eval (x+x);   /* overflow  */
-         return x;
+         float u = x+x;                /* overflow  */
+         math_force_eval (u);
        }
        if(hy<0x00800000) {             /* underflow */
            float u = x*x;
index b972a3eb3a7de06aedb6d95e9b5e489b88d3a1e1..7908f9c0ff6a090f6ec86b2cd939f2ad86676ecb 100644 (file)
@@ -70,8 +70,8 @@ double __nexttoward(double x, long double y)
        }
        hy = hx&0x7ff00000;
        if(hy>=0x7ff00000) {
-         x = math_narrow_eval (x+x);   /* overflow  */
-         return x;
+         double u = x+x;                       /* overflow  */
+         math_force_eval (u);
        }
        if(hy<0x00100000) {
            double u = x*x;                     /* underflow */
index f1fe4e7ca7110f6d909830a20363caedb18bfb2e..53c527d9ac81e54758017b1d1d0b937e9c0f2c56 100644 (file)
@@ -58,8 +58,8 @@ float __nexttowardf(float x, long double y)
        }
        hy = hx&0x7f800000;
        if(hy>=0x7f800000) {
-         x = math_narrow_eval (x+x);   /* overflow  */
-         return x;
+         float u = x+x;                        /* overflow  */
+         math_force_eval (u);
        }
        if(hy<0x00800000) {
            float u = x*x;                      /* underflow */
index 782e1a33401f85a60707b04422dbf3cf81e1a69e..dbcf840f2c01c65035358302fb4c8d87bb006138 100644 (file)
@@ -62,8 +62,8 @@ float __nldbl_nexttowardf(float x, double y)
        }
        hy = hx&0x7f800000;
        if(hy>=0x7f800000) {
-         x = math_narrow_eval (x+x);   /* overflow  */
-         return x;
+         float u = x+x;                        /* overflow  */
+         math_force_eval (u);
        }
        if(hy<0x00800000) {
            float u = x*x;                      /* underflow */