diff options
author | Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com> | 2017-04-28 19:45:52 -0300 |
---|---|---|
committer | Aurelien Jarno <aurelien@aurel32.net> | 2017-08-02 15:28:34 +0200 |
commit | da3e97f94c80c5d05c0d999e87179aad35f7e975 (patch) | |
tree | 9a8c48d9acfaa411b985336a67303703955bd370 | |
parent | 0edeadc0d396aa713b808ae50a0058aca5d3837e (diff) | |
download | glibc-da3e97f94c80c5d05c0d999e87179aad35f7e975.tar.gz glibc-da3e97f94c80c5d05c0d999e87179aad35f7e975.tar.xz glibc-da3e97f94c80c5d05c0d999e87179aad35f7e975.zip |
powerpc: Fix logbl on power7 [BZ# 21280]
1. Fix the results for negative subnormals by ignoring the signal when normalizing the value. 2. Fix the output when the high part is a power of 2 and the low part is a nonzero number with opposite sign. This fix is based on commit 380bd0fd2418f8988217de950f8b8ff18af0cb2b. After applying this patch, logbl() tests pass cleanly on POWER >= 7. Tested on powerpc, powerpc64 and powerpc64le [BZ #21280] * sysdeps/powerpc/power7/fpu/s_logbl.c (__logbl): Ignore the signal of subnormals and adjust the exponent of power of 2 down when low part has opposite sign. (cherry picked from commit c064f6a613844181f411aabb2662384a6aefb69e)
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | sysdeps/powerpc/power7/fpu/s_logbl.c | 24 |
2 files changed, 25 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog index ff0853d3d2..b70096ae6d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2017-04-28 Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com> + + [BZ #21280] + * sysdeps/powerpc/power7/fpu/s_logbl.c (__logbl): Ignore the + signal of subnormals and adjust the exponent of power of 2 down + when low part has opposite sign. + 2017-07-26 H.J. Lu <hongjiu.lu@intel.com> [BZ #21666] diff --git a/sysdeps/powerpc/power7/fpu/s_logbl.c b/sysdeps/powerpc/power7/fpu/s_logbl.c index f7ecbd105a..3ae383a831 100644 --- a/sysdeps/powerpc/power7/fpu/s_logbl.c +++ b/sysdeps/powerpc/power7/fpu/s_logbl.c @@ -35,14 +35,16 @@ static const union { long double __logbl (long double x) { - double xh; + double xh, xl; double ret; + int64_t hx; if (__builtin_expect (x == 0.0L, 0)) /* Raise FE_DIVBYZERO and return -HUGE_VAL[LF]. */ return -1.0L / __builtin_fabsl (x); - xh = ldbl_high (x); + ldbl_unpack (x, &xh, &xl); + EXTRACT_WORDS64 (hx, xh); /* ret = x & 0x7ff0000000000000; */ asm ( "xxland %x0,%x1,%x2\n" @@ -58,10 +60,20 @@ __logbl (long double x) { /* POSIX specifies that denormal number is treated as though it were normalized. */ - int64_t hx; - - EXTRACT_WORDS64 (hx, xh); - return (long double) (-1023 - (__builtin_clzll (hx) - 12)); + return (long double) (- (__builtin_clzll (hx & 0x7fffffffffffffffLL) \ + - 12) - 1023); + } + 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, rhx; + EXTRACT_WORDS64 (lx, xl); + rhx = (hx & 0x7ff0000000000000LL) >> 52; + if ((hx ^ lx) < 0 && (lx & 0x7fffffffffffffffLL) != 0) + rhx--; + return (long double) (rhx - 1023); } /* Test to avoid logb_downward (0.0) == -0.0. */ return ret == -0.0 ? 0.0 : ret; |