mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-22 10:50:07 +00:00
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.
This commit is contained in:
parent
ef6b619f73
commit
59a63cca11
20
ChangeLog
20
ChangeLog
@ -1,5 +1,25 @@
|
|||||||
2015-10-02 Joseph Myers <joseph@codesourcery.com>
|
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
|
* nss/rewrite_field.c (__nss_rewrite_field): Use
|
||||||
internal_function.
|
internal_function.
|
||||||
* nss/valid_field.c (__nss_valid_field): Likewise.
|
* nss/valid_field.c (__nss_valid_field): Likewise.
|
||||||
|
2
NEWS
2
NEWS
@ -17,7 +17,7 @@ Version 2.23
|
|||||||
18778, 18781, 18787, 18789, 18790, 18795, 18796, 18803, 18820, 18823,
|
18778, 18781, 18787, 18789, 18790, 18795, 18796, 18803, 18820, 18823,
|
||||||
18824, 18825, 18857, 18863, 18870, 18872, 18873, 18875, 18887, 18921,
|
18824, 18825, 18857, 18863, 18870, 18872, 18873, 18875, 18887, 18921,
|
||||||
18951, 18952, 18956, 18961, 18966, 18967, 18969, 18970, 18977, 18980,
|
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
|
* The obsolete header <regexp.h> has been removed. Programs that require
|
||||||
this header must be updated to use <regex.h> instead.
|
this header must be updated to use <regex.h> instead.
|
||||||
|
@ -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, 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),
|
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
|
#ifdef TEST_FLOAT
|
||||||
TEST_ff_f (nexttoward, 1.0, 1.1L, 0x1.000002p0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
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),
|
TEST_ff_f (nexttoward, 1.0, LDBL_MAX, 0x1.000002p0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||||
|
@ -59,8 +59,8 @@ float __nexttowardf(float x, long double y)
|
|||||||
}
|
}
|
||||||
hy = hx&0x7f800000;
|
hy = hx&0x7f800000;
|
||||||
if(hy>=0x7f800000) {
|
if(hy>=0x7f800000) {
|
||||||
x = math_narrow_eval (x+x); /* overflow */
|
float u = x+x; /* overflow */
|
||||||
return x;
|
math_force_eval (u);
|
||||||
}
|
}
|
||||||
if(hy<0x00800000) {
|
if(hy<0x00800000) {
|
||||||
float u = x*x; /* underflow */
|
float u = x*x; /* underflow */
|
||||||
|
@ -73,8 +73,8 @@ double __nexttoward(double x, long double y)
|
|||||||
}
|
}
|
||||||
hy = hx&0x7ff00000;
|
hy = hx&0x7ff00000;
|
||||||
if(hy>=0x7ff00000) {
|
if(hy>=0x7ff00000) {
|
||||||
x = math_narrow_eval (x+x); /* overflow */
|
double u = x+x; /* overflow */
|
||||||
return x;
|
math_force_eval (u);
|
||||||
}
|
}
|
||||||
if(hy<0x00100000) {
|
if(hy<0x00100000) {
|
||||||
double u = x*x; /* underflow */
|
double u = x*x; /* underflow */
|
||||||
|
@ -61,8 +61,8 @@ float __nexttowardf(float x, long double y)
|
|||||||
}
|
}
|
||||||
hy = hx&0x7f800000;
|
hy = hx&0x7f800000;
|
||||||
if(hy>=0x7f800000) {
|
if(hy>=0x7f800000) {
|
||||||
x = math_narrow_eval (x+x); /* overflow */
|
float u = x+x; /* overflow */
|
||||||
return x;
|
math_force_eval (u);
|
||||||
}
|
}
|
||||||
if(hy<0x00800000) {
|
if(hy<0x00800000) {
|
||||||
float u = x*x; /* underflow */
|
float u = x*x; /* underflow */
|
||||||
|
@ -73,8 +73,8 @@ double __nexttoward(double x, long double y)
|
|||||||
}
|
}
|
||||||
hy = hx&0x7ff00000;
|
hy = hx&0x7ff00000;
|
||||||
if(hy>=0x7ff00000) {
|
if(hy>=0x7ff00000) {
|
||||||
x = math_narrow_eval (x+x); /* overflow */
|
double u = x+x; /* overflow */
|
||||||
return x;
|
math_force_eval (u);
|
||||||
}
|
}
|
||||||
if(hy<0x00100000) {
|
if(hy<0x00100000) {
|
||||||
double u = x*x; /* underflow */
|
double u = x*x; /* underflow */
|
||||||
|
@ -59,7 +59,10 @@ float __nexttowardf(float x, long double y)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
hy = hx&0x7f800000;
|
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) {
|
if(hy<0x00800000) {
|
||||||
float u = x*x; /* underflow */
|
float u = x*x; /* underflow */
|
||||||
math_force_eval (u); /* raise underflow flag */
|
math_force_eval (u); /* raise underflow flag */
|
||||||
|
@ -74,8 +74,8 @@ double __nexttoward(double x, long double y)
|
|||||||
}
|
}
|
||||||
hy = hx&0x7ff00000;
|
hy = hx&0x7ff00000;
|
||||||
if(hy>=0x7ff00000) {
|
if(hy>=0x7ff00000) {
|
||||||
x = math_narrow_eval (x+x); /* overflow */
|
double u = x+x; /* overflow */
|
||||||
return x;
|
math_force_eval (u);
|
||||||
}
|
}
|
||||||
if(hy<0x00100000) {
|
if(hy<0x00100000) {
|
||||||
double u = x*x; /* underflow */
|
double u = x*x; /* underflow */
|
||||||
|
@ -63,8 +63,8 @@ float __nexttowardf(float x, long double y)
|
|||||||
}
|
}
|
||||||
hy = hx&0x7f800000;
|
hy = hx&0x7f800000;
|
||||||
if(hy>=0x7f800000) {
|
if(hy>=0x7f800000) {
|
||||||
x = math_narrow_eval (x+x); /* overflow */
|
float u = x+x; /* overflow */
|
||||||
return x;
|
math_force_eval (u);
|
||||||
}
|
}
|
||||||
if(hy<0x00800000) { /* underflow */
|
if(hy<0x00800000) { /* underflow */
|
||||||
float u = x*x;
|
float u = x*x;
|
||||||
|
@ -70,8 +70,8 @@ double __nexttoward(double x, long double y)
|
|||||||
}
|
}
|
||||||
hy = hx&0x7ff00000;
|
hy = hx&0x7ff00000;
|
||||||
if(hy>=0x7ff00000) {
|
if(hy>=0x7ff00000) {
|
||||||
x = math_narrow_eval (x+x); /* overflow */
|
double u = x+x; /* overflow */
|
||||||
return x;
|
math_force_eval (u);
|
||||||
}
|
}
|
||||||
if(hy<0x00100000) {
|
if(hy<0x00100000) {
|
||||||
double u = x*x; /* underflow */
|
double u = x*x; /* underflow */
|
||||||
|
@ -58,8 +58,8 @@ float __nexttowardf(float x, long double y)
|
|||||||
}
|
}
|
||||||
hy = hx&0x7f800000;
|
hy = hx&0x7f800000;
|
||||||
if(hy>=0x7f800000) {
|
if(hy>=0x7f800000) {
|
||||||
x = math_narrow_eval (x+x); /* overflow */
|
float u = x+x; /* overflow */
|
||||||
return x;
|
math_force_eval (u);
|
||||||
}
|
}
|
||||||
if(hy<0x00800000) {
|
if(hy<0x00800000) {
|
||||||
float u = x*x; /* underflow */
|
float u = x*x; /* underflow */
|
||||||
|
@ -62,8 +62,8 @@ float __nldbl_nexttowardf(float x, double y)
|
|||||||
}
|
}
|
||||||
hy = hx&0x7f800000;
|
hy = hx&0x7f800000;
|
||||||
if(hy>=0x7f800000) {
|
if(hy>=0x7f800000) {
|
||||||
x = math_narrow_eval (x+x); /* overflow */
|
float u = x+x; /* overflow */
|
||||||
return x;
|
math_force_eval (u);
|
||||||
}
|
}
|
||||||
if(hy<0x00800000) {
|
if(hy<0x00800000) {
|
||||||
float u = x*x; /* underflow */
|
float u = x*x; /* underflow */
|
||||||
|
Loading…
Reference in New Issue
Block a user