mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-29 11:41:21 +03:00
Correct IBM long double nextafterl.
Fix for values near a power of two, and some tidies. [BZ #16739] * sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c (__nextafterl): Correct output when value is near a power of two. Use int64_t for lx and remove casts. Use decimal rather than hex exponent constants. Don't use long double multiplication when double will suffice. * math/libm-test.inc (nextafter_test_data): Add tests. * NEWS: Add 16739 and 16786 to bug list.
This commit is contained in:
10
ChangeLog
10
ChangeLog
@ -1,3 +1,13 @@
|
|||||||
|
2014-04-02 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
[BZ #16739]
|
||||||
|
* sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c (__nextafterl): Correct
|
||||||
|
output when value is near a power of two. Use int64_t for lx and
|
||||||
|
remove casts. Use decimal rather than hex exponent constants.
|
||||||
|
Don't use long double multiplication when double will suffice.
|
||||||
|
* math/libm-test.inc (nextafter_test_data): Add tests.
|
||||||
|
* NEWS: Add 16739 and 16786 to bug list.
|
||||||
|
|
||||||
2014-04-02 Alan Modra <amodra@gmail.com>
|
2014-04-02 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* sysdeps/powerpc/powerpc64/power7/memrchr.S: Correct stream hint.
|
* sysdeps/powerpc/powerpc64/power7/memrchr.S: Correct stream hint.
|
||||||
|
2
NEWS
2
NEWS
@ -13,7 +13,7 @@ Version 2.20
|
|||||||
16357, 16362, 16447, 16532, 16545, 16574, 16599, 16600, 16609, 16610,
|
16357, 16362, 16447, 16532, 16545, 16574, 16599, 16600, 16609, 16610,
|
||||||
16611, 16613, 16623, 16632, 16634, 16639, 16642, 16648, 16649, 16670,
|
16611, 16613, 16623, 16632, 16634, 16639, 16642, 16648, 16649, 16670,
|
||||||
16674, 16677, 16680, 16683, 16689, 16695, 16701, 16706, 16707, 16712,
|
16674, 16677, 16680, 16683, 16689, 16695, 16701, 16706, 16707, 16712,
|
||||||
16713, 16714, 16731, 16743, 16758, 16759, 16760, 16770.
|
16713, 16714, 16731, 16739, 16743, 16758, 16759, 16760, 16770, 16786.
|
||||||
|
|
||||||
* Running the testsuite no longer terminates as soon as a test fails.
|
* Running the testsuite no longer terminates as soon as a test fails.
|
||||||
Instead, a file tests.sum (xtests.sum from "make xcheck") is generated,
|
Instead, a file tests.sum (xtests.sum from "make xcheck") is generated,
|
||||||
|
@ -8302,6 +8302,14 @@ static const struct test_ff_f_data nextafter_test_data[] =
|
|||||||
// XXX Enable once gcc is fixed.
|
// XXX Enable once gcc is fixed.
|
||||||
//TEST_ff_f (nextafter, 0x0.00000040000000000000p-16385L, -0.1L, 0x0.0000003ffffffff00000p-16385L),
|
//TEST_ff_f (nextafter, 0x0.00000040000000000000p-16385L, -0.1L, 0x0.0000003ffffffff00000p-16385L),
|
||||||
#endif
|
#endif
|
||||||
|
#if defined TEST_LDOUBLE && LDBL_MANT_DIG == 106
|
||||||
|
TEST_ff_f (nextafter, 1.0L, -10.0L, 1.0L-0x1p-106L, NO_EXCEPTION),
|
||||||
|
TEST_ff_f (nextafter, 1.0L, 10.0L, 1.0L+0x1p-105L, NO_EXCEPTION),
|
||||||
|
TEST_ff_f (nextafter, 1.0L-0x1p-106L, 10.0L, 1.0L, NO_EXCEPTION),
|
||||||
|
TEST_ff_f (nextafter, -1.0L, -10.0L, -1.0L-0x1p-105L, NO_EXCEPTION),
|
||||||
|
TEST_ff_f (nextafter, -1.0L, 10.0L, -1.0L+0x1p-106L, NO_EXCEPTION),
|
||||||
|
TEST_ff_f (nextafter, -1.0L+0x1p-106L, -10.0L, -1.0L, NO_EXCEPTION),
|
||||||
|
#endif
|
||||||
|
|
||||||
/* XXX We need the hexadecimal FP number representation here for further
|
/* XXX We need the hexadecimal FP number representation here for further
|
||||||
tests. */
|
tests. */
|
||||||
|
@ -30,8 +30,7 @@ static char rcsid[] = "$NetBSD: $";
|
|||||||
|
|
||||||
long double __nextafterl(long double x, long double y)
|
long double __nextafterl(long double x, long double y)
|
||||||
{
|
{
|
||||||
int64_t hx,hy,ihx,ihy;
|
int64_t hx, hy, ihx, ihy, lx;
|
||||||
uint64_t lx;
|
|
||||||
double xhi, xlo, yhi;
|
double xhi, xlo, yhi;
|
||||||
|
|
||||||
ldbl_unpack (x, &xhi, &xlo);
|
ldbl_unpack (x, &xhi, &xlo);
|
||||||
@ -79,19 +78,28 @@ long double __nextafterl(long double x, long double y)
|
|||||||
u = math_opt_barrier (x);
|
u = math_opt_barrier (x);
|
||||||
x -= __LDBL_DENORM_MIN__;
|
x -= __LDBL_DENORM_MIN__;
|
||||||
if (ihx < 0x0360000000000000LL
|
if (ihx < 0x0360000000000000LL
|
||||||
|| (hx > 0 && (int64_t) lx <= 0)
|
|| (hx > 0 && lx <= 0)
|
||||||
|| (hx < 0 && (int64_t) lx > 1)) {
|
|| (hx < 0 && lx > 1)) {
|
||||||
u = u * u;
|
u = u * u;
|
||||||
math_force_eval (u); /* raise underflow flag */
|
math_force_eval (u); /* raise underflow flag */
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
if (ihx < 0x06a0000000000000LL) { /* ulp will denormal */
|
/* If the high double is an exact power of two and the low
|
||||||
INSERT_WORDS64 (yhi, hx & (0x7ffLL<<52));
|
double is the opposite sign, then 1ulp is one less than
|
||||||
u = yhi;
|
what we might determine from the high double. Similarly
|
||||||
u *= 0x1.0000000000000p-105L;
|
if X is an exact power of two, and positive, because
|
||||||
|
making it a little smaller will result in the exponent
|
||||||
|
decreasing by one and normalisation of the mantissa. */
|
||||||
|
if ((hx & 0x000fffffffffffffLL) == 0
|
||||||
|
&& ((lx != 0 && (hx ^ lx) < 0)
|
||||||
|
|| (lx == 0 && hx >= 0)))
|
||||||
|
ihx -= 1LL << 52;
|
||||||
|
if (ihx < (106LL << 52)) { /* ulp will denormal */
|
||||||
|
INSERT_WORDS64 (yhi, ihx & (0x7ffLL<<52));
|
||||||
|
u = yhi * 0x1p-105;
|
||||||
} else {
|
} else {
|
||||||
INSERT_WORDS64 (yhi, (hx & (0x7ffLL<<52))-(0x069LL<<52));
|
INSERT_WORDS64 (yhi, (ihx & (0x7ffLL<<52))-(105LL<<52));
|
||||||
u = yhi;
|
u = yhi;
|
||||||
}
|
}
|
||||||
return x - u;
|
return x - u;
|
||||||
@ -109,8 +117,8 @@ long double __nextafterl(long double x, long double y)
|
|||||||
u = math_opt_barrier (x);
|
u = math_opt_barrier (x);
|
||||||
x += __LDBL_DENORM_MIN__;
|
x += __LDBL_DENORM_MIN__;
|
||||||
if (ihx < 0x0360000000000000LL
|
if (ihx < 0x0360000000000000LL
|
||||||
|| (hx > 0 && (int64_t) lx < 0 && lx != 0x8000000000000001LL)
|
|| (hx > 0 && lx < 0 && lx != 0x8000000000000001LL)
|
||||||
|| (hx < 0 && (int64_t) lx >= 0)) {
|
|| (hx < 0 && lx >= 0)) {
|
||||||
u = u * u;
|
u = u * u;
|
||||||
math_force_eval (u); /* raise underflow flag */
|
math_force_eval (u); /* raise underflow flag */
|
||||||
}
|
}
|
||||||
@ -118,12 +126,21 @@ long double __nextafterl(long double x, long double y)
|
|||||||
x = -0.0L;
|
x = -0.0L;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
if (ihx < 0x06a0000000000000LL) { /* ulp will denormal */
|
/* If the high double is an exact power of two and the low
|
||||||
INSERT_WORDS64 (yhi, hx & (0x7ffLL<<52));
|
double is the opposite sign, then 1ulp is one less than
|
||||||
u = yhi;
|
what we might determine from the high double. Similarly
|
||||||
u *= 0x1.0000000000000p-105L;
|
if X is an exact power of two, and negative, because
|
||||||
|
making it a little larger will result in the exponent
|
||||||
|
decreasing by one and normalisation of the mantissa. */
|
||||||
|
if ((hx & 0x000fffffffffffffLL) == 0
|
||||||
|
&& ((lx != 0 && (hx ^ lx) < 0)
|
||||||
|
|| (lx == 0 && hx < 0)))
|
||||||
|
ihx -= 1LL << 52;
|
||||||
|
if (ihx < (106LL << 52)) { /* ulp will denormal */
|
||||||
|
INSERT_WORDS64 (yhi, ihx & (0x7ffLL<<52));
|
||||||
|
u = yhi * 0x1p-105;
|
||||||
} else {
|
} else {
|
||||||
INSERT_WORDS64 (yhi, (hx & (0x7ffLL<<52))-(0x069LL<<52));
|
INSERT_WORDS64 (yhi, (ihx & (0x7ffLL<<52))-(105LL<<52));
|
||||||
u = yhi;
|
u = yhi;
|
||||||
}
|
}
|
||||||
return x + u;
|
return x + u;
|
||||||
|
Reference in New Issue
Block a user