mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-08 22:30:07 +00:00
Fix ldbl-96 scalblnl underflowing results (bug 17803).
The ldbl-96 implementation of scalblnl (used for x86_64 and ia64) uses a condition k <= -63 to determine when a standard underflowing result tiny*__copysignl(tiny,x) should be returned. However, that condition corresponds to values with exponent -16446 or less, and in the case of -16446, the correct result for round-to-nearest depends on whether the value is exactly 0x1p-16446 (half the least subnormal) or more than that. This patch fixes the bug by changing the condition to k <= -64 and accordingly adjusting the exponent by 64 not 63 when converting to a normal value. Tested for x86_64. [BZ #17803] * sysdeps/ieee754/ldbl-96/s_scalblnl.c (twom63): Rename to twom64. Adjust value to 0x1p-64L. (__scalblnl): Only return standard underflowing result for K <= -64 not K <= -63; adjust exponent for underflowing result by 64 not 63. * math/libm-test.inc (scalbn_test_data): Add more tests. (scalbln_test_data): Likewise.
This commit is contained in:
parent
34e93d6c76
commit
5a9e4c09a2
@ -1,5 +1,14 @@
|
||||
2015-01-12 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
[BZ #17803]
|
||||
* sysdeps/ieee754/ldbl-96/s_scalblnl.c (twom63): Rename to
|
||||
twom64. Adjust value to 0x1p-64L.
|
||||
(__scalblnl): Only return standard underflowing result for K <=
|
||||
-64 not K <= -63; adjust exponent for underflowing result by 64
|
||||
not 63.
|
||||
* math/libm-test.inc (scalbn_test_data): Add more tests.
|
||||
(scalbln_test_data): Likewise.
|
||||
|
||||
[BZ #17834]
|
||||
* sysdeps/ieee754/ldbl-96/s_scalblnl.c (two63): Change value to
|
||||
0x1p63L.
|
||||
|
2
NEWS
2
NEWS
@ -17,7 +17,7 @@ Version 2.21
|
||||
17633, 17634, 17635, 17647, 17653, 17657, 17658, 17664, 17665, 17668,
|
||||
17682, 17717, 17719, 17722, 17723, 17724, 17725, 17732, 17733, 17744,
|
||||
17745, 17746, 17747, 17748, 17775, 17777, 17780, 17781, 17782, 17791,
|
||||
17793, 17796, 17797, 17806, 17834
|
||||
17793, 17796, 17797, 17803, 17806, 17834
|
||||
|
||||
* Added support for TSX lock elision of pthread mutexes on powerpc32, powerpc64
|
||||
and powerpc64le. This may improve lock scaling of existing programs on
|
||||
|
@ -9135,6 +9135,25 @@ static const struct test_fi_f_data scalbn_test_data[] =
|
||||
TEST_fi_f (scalbn, min_subnorm_value, MANT_DIG, min_value, NO_INEXACT_EXCEPTION),
|
||||
TEST_fi_f (scalbn, -min_subnorm_value, MANT_DIG, -min_value, NO_INEXACT_EXCEPTION),
|
||||
|
||||
TEST_fi_f (scalbn, min_value, -MANT_DIG, min_subnorm_value, NO_INEXACT_EXCEPTION),
|
||||
TEST_fi_f (scalbn, -min_value, -MANT_DIG, -min_subnorm_value, NO_INEXACT_EXCEPTION),
|
||||
TEST_fi_f (scalbn, min_value, -MANT_DIG-1, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fi_f (scalbn, -min_value, -MANT_DIG-1, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fi_f (scalbn, min_value, -MANT_DIG-2, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fi_f (scalbn, -min_value, -MANT_DIG-2, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fi_f (scalbn, min_value * 1.5, -MANT_DIG, min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value * 2, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value * 2, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fi_f (scalbn, -min_value * 1.5, -MANT_DIG, -min_subnorm_value * 2, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, -min_subnorm_value * 2, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, -min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, -min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fi_f (scalbn, min_value * 1.5, -MANT_DIG-1, plus_zero, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, plus_zero, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fi_f (scalbn, -min_value * 1.5, -MANT_DIG-1, -min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, -min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, minus_zero, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, minus_zero, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fi_f (scalbn, min_value * 1.5, -MANT_DIG-2, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fi_f (scalbn, -min_value * 1.5, -MANT_DIG-2, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fi_f (scalbn, min_value * 1.25, -MANT_DIG, min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value * 2, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fi_f (scalbn, -min_value * 1.25, -MANT_DIG, -min_subnorm_value * 2, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, -min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, -min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, -min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fi_f (scalbn, min_value * 1.25, -MANT_DIG-1, plus_zero, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, plus_zero, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fi_f (scalbn, -min_value * 1.25, -MANT_DIG-1, -min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, -min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, minus_zero, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, minus_zero, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fi_f (scalbn, min_value * 1.25, -MANT_DIG-2, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fi_f (scalbn, -min_value * 1.25, -MANT_DIG-2, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
|
||||
TEST_fi_f (scalbn, 1, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
|
||||
TEST_fi_f (scalbn, 1, INT_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fi_f (scalbn, max_value, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
|
||||
@ -9193,6 +9212,25 @@ static const struct test_fl_f_data scalbln_test_data[] =
|
||||
TEST_fl_f (scalbln, min_subnorm_value, MANT_DIG, min_value, NO_INEXACT_EXCEPTION),
|
||||
TEST_fl_f (scalbln, -min_subnorm_value, MANT_DIG, -min_value, NO_INEXACT_EXCEPTION),
|
||||
|
||||
TEST_fl_f (scalbln, min_value, -MANT_DIG, min_subnorm_value, NO_INEXACT_EXCEPTION),
|
||||
TEST_fl_f (scalbln, -min_value, -MANT_DIG, -min_subnorm_value, NO_INEXACT_EXCEPTION),
|
||||
TEST_fl_f (scalbln, min_value, -MANT_DIG-1, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fl_f (scalbln, -min_value, -MANT_DIG-1, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fl_f (scalbln, min_value, -MANT_DIG-2, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fl_f (scalbln, -min_value, -MANT_DIG-2, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fl_f (scalbln, min_value * 1.5, -MANT_DIG, min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value * 2, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value * 2, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fl_f (scalbln, -min_value * 1.5, -MANT_DIG, -min_subnorm_value * 2, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, -min_subnorm_value * 2, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, -min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, -min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fl_f (scalbln, min_value * 1.5, -MANT_DIG-1, plus_zero, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, plus_zero, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fl_f (scalbln, -min_value * 1.5, -MANT_DIG-1, -min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, -min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, minus_zero, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, minus_zero, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fl_f (scalbln, min_value * 1.5, -MANT_DIG-2, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fl_f (scalbln, -min_value * 1.5, -MANT_DIG-2, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fl_f (scalbln, min_value * 1.25, -MANT_DIG, min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value * 2, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fl_f (scalbln, -min_value * 1.25, -MANT_DIG, -min_subnorm_value * 2, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, -min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, -min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, -min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fl_f (scalbln, min_value * 1.25, -MANT_DIG-1, plus_zero, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, plus_zero, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fl_f (scalbln, -min_value * 1.25, -MANT_DIG-1, -min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, -min_subnorm_value, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, minus_zero, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION, minus_zero, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fl_f (scalbln, min_value * 1.25, -MANT_DIG-2, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
TEST_fl_f (scalbln, -min_value * 1.25, -MANT_DIG-2, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
|
||||
|
||||
TEST_fl_f (scalbln, 1, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_PLUS_OFLOW),
|
||||
TEST_fl_f (scalbln, 1, INT_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_PLUS_UFLOW),
|
||||
TEST_fl_f (scalbln, max_value, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_PLUS_OFLOW),
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
static const long double
|
||||
two63 = 0x1p63L,
|
||||
twom63 = 1.08420217248550443400e-19,
|
||||
twom64 = 0x1p-64L,
|
||||
huge = 1.0e+4900L,
|
||||
tiny = 1.0e-4900L;
|
||||
|
||||
@ -52,9 +52,9 @@ __scalblnl (long double x, long int n)
|
||||
k = k+n;
|
||||
if (__builtin_expect(k > 0, 1)) /* normal result */
|
||||
{SET_LDOUBLE_EXP(x,(es&0x8000)|k); return x;}
|
||||
if (k <= -63)
|
||||
if (k <= -64)
|
||||
return tiny*__copysignl(tiny,x); /*underflow*/
|
||||
k += 63; /* subnormal result */
|
||||
k += 64; /* subnormal result */
|
||||
SET_LDOUBLE_EXP(x,(es&0x8000)|k);
|
||||
return x*twom63;
|
||||
return x*twom64;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user