home *** CD-ROM | disk | FTP | other *** search
- /* atan.c
- *
- * Inverse circular tangent
- * (arctangent)
- *
- *
- *
- * SYNOPSIS:
- *
- * double x, y, atan();
- *
- * y = atan( x );
- *
- *
- *
- * DESCRIPTION:
- *
- * Returns radian angle between -pi/2 and +pi/2 whose tangent
- * is x.
- *
- * Range reduction is from four intervals into the interval
- * from zero to tan( pi/8 ). The approximant uses a rational
- * function of degree 3/4 of the form x + x**3 P(x)/Q(x).
- *
- *
- *
- * ACCURACY:
- *
- * Relative error:
- * arithmetic range # trials peak rms
- * DEC 0, 10 9500 2.8e-17 8.6e-18
- * IEEE 0, 10 5000 2.4e-16 7.6e-17
- *
- */
- /* atan2()
- *
- * Quadrant correct inverse circular tangent
- *
- *
- *
- * SYNOPSIS:
- *
- * double x, y, z, atan2();
- *
- * z = atan2( x, y );
- *
- *
- *
- * DESCRIPTION:
- *
- * Returns radian angle between 0 and +2pi whose tangent
- * is y/x.
- *
- *
- *
- * ACCURACY:
- *
- * See atan.c.
- *
- */
-
- /* atan.c */
-
-
- /*
- Cephes Math Library Release 2.0: April, 1987
- Copyright 1984, 1987 by Stephen L. Moshier
- Direct inquiries to 30 Frost Street, Cambridge, MA 02140
- */
-
-
- #include "mconf.h"
-
- #ifdef UNK
- static double P[] = {
- -8.40980878064499716001E-1,
- -8.83860837023772394279E0,
- -2.18476213081316705724E1,
- -1.48307050340438946993E1
- };
- static double Q[] = {
- /* 1.00000000000000000000E0,*/
- 1.54974124675307267552E1,
- 6.27906555762653017263E1,
- 9.22381329856214406485E1,
- 4.44921151021319438465E1,
- };
-
- /* tan( 3*pi/8 ) */
- static double T3P8 = 2.41421356237309504880;
-
- /* tan( pi/8 ) */
- static double TP8 = 0.41421356237309504880;
- #endif
-
- #ifdef DEC
- static short P[] = {
- 0140127,0045205,0153731,0030027,
- 0141015,0065360,0116105,0025210,
- 0141256,0143755,0127056,0105716,
- 0141155,0045221,0056235,0072437
- };
- static short Q[] = {
- /*0040200,0000000,0000000,0000000,*/
- 0041167,0172546,0143212,0126224,
- 0041573,0024641,0116611,0153210,
- 0041670,0074754,0110422,0127624,
- 0041461,0173755,0002566,0014374
- };
-
- /* tan( 3*pi/8 ) = 2.41421356237309504880 */
- static short T3P8A[] = {040432,0101171,0114774,0167462,};
- #define T3P8 *(double *)T3P8A
-
- /* tan( pi/8 ) = 0.41421356237309504880 */
- static short TP8A[] = {037724,011714,0147747,074622,};
- #define TP8 *(double *)TP8A
- #endif
-
- #ifdef IBMPC
- static short P[] = {
- 0x2603,0xbafb,0xe950,0xbfea,
- 0xa551,0x1388,0xad5e,0xc021,
- 0xd17a,0xb5c5,0xd8fd,0xc035,
- 0xaea4,0x2b93,0xa952,0xc02d
- };
- static short Q[] = {
- /*0x0000,0x0000,0x0000,0x3ff0,*/
- 0x5592,0xd8d1,0xfeac,0x402e,
- 0x3ad1,0x33b1,0x6534,0x404f,
- 0x55f2,0x9222,0x0f3d,0x4057,
- 0xc31f,0xa0ae,0x3efd,0x4046
- };
-
- /* tan( 3*pi/8 ) = 2.41421356237309504880 */
- static short T3P8A[] = {0x9de6,0x333f,0x504f,0x4003};
- #define T3P8 *(double *)T3P8A
-
- /* tan( pi/8 ) = 0.41421356237309504880 */
- static short TP8A[] = {0xef32,0x99fc,0x8279,0x3fda};
- #define TP8 *(double *)TP8A
- #endif
-
- #ifdef MIEEE
- static short P[] = {
- 0xbfea,0xe950,0xbafb,0x2603,
- 0xc021,0xad5e,0x1388,0xa551,
- 0xc035,0xd8fd,0xb5c5,0xd17a,
- 0xc02d,0xa952,0x2b93,0xaea4
- };
- static short Q[] = {
- 0x402e,0xfeac,0xd8d1,0x5592,
- 0x404f,0x6534,0x33b1,0x3ad1,
- 0x4057,0x0f3d,0x9222,0x55f2,
- 0x4046,0x3efd,0xa0ae,0xc31f,
- };
-
- /* tan( 3*pi/8 ) = 2.41421356237309504880 */
- static short T3P8A[] = {
- 0x4003,0x504f,0x333f,0x9de6
- };
- #define T3P8 *(double *)T3P8A
-
- /* tan( pi/8 ) = 0.41421356237309504880 */
- static short TP8A[] = {
- 0x3fda,0x8279,0x99fc,0xef32
- };
- #define TP8 *(double *)TP8A
- #endif
-
-
- double atan(x)
- double x;
- {
- extern double PIO2, PIO4;
- double y,z,p,q;
- double polevl(), p1evl();
- short sign;
-
- /* make argument positive and save the sign */
- sign = 1;
- if( x < 0.0 )
- {
- sign = -1;
- x = -x;
- }
-
- /* range reduction */
- if( x > T3P8 )
- {
- y = PIO2;
- x = -( 1.0/x );
- }
-
- else if( x > TP8 )
- {
- y = PIO4;
- x = (x-1.0)/(x+1.0);
- }
- else
- y = 0.0;
-
- /* rational form in x**2 */
- z = x * x;
- y = y + ( polevl( z, P, 3 ) / p1evl( z, Q, 4 ) ) * z * x + x;
-
- if( sign < 0 )
- y = -y;
-
- return(y);
- }
-
- /* atan2 */
-
- extern double PI, PIO2;
-
- double atan2( x, y )
- double x, y;
- {
- double z, w;
- short code;
- double atan();
-
-
- code = 0;
-
- if( x < 0.0 )
- code = 2;
- if( y < 0.0 )
- code |= 1;
-
- if( x == 0.0 )
- {
- if( code & 1 )
- return( 3.0*PIO2 );
- if( y == 0.0 )
- return( 0.0 );
- return( PIO2 );
- }
-
- if( y == 0.0 )
- {
- if( code & 2 )
- return( PI );
- return( 0.0 );
- }
-
-
- switch( code )
- {
- case 0: w = 0.0; break;
- case 1: w = 2.0 * PI; break;
- case 2:
- case 3: w = PI; break;
- }
-
- z = atan( y/x );
-
- return( w + z );
- }
-