hidden double __sin(double,double,int);
hidden double __cos(double,double);
hidden double __tan(double,double,int);
-hidden double __expo2(double);
+hidden double __expo2(double,double);
hidden int __rem_pio2f(float,double*);
hidden float __sindf(double);
hidden float __cosdf(double);
hidden float __tandf(double,int);
-hidden float __expo2f(float);
+hidden float __expo2f(float,float);
hidden int __rem_pio2l(long double, long double *);
hidden long double __sinl(long double, long double, int);
static const double kln2 = 0x1.62066151add8bp+10;
/* exp(x)/2 for x >= log(DBL_MAX), slightly better than 0.5*exp(x/2)*exp(x/2) */
-double __expo2(double x)
+double __expo2(double x, double sign)
{
double scale;
/* note that k is odd and scale*scale overflows */
INSERT_WORDS(scale, (uint32_t)(0x3ff + k/2) << 20, 0);
/* exp(x - k ln2) * 2**(k-1) */
- return exp(x - kln2) * scale * scale;
+ /* in directed rounding correct sign before rounding or overflow is important */
+ return exp(x - kln2) * (sign * scale) * scale;
}
static const float kln2 = 0x1.45c778p+7f;
/* expf(x)/2 for x >= log(FLT_MAX), slightly better than 0.5f*expf(x/2)*expf(x/2) */
-float __expo2f(float x)
+float __expo2f(float x, float sign)
{
float scale;
/* note that k is odd and scale*scale overflows */
SET_FLOAT_WORD(scale, (uint32_t)(0x7f + k/2) << 23);
/* exp(x - k ln2) * 2**(k-1) */
- return expf(x - kln2) * scale * scale;
+ /* in directed rounding correct sign before rounding or overflow is important */
+ return expf(x - kln2) * (sign * scale) * scale;
}
/* |x| > log(DBL_MAX) or nan */
/* note: the result is stored to handle overflow */
- t = __expo2(x);
+ t = __expo2(x, 1.0);
return t;
}
}
/* |x| > log(FLT_MAX) or nan */
- t = __expo2f(x);
+ t = __expo2f(x, 1.0f);
return t;
}
/* |x| > log(DBL_MAX) or nan */
/* note: the result is stored to handle overflow */
- t = 2*h*__expo2(absx);
+ t = __expo2(absx, 2*h);
return t;
}
}
/* |x| > logf(FLT_MAX) or nan */
- t = 2*h*__expo2f(absx);
+ t = __expo2f(absx, 2*h);
return t;
}