diff options
author | Joseph Myers <joseph@codesourcery.com> | 2015-10-02 17:11:13 +0000 |
---|---|---|
committer | Joseph Myers <joseph@codesourcery.com> | 2015-10-02 17:11:13 +0000 |
commit | 59a63cca1133a8e1e3219970ee95979ac1f810df (patch) | |
tree | a4fc7c389f60647377479748d75bcc94f3c36547 /sysdeps | |
parent | ef6b619f73e49b6d87c7530e6e9f8a59723b492d (diff) | |
download | glibc-59a63cca1133a8e1e3219970ee95979ac1f810df.zip glibc-59a63cca1133a8e1e3219970ee95979ac1f810df.tar.gz glibc-59a63cca1133a8e1e3219970ee95979ac1f810df.tar.bz2 |
Fix nexttoward overflow in non-default rounding modes (bug 19059).
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.
Diffstat (limited to 'sysdeps')
-rw-r--r-- | sysdeps/i386/fpu/s_nexttoward.c | 4 | ||||
-rw-r--r-- | sysdeps/i386/fpu/s_nexttowardf.c | 4 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-128/s_nexttoward.c | 4 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-128/s_nexttowardf.c | 5 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c | 4 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c | 4 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-96/s_nexttoward.c | 4 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-96/s_nexttowardf.c | 4 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-opt/s_nexttowardfd.c | 4 |
9 files changed, 20 insertions, 17 deletions
diff --git a/sysdeps/i386/fpu/s_nexttoward.c b/sysdeps/i386/fpu/s_nexttoward.c index be65b8c..839efe6 100644 --- a/sysdeps/i386/fpu/s_nexttoward.c +++ b/sysdeps/i386/fpu/s_nexttoward.c @@ -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 */ diff --git a/sysdeps/i386/fpu/s_nexttowardf.c b/sysdeps/i386/fpu/s_nexttowardf.c index 8379eff..29b4f12 100644 --- a/sysdeps/i386/fpu/s_nexttowardf.c +++ b/sysdeps/i386/fpu/s_nexttowardf.c @@ -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 */ diff --git a/sysdeps/ieee754/ldbl-128/s_nexttoward.c b/sysdeps/ieee754/ldbl-128/s_nexttoward.c index e62ca3f..2ee7a1b 100644 --- a/sysdeps/ieee754/ldbl-128/s_nexttoward.c +++ b/sysdeps/ieee754/ldbl-128/s_nexttoward.c @@ -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 */ diff --git a/sysdeps/ieee754/ldbl-128/s_nexttowardf.c b/sysdeps/ieee754/ldbl-128/s_nexttowardf.c index ccd49d2..9c9c7e5 100644 --- a/sysdeps/ieee754/ldbl-128/s_nexttowardf.c +++ b/sysdeps/ieee754/ldbl-128/s_nexttowardf.c @@ -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 */ diff --git a/sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c b/sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c index 85140c1..8c61198 100644 --- a/sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c +++ b/sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c @@ -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 */ diff --git a/sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c b/sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c index b27f0bb..4000a93 100644 --- a/sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c +++ b/sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c @@ -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; diff --git a/sysdeps/ieee754/ldbl-96/s_nexttoward.c b/sysdeps/ieee754/ldbl-96/s_nexttoward.c index b972a3e..7908f9c 100644 --- a/sysdeps/ieee754/ldbl-96/s_nexttoward.c +++ b/sysdeps/ieee754/ldbl-96/s_nexttoward.c @@ -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 */ diff --git a/sysdeps/ieee754/ldbl-96/s_nexttowardf.c b/sysdeps/ieee754/ldbl-96/s_nexttowardf.c index f1fe4e7..53c527d 100644 --- a/sysdeps/ieee754/ldbl-96/s_nexttowardf.c +++ b/sysdeps/ieee754/ldbl-96/s_nexttowardf.c @@ -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 */ diff --git a/sysdeps/ieee754/ldbl-opt/s_nexttowardfd.c b/sysdeps/ieee754/ldbl-opt/s_nexttowardfd.c index 782e1a3..dbcf840 100644 --- a/sysdeps/ieee754/ldbl-opt/s_nexttowardfd.c +++ b/sysdeps/ieee754/ldbl-opt/s_nexttowardfd.c @@ -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 */ |