diff options
author | das <das@FreeBSD.org> | 2008-01-28 01:19:07 +0000 |
---|---|---|
committer | das <das@FreeBSD.org> | 2008-01-28 01:19:07 +0000 |
commit | b2c068251b6066a7f5d1e4126014a929ac3de73d (patch) | |
tree | 85255327baddeb92c4e5046d1ae3c15c405f71bb /lib | |
parent | a15e8d3ada60473573df3e6aab707dbd1d10e38a (diff) | |
download | FreeBSD-src-b2c068251b6066a7f5d1e4126014a929ac3de73d.zip FreeBSD-src-b2c068251b6066a7f5d1e4126014a929ac3de73d.tar.gz |
Adjust the exponent before converting the result from double to
float precision. This fixes some double rounding problems for
subnormals and simplifies things a bit.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/msun/src/s_exp2f.c | 26 |
1 files changed, 10 insertions, 16 deletions
diff --git a/lib/msun/src/s_exp2f.c b/lib/msun/src/s_exp2f.c index db8542c..ffe58a2 100644 --- a/lib/msun/src/s_exp2f.c +++ b/lib/msun/src/s_exp2f.c @@ -93,12 +93,12 @@ float exp2f(float x) { double tv; - float r, t, z; - uint32_t hx, hr, ix, i0; + float t, z; + uint32_t hx, htv, ix, i0; int32_t k; /* Filter out exceptional cases. */ - GET_FLOAT_WORD(hx,x); + GET_FLOAT_WORD(hx, x); ix = hx & 0x7fffffff; /* high word of |x| */ if(ix >= 0x43000000) { /* |x| >= 128 */ if(ix >= 0x7f800000) { @@ -119,25 +119,19 @@ exp2f(float x) STRICT_ASSIGN(float, t, x + redux); GET_FLOAT_WORD(i0, t); i0 += TBLSIZE / 2; - k = (i0 >> TBLBITS) << 23; + k = (i0 >> TBLBITS) << 20; i0 &= TBLSIZE - 1; t -= redux; z = x - t; /* Compute r = exp2(y) = exp2ft[i0] * p(z). */ tv = exp2ft[i0]; - r = tv + tv * (z * (P1 + z * (P2 + z * (P3 + z * P4)))); + tv = tv + tv * (z * (P1 + z * (P2 + z * (P3 + z * P4)))); - /* Scale by 2**(k>>23). */ - if(k >= -125 << 23) { - if (k != 0) { - GET_FLOAT_WORD(hr, r); - SET_FLOAT_WORD(r, hr + k); - } - return (r); - } else { - GET_FLOAT_WORD(hr, r); - SET_FLOAT_WORD(r, hr + (k + (100 << 23))); - return (r * twom100); + /* Scale by 2**(k>>20). */ + if (k != 0) { + GET_HIGH_WORD(htv, tv); + SET_HIGH_WORD(tv, htv + k); } + return (tv); } |