use scalbn or *2.0 instead of ldexp, fix fmal

Some code assumed ldexp(x, 1) is faster than 2.0*x,
but ldexp is a wrapper around scalbn which uses
multiplications inside, so this optimization is
wrong.

This commit also fixes fmal which accidentally
used ldexp instead of ldexpl loosing precision.

There are various additional changes from the
work-in-progress const cleanups.
This commit is contained in:
nsz 2012-03-19 22:57:58 +01:00
commit 2786c7d216
8 changed files with 102 additions and 101 deletions

View file

@ -115,7 +115,7 @@ static inline long double add_and_denormalize(long double a, long double b, int
if (bits_lost != 1 ^ (int)(u.bits.manl & 1))
sum.hi = nextafterl(sum.hi, INFINITY * sum.lo);
}
return (ldexp(sum.hi, scale));
return scalbnl(sum.hi, scale);
}
/*
@ -228,7 +228,7 @@ long double fmal(long double x, long double y, long double z)
}
}
if (spread <= LDBL_MANT_DIG * 2)
zs = ldexpl(zs, -spread);
zs = scalbnl(zs, -spread);
else
zs = copysignl(LDBL_MIN, zs);
@ -254,7 +254,7 @@ long double fmal(long double x, long double y, long double z)
*/
fesetround(oround);
volatile long double vzs = zs; /* XXX gcc CSE bug workaround */
return (xy.hi + vzs + ldexpl(xy.lo, spread));
return xy.hi + vzs + scalbnl(xy.lo, spread);
}
if (oround != FE_TONEAREST) {
@ -264,13 +264,13 @@ long double fmal(long double x, long double y, long double z)
*/
fesetround(oround);
adj = r.lo + xy.lo;
return (ldexpl(r.hi + adj, spread));
return scalbnl(r.hi + adj, spread);
}
adj = add_adjusted(r.lo, xy.lo);
if (spread + ilogbl(r.hi) > -16383)
return (ldexpl(r.hi + adj, spread));
return scalbnl(r.hi + adj, spread);
else
return (add_and_denormalize(r.hi, adj, spread));
return add_and_denormalize(r.hi, adj, spread);
}
#endif