diff options
Diffstat (limited to 'lib/msun/src')
-rw-r--r-- | lib/msun/src/k_cosf.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/lib/msun/src/k_cosf.c b/lib/msun/src/k_cosf.c index fb021ed..4239ae1 100644 --- a/lib/msun/src/k_cosf.c +++ b/lib/msun/src/k_cosf.c @@ -44,10 +44,21 @@ __kernel_cosf(float x, float y) if(ix < 0x3e99999a) /* if |x| < 0.3 */ return one - ((float)0.5*z - (z*r - x*y)); else { + /* + * qx is an approximation to x*x/2 such that 1-qx and x*x/2-qx + * are both exact. Its implementation is optimized for + * efficiency in preference to accuracy. We use x*x/2 ~ x/4 for + * x near 0.5 and mask off just enough low bits (3) for both of + * the above differences to be exact. We use a constant for + * x > 0.78125 to keep using the same algorithm as k_cos.c, + * although this gives only a small improvement in accuracy, at + * least here. Using x*x/2 to approximate itself (masking off + * 3 low bits again) would give better accuracy. + */ if(ix > 0x3f480000) { /* x > 0.78125 */ qx = (float)0.28125; } else { - SET_FLOAT_WORD(qx,ix-0x01000000); /* x/4 */ + SET_FLOAT_WORD(qx,(ix-0x01000000)&0xfffffff8); } hz = (float)0.5*z-qx; a = one-qx; |