diff options
author | Eric Andersen <andersen@codepoet.org> | 2001-05-10 00:40:28 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2001-05-10 00:40:28 +0000 |
commit | 1077fa4d772832f77a677ce7fb7c2d513b959e3f (patch) | |
tree | 579bee13fb0b58d2800206366ec2caecbb15f3fc /libm/float/sinf.c | |
parent | 22358dd7ce7bb49792204b698f01a6f69b9c8e08 (diff) |
uClibc now has a math library. muahahahaha!
-Erik
Diffstat (limited to 'libm/float/sinf.c')
-rw-r--r-- | libm/float/sinf.c | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/libm/float/sinf.c b/libm/float/sinf.c new file mode 100644 index 000000000..2f1bb45b8 --- /dev/null +++ b/libm/float/sinf.c @@ -0,0 +1,283 @@ +/* sinf.c + * + * Circular sine + * + * + * + * SYNOPSIS: + * + * float x, y, sinf(); + * + * y = sinf( x ); + * + * + * + * DESCRIPTION: + * + * Range reduction is into intervals of pi/4. The reduction + * error is nearly eliminated by contriving an extended precision + * modular arithmetic. + * + * Two polynomial approximating functions are employed. + * Between 0 and pi/4 the sine is approximated by + * x + x**3 P(x**2). + * Between pi/4 and pi/2 the cosine is represented as + * 1 - x**2 Q(x**2). + * + * + * ACCURACY: + * + * Relative error: + * arithmetic domain # trials peak rms + * IEEE -4096,+4096 100,000 1.2e-7 3.0e-8 + * IEEE -8192,+8192 100,000 3.0e-7 3.0e-8 + * + * ERROR MESSAGES: + * + * message condition value returned + * sin total loss x > 2^24 0.0 + * + * Partial loss of accuracy begins to occur at x = 2^13 + * = 8192. Results may be meaningless for x >= 2^24 + * The routine as implemented flags a TLOSS error + * for x >= 2^24 and returns 0.0. + */ + +/* cosf.c + * + * Circular cosine + * + * + * + * SYNOPSIS: + * + * float x, y, cosf(); + * + * y = cosf( x ); + * + * + * + * DESCRIPTION: + * + * Range reduction is into intervals of pi/4. The reduction + * error is nearly eliminated by contriving an extended precision + * modular arithmetic. + * + * Two polynomial approximating functions are employed. + * Between 0 and pi/4 the cosine is approximated by + * 1 - x**2 Q(x**2). + * Between pi/4 and pi/2 the sine is represented as + * x + x**3 P(x**2). + * + * + * ACCURACY: + * + * Relative error: + * arithmetic domain # trials peak rms + * IEEE -8192,+8192 100,000 3.0e-7 3.0e-8 + */ + +/* +Cephes Math Library Release 2.2: June, 1992 +Copyright 1985, 1987, 1988, 1992 by Stephen L. Moshier +Direct inquiries to 30 Frost Street, Cambridge, MA 02140 +*/ + + +/* Single precision circular sine + * test interval: [-pi/4, +pi/4] + * trials: 10000 + * peak relative error: 6.8e-8 + * rms relative error: 2.6e-8 + */ +#include <math.h> + + +static float FOPI = 1.27323954473516; + +extern float PIO4F; +/* Note, these constants are for a 32-bit significand: */ +/* +static float DP1 = 0.7853851318359375; +static float DP2 = 1.30315311253070831298828125e-5; +static float DP3 = 3.03855025325309630e-11; +static float lossth = 65536.; +*/ + +/* These are for a 24-bit significand: */ +static float DP1 = 0.78515625; +static float DP2 = 2.4187564849853515625e-4; +static float DP3 = 3.77489497744594108e-8; +static float lossth = 8192.; +static float T24M1 = 16777215.; + +static float sincof[] = { +-1.9515295891E-4, + 8.3321608736E-3, +-1.6666654611E-1 +}; +static float coscof[] = { + 2.443315711809948E-005, +-1.388731625493765E-003, + 4.166664568298827E-002 +}; + +float sinf( float xx ) +{ +float *p; +float x, y, z; +register unsigned long j; +register int sign; + +sign = 1; +x = xx; +if( xx < 0 ) + { + sign = -1; + x = -xx; + } +if( x > T24M1 ) + { + mtherr( "sinf", TLOSS ); + return(0.0); + } +j = FOPI * x; /* integer part of x/(PI/4) */ +y = j; +/* map zeros to origin */ +if( j & 1 ) + { + j += 1; + y += 1.0; + } +j &= 7; /* octant modulo 360 degrees */ +/* reflect in x axis */ +if( j > 3) + { + sign = -sign; + j -= 4; + } + +if( x > lossth ) + { + mtherr( "sinf", PLOSS ); + x = x - y * PIO4F; + } +else + { +/* Extended precision modular arithmetic */ + x = ((x - y * DP1) - y * DP2) - y * DP3; + } +/*einits();*/ +z = x * x; +if( (j==1) || (j==2) ) + { +/* measured relative error in +/- pi/4 is 7.8e-8 */ +/* + y = (( 2.443315711809948E-005 * z + - 1.388731625493765E-003) * z + + 4.166664568298827E-002) * z * z; +*/ + p = coscof; + y = *p++; + y = y * z + *p++; + y = y * z + *p++; + y *= z * z; + y -= 0.5 * z; + y += 1.0; + } +else + { +/* Theoretical relative error = 3.8e-9 in [-pi/4, +pi/4] */ +/* + y = ((-1.9515295891E-4 * z + + 8.3321608736E-3) * z + - 1.6666654611E-1) * z * x; + y += x; +*/ + p = sincof; + y = *p++; + y = y * z + *p++; + y = y * z + *p++; + y *= z * x; + y += x; + } +/*einitd();*/ +if(sign < 0) + y = -y; +return( y); +} + + +/* Single precision circular cosine + * test interval: [-pi/4, +pi/4] + * trials: 10000 + * peak relative error: 8.3e-8 + * rms relative error: 2.2e-8 + */ + +float cosf( float xx ) +{ +float x, y, z; +int j, sign; + +/* make argument positive */ +sign = 1; +x = xx; +if( x < 0 ) + x = -x; + +if( x > T24M1 ) + { + mtherr( "cosf", TLOSS ); + return(0.0); + } + +j = FOPI * x; /* integer part of x/PIO4 */ +y = j; +/* integer and fractional part modulo one octant */ +if( j & 1 ) /* map zeros to origin */ + { + j += 1; + y += 1.0; + } +j &= 7; +if( j > 3) + { + j -=4; + sign = -sign; + } + +if( j > 1 ) + sign = -sign; + +if( x > lossth ) + { + mtherr( "cosf", PLOSS ); + x = x - y * PIO4F; + } +else +/* Extended precision modular arithmetic */ + x = ((x - y * DP1) - y * DP2) - y * DP3; + +z = x * x; + +if( (j==1) || (j==2) ) + { + y = (((-1.9515295891E-4 * z + + 8.3321608736E-3) * z + - 1.6666654611E-1) * z * x) + + x; + } +else + { + y = (( 2.443315711809948E-005 * z + - 1.388731625493765E-003) * z + + 4.166664568298827E-002) * z * z; + y -= 0.5 * z; + y += 1.0; + } +if(sign < 0) + y = -y; +return( y ); +} + |