From 380bd0fd2418f8988217de950f8b8ff18af0cb2b Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Thu, 26 Feb 2015 15:13:22 +0000 Subject: [PATCH] Fix ldbl-128ibm logbl near powers of 2 (bug 18030). The ldbl-128ibm implementation of logbl produces incorrect results when the high part of the argument is a power of 2 and the low part a nonzero number with the opposite sign (and so the returned exponent should be 1 less than that of the high part). For example, logbl (0x1.ffffffffffffffp1L) returns 2 but should return 1. (This is similar to (fixed) bug 16740 for frexpl, and (fixed) bug 18029 for ilogbl.) This patch adds checks for that case. Tested for powerpc. [BZ #18030] * sysdeps/ieee754/ldbl-128ibm/s_logbl.c (__logbl): Adjust exponent of power of 2 down when low part has opposite sign. * math/libm-test.inc (logb_test_data): Add more tests. --- ChangeLog | 7 +++++++ NEWS | 2 +- math/libm-test.inc | 5 +++++ sysdeps/ieee754/ldbl-128ibm/s_logbl.c | 17 ++++++++++++++--- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 90c42c85a3..ac6110b965 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2015-02-26 Joseph Myers + + [BZ #18030] + * sysdeps/ieee754/ldbl-128ibm/s_logbl.c (__logbl): Adjust exponent + of power of 2 down when low part has opposite sign. + * math/libm-test.inc (logb_test_data): Add more tests. + 2015-02-26 Andreas Schwab [BZ #18032] diff --git a/NEWS b/NEWS index 77e081464d..f09ffb1ccd 100644 --- a/NEWS +++ b/NEWS @@ -12,7 +12,7 @@ Version 2.22 4719, 14841, 13064, 14094, 15319, 15467, 15790, 15969, 16560, 16783, 17269, 17523, 17569, 17588, 17792, 17836, 17912, 17916, 17932, 17944, 17949, 17964, 17965, 17967, 17969, 17978, 17987, 17991, 17996, 17998, - 17999, 18019, 18020, 18029, 18032. + 17999, 18019, 18020, 18029, 18030, 18032. * Character encoding and ctype tables were updated to Unicode 7.0.0, using new generator scripts contributed by Pravin Satpute and Mike FABIAN (Red diff --git a/math/libm-test.inc b/math/libm-test.inc index 6045764fd3..7acd29bc13 100644 --- a/math/libm-test.inc +++ b/math/libm-test.inc @@ -7868,6 +7868,11 @@ static const struct test_f_f_data logb_test_data[] = TEST_f_f (logb, 0x1p-16400L, -16400, NO_INEXACT_EXCEPTION), TEST_f_f (logb, 0x.00000000001p-16382L, -16426, NO_INEXACT_EXCEPTION), #endif + +#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 57 + TEST_f_f (logb, 0x1.ffffffffffffffp1L, 1, NO_INEXACT_EXCEPTION), + TEST_f_f (logb, -0x1.ffffffffffffffp1L, 1, NO_INEXACT_EXCEPTION), +#endif }; static void diff --git a/sysdeps/ieee754/ldbl-128ibm/s_logbl.c b/sysdeps/ieee754/ldbl-128ibm/s_logbl.c index dbd3478e63..22e5fc24c0 100644 --- a/sysdeps/ieee754/ldbl-128ibm/s_logbl.c +++ b/sysdeps/ieee754/ldbl-128ibm/s_logbl.c @@ -26,11 +26,12 @@ long double __logbl (long double x) { - int64_t hx, rhx; - double xhi; + int64_t hx, hxs, rhx; + double xhi, xlo; - xhi = ldbl_high (x); + ldbl_unpack (x, &xhi, &xlo); EXTRACT_WORDS64 (hx, xhi); + hxs = hx; hx &= 0x7fffffffffffffffLL; /* high |x| */ if (hx == 0) return -1.0 / fabs (x); @@ -42,6 +43,16 @@ __logbl (long double x) though it were normalized. */ rhx -= __builtin_clzll (hx) - 12; } + else if ((hx & 0x000fffffffffffffLL) == 0) + { + /* If the high part is a power of 2, and the low part is nonzero + with the opposite sign, the low part affects the + exponent. */ + int64_t lx; + EXTRACT_WORDS64 (lx, xlo); + if ((hxs ^ lx) < 0 && (lx & 0x7fffffffffffffffLL) != 0) + rhx--; + } return (long double) (rhx - 1023); } #ifndef __logbl