Use only double precision for "kernel" tanf (except for returning float).
This is a minor interface change. The function is renamed from __kernel_tanf() to __kernel_tandf() so that misues of it will cause link errors and not crashes. This version is a routine translation with no special optimizations for accuracy or efficiency. It gives an unimportant increase in accuracy, from ~0.9 ulps to 0.5285 ulps. Almost all of the error is from the minimax polynomial (~0.03 ulps and the final rounding step (< 0.5 ulps). It gives strange differences in efficiency in the -5 to +10% range, with -O1 fairly consistently becoming faster and -O2 slower on AXP and A64 with gcc-3.3 and gcc-3.4.
This commit is contained in:
parent
11e07dda30
commit
1e3150891d
@ -21,35 +21,32 @@ static char rcsid[] = "$FreeBSD$";
|
||||
#include "math.h"
|
||||
#include "math_private.h"
|
||||
|
||||
static const float
|
||||
pio4 = 7.8539812565e-01, /* 0x3f490fda */
|
||||
pio4lo= 3.7748947079e-08, /* 0x33222168 */
|
||||
/* |tan(x)/x - t(x)| < 2**-29.2 (~[-1.73e-09, 1.724e-09]). */
|
||||
static const double
|
||||
pio4 = M_PI_4,
|
||||
/* |tan(x)/x - t(x)| < 2**-29.1 (~[-1.72e-09, 1.719e-09]). */
|
||||
T[] = {
|
||||
0xaaaaa3.0p-25, /* 0.33333310485 */
|
||||
0x888b06.0p-26, /* 0.13334283238 */
|
||||
0xdc84c8.0p-28, /* 0.053837567568 */
|
||||
0xb9d8f1.0p-29, /* 0.022686453536 */
|
||||
0xcfe632.0p-31, /* 0.0063445800915 */
|
||||
0xeaf97e.0p-31, /* 0.0071708550677 */
|
||||
0x1555545f8b54d0.0p-54, /* 0.333333104424423432022 */
|
||||
0x111160cdc2c9af.0p-55, /* 0.133342838734802765499 */
|
||||
0x1b9097e5693cd0.0p-57, /* 0.0538375346701457369036 */
|
||||
0x173b2333895b6f.0p-58, /* 0.0226865291791357691353 */
|
||||
0x19fcb197e825ab.0p-60, /* 0.00634450313965243938713 */
|
||||
0x1d5f3701b44a27.0p-60, /* 0.00717088210082520490646 */
|
||||
};
|
||||
|
||||
#ifdef INLINE_KERNEL_TANF
|
||||
extern inline
|
||||
#endif
|
||||
float
|
||||
__kernel_tanf(float x, float y, int iy)
|
||||
__kernel_tandf(double x, int iy)
|
||||
{
|
||||
float z,r,v,w,s;
|
||||
double z,r,v,w,s;
|
||||
int32_t ix,hx;
|
||||
|
||||
GET_FLOAT_WORD(hx,x);
|
||||
ix = hx&0x7fffffff;
|
||||
if(ix>=0x3f2ca140) { /* |x|>=0.67434 */
|
||||
if(hx<0) {x = -x; y = -y;}
|
||||
z = pio4-x;
|
||||
w = pio4lo-y;
|
||||
x = z+w; y = 0.0;
|
||||
if(hx<0) {x = -x;}
|
||||
x = pio4-x;
|
||||
}
|
||||
z = x*x;
|
||||
w = z*z;
|
||||
@ -60,13 +57,13 @@ __kernel_tanf(float x, float y, int iy)
|
||||
r = T[1]+w*(T[3]+w*T[5]);
|
||||
v = z*(T[2]+w*T[4]);
|
||||
s = z*x;
|
||||
r = y + z*(s*(r+v)+y);
|
||||
r = z*s*(r+v);
|
||||
r += T[0]*s;
|
||||
w = x+r;
|
||||
if(ix>=0x3f2ca140) {
|
||||
v = (float)iy;
|
||||
return (float)(1-((hx>>30)&2))*(v-(float)2.0*(x-(w*w/(w+v)-r)));
|
||||
v = (double)iy;
|
||||
return (double)(1-((hx>>30)&2))*(v-2.0*(x-(w*w/(w+v)-r)));
|
||||
}
|
||||
if(iy==1) return w;
|
||||
else return -1.0/((double)x+r);
|
||||
else return -1.0/w;
|
||||
}
|
||||
|
@ -266,7 +266,7 @@ int __kernel_rem_pio2(double*,double*,int,int,int,const int*);
|
||||
int __ieee754_rem_pio2f(float,float*);
|
||||
float __kernel_sinf(float,float,int);
|
||||
float __kernel_cosf(float,float);
|
||||
float __kernel_tanf(float,float,int);
|
||||
float __kernel_tandf(double,int);
|
||||
int __kernel_rem_pio2f(float*,float*,int,int,int,const int*);
|
||||
|
||||
#endif /* !_MATH_PRIVATE_H_ */
|
||||
|
@ -29,12 +29,6 @@ t2pio2 = 2*M_PI_2, /* 0x400921FB, 0x54442D18 */
|
||||
t3pio2 = 3*M_PI_2, /* 0x4012D97C, 0x7F3321D2 */
|
||||
t4pio2 = 4*M_PI_2; /* 0x401921FB, 0x54442D18 */
|
||||
|
||||
static inline float
|
||||
__kernel_tandf(double x, int iy)
|
||||
{
|
||||
return __kernel_tanf((float)x, x - (float)x, iy);
|
||||
}
|
||||
|
||||
float
|
||||
tanf(float x)
|
||||
{
|
||||
@ -47,7 +41,7 @@ tanf(float x)
|
||||
if(ix <= 0x3f490fda) { /* |x| ~<= pi/4 */
|
||||
if(ix<0x39800000) /* |x| < 2**-12 */
|
||||
if(((int)x)==0) return x; /* x with inexact if x != 0 */
|
||||
return __kernel_tanf(x,0.0,1);
|
||||
return __kernel_tandf(x,1);
|
||||
}
|
||||
if(ix<=0x407b53d1) { /* |x| ~<= 5*pi/4 */
|
||||
if(ix<=0x4016cbe3) /* |x| ~<= 3pi/4 */
|
||||
@ -69,6 +63,6 @@ tanf(float x)
|
||||
else {
|
||||
n = __ieee754_rem_pio2f(x,y);
|
||||
/* integer parameter: 1 -- n even; -1 -- n odd */
|
||||
return __kernel_tanf(y[0],y[1],1-((n&1)<<1));
|
||||
return __kernel_tandf((double)y[0]+y[1],1-((n&1)<<1));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user