diff options
author | Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com> | 2017-04-28 19:45:52 -0300 |
---|---|---|
committer | Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com> | 2017-04-28 19:45:52 -0300 |
commit | c064f6a613844181f411aabb2662384a6aefb69e (patch) | |
tree | 87eddafe48fccaed565604fd1f405ad0437858f5 | |
parent | 2f7f3cd8cd302bb10908c86f3f7b349df0a78e6a (diff) | |
download | glibc-c064f6a613844181f411aabb2662384a6aefb69e.tar glibc-c064f6a613844181f411aabb2662384a6aefb69e.tar.gz glibc-c064f6a613844181f411aabb2662384a6aefb69e.tar.bz2 glibc-c064f6a613844181f411aabb2662384a6aefb69e.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.
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | sysdeps/powerpc/power7/fpu/s_logbl.c | 24 |
2 files changed, 25 insertions, 6 deletions
@@ -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-04-28 Paul E. Murphy <murphyp@linux.vnet.ibm.com> * sysdeps/powerpc/powerpc64le/Implies: New file. 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; |