Fixed some magic numbers.

The threshold for not being tiny was confusing and too small.  Use the
usual 2**-12 threshold and simplify the algorithm slightly so that
this threshold works (now use the threshold for sinhf() instead of one
for 1+expm1()).  This is just a small optimization.

The magic number 22 is log(DBL_EPSILON)/2 plus slop.  This is bogus
for float precision.  Use 9 (~log(FLT_EPSILON)/2 plus less slop than
for double precision).

The threshold for switching from returning exp(x)/2 to returning
exp(x/2)^2/2 was a little smaller than necessary.  This was not quite
harmless since the exp(x/2)^2/2 case is inaccurate.  Fixing it happens
to avoid accuracy problems for 2*6 of the 2*151 args that were handled
by the exp(x)/2 case.  This leaves accuracy problems for about 2*19997
args near the overflow threshold (~89); the maximum error there is
2.5029 ulps.

There are also accuracy probles for args in +-[0.5*ln2, 9] -- 2*188885
args with errors of more than 1 ulp, with a maximum error of 1.384 ulps.

Fixed a syntax error and naming errors in pseudo-code in comments.
This commit is contained in:
Bruce Evans 2005-11-13 00:08:23 +00:00
parent 26cd969f5e
commit c24b7984fc
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=152352

View file

@ -38,20 +38,20 @@ __ieee754_coshf(float x)
if(ix<0x3eb17218) {
t = expm1f(fabsf(x));
w = one+t;
if (ix<0x24000000) return w; /* cosh(tiny) = 1 */
if (ix<0x39800000) return one; /* cosh(tiny) = 1 */
return one+(t*t)/(w+w);
}
/* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */
if (ix < 0x41b00000) {
/* |x| in [0.5*ln2,9], return (exp(|x|)+1/exp(|x|))/2; */
if (ix < 0x41100000) {
t = __ieee754_expf(fabsf(x));
return half*t+half/t;
}
/* |x| in [22, log(maxdouble)] return half*exp(|x|) */
if (ix < 0x42b17180) return half*__ieee754_expf(fabsf(x));
/* |x| in [9, log(maxfloat)] return half*exp(|x|) */
if (ix < 0x42b17217) return half*__ieee754_expf(fabsf(x));
/* |x| in [log(maxdouble), overflowthresold] */
/* |x| in [log(maxfloat), overflowthresold] */
if (ix<=0x42b2d4fc) {
w = __ieee754_expf(half*fabsf(x));
t = half*w;