summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authordas <das@FreeBSD.org>2008-01-28 01:19:07 +0000
committerdas <das@FreeBSD.org>2008-01-28 01:19:07 +0000
commitb2c068251b6066a7f5d1e4126014a929ac3de73d (patch)
tree85255327baddeb92c4e5046d1ae3c15c405f71bb /lib
parenta15e8d3ada60473573df3e6aab707dbd1d10e38a (diff)
downloadFreeBSD-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.c26
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);
}
OpenPOWER on IntegriCloud