home *** CD-ROM | disk | FTP | other *** search
- /* asin.c
- *
- * Inverse circular sine
- *
- *
- *
- * SYNOPSIS:
- *
- * double x, y, asin();
- *
- * y = asin( x );
- *
- *
- *
- * DESCRIPTION:
- *
- * Returns radian angle between -pi/2 and +pi/2 whose sine is x.
- *
- * A rational function of the form x + x**3 P(x**2)/Q(x**2)
- * is used for |x| in the interval [0, 0.5]. If |x| > 0.5 it is
- * transformed by the identity
- *
- * asin(x) = pi/2 - 2 asin( sqrt( (1-x)/2 ) ).
- *
- *
- * ACCURACY:
- *
- * Relative error:
- * arithmetic range # trials peak rms
- * DEC -1, 1 20000 5.7e-17 1.2e-17
- * IEEE -1, 1 10000 4.6e-16 8.4e-17
- *
- *
- * ERROR MESSAGES:
- *
- * message condition value returned
- * asin domain |x| > 1 0.0
- *
- */
- /* acos()
- *
- * Inverse circular cosine
- *
- *
- *
- * SYNOPSIS:
- *
- * double x, y, acos();
- *
- * y = acos( x );
- *
- *
- *
- * DESCRIPTION:
- *
- * Returns radian angle between -pi/2 and +pi/2 whose cosine
- * is x.
- *
- * Analytically, acos(x) = pi/2 - asin(x). However if |x| is
- * near 1, there is cancellation error in subtracting asin(x)
- * from pi/2. Hence if x < -0.5,
- *
- * acos(x) = pi - 2.0 * asin( sqrt((1+x)/2) );
- *
- * or if x > +0.5,
- *
- * acos(x) = 2.0 * asin( sqrt((1-x)/2) ).
- *
- *
- * ACCURACY:
- *
- * Relative error:
- * arithmetic range # trials peak rms
- * DEC -1, 1 13000 3.2e-17 7.8e-18
- * IEEE -1, 1 10000 2.1e-16 6.7e-17
- *
- *
- * ERROR MESSAGES:
- *
- * message condition value returned
- * asin domain |x| > 1 0.0
- */
-
- /* asin.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[] = {
- -6.96822599948686174217E-1,
- 1.01598286089872099722E1,
- -3.97340771391578757294E1,
- 5.72912144709846496134E1,
- -2.74148200465925708020E1
- };
- static double Q[] = {
- /* 1.00000000000000000000E0,*/
- -2.38368245005177488242E1,
- 1.51095072703128995631E2,
- -3.82340216045978957023E2,
- 4.17767300951716199422E2,
- -1.64488920279555473283E2
- };
- #endif
-
- #ifdef DEC
- static short P[] = {
- 0140062,0061367,0042744,0127464,
- 0041042,0107250,0070611,0005470,
- 0141436,0167661,0165345,0131200,
- 0041545,0025064,0020124,0000411,
- 0141333,0050615,0026056,0134351
- };
- static short Q[] = {
- /*0040200,0000000,0000000,0000000,*/
- 0141276,0130721,0005461,0134336,
- 0042027,0014126,0127506,0127155,
- 0142277,0025614,0031413,0103353,
- 0042320,0161066,0165346,0163707,
- 0142044,0076451,0160443,0005274
- };
- #endif
-
- #ifdef IBMPC
- static short P[] = {
- 0x95e7,0xe8bc,0x4c5e,0xbfe6,
- 0x2167,0x0e31,0x51d5,0x4024,
- 0xb650,0x3d5c,0xddf6,0xc043,
- 0x8021,0x840a,0xa546,0x404c,
- 0xd71d,0xa585,0x6a31,0xc03b
- };
- static short Q[] = {
- /*0x0000,0x0000,0x0000,0x3ff0,*/
- 0x371c,0x2166,0xd63a,0xc037,
- 0xd5ce,0xd5e8,0xe30a,0x4062,
- 0x70dd,0x8661,0xe571,0xc077,
- 0xdcf9,0xdd5c,0x1c46,0x407a,
- 0x6158,0x3c24,0x8fa5,0xc064
- };
- #endif
-
- #ifdef MIEEE
- static short P[] = {
- 0xbfe6,0x4c5e,0xe8bc,0x95e7,
- 0x4024,0x51d5,0x0e31,0x2167,
- 0xc043,0xddf6,0x3d5c,0xb650,
- 0x404c,0xa546,0x840a,0x8021,
- 0xc03b,0x6a31,0xa585,0xd71d
- };
- static short Q[] = {
- 0xc037,0xd63a,0x2166,0x371c,
- 0x4062,0xe30a,0xd5e8,0xd5ce,
- 0xc077,0xe571,0x8661,0x70dd,
- 0x407a,0x1c46,0xdd5c,0xdcf9,
- 0xc0640x8fa5,0x3c24,0x6158
- };
- #endif
-
- double asin(x)
- double x;
- {
- double a, p, z, zz;
- double sqrt(), polevl(), p1evl();
- short sign, flag;
- extern double PIO2;
-
- if( x > 0 )
- {
- sign = 1;
- a = x;
- }
- else
- {
- sign = -1;
- a = -x;
- }
-
- if( a > 1.0 )
- {
- mtherr( "asin", DOMAIN );
- return( 0.0 );
- }
-
- if( a < 1.0e-7 )
- {
- z = a;
- goto done;
- }
-
- if( a > 0.5 )
- {
- zz = 0.5 -a;
- zz = (zz + 0.5)/2.0;
- z = sqrt( zz );
- flag = 1;
- }
- else
- {
- z = a;
- zz = z * z;
- flag = 0;
- }
-
- p = zz * polevl( zz, P, 4)/p1evl( zz, Q, 5);
- z = z * p + z;
- if( flag != 0 )
- {
- z = z + z;
- z = PIO2 - z;
- }
- done:
- if( sign < 0 )
- z = -z;
- return(z);
- }
-
-
- extern double PIO2, PI;
-
- double acos(x)
- double x;
- {
- double asin(), sqrt();
-
- if( x < -1.0 )
- goto domerr;
-
- if( x < -0.5)
- return( PI - 2.0 * asin( sqrt(0.5*(1.0+x)) ) );
-
- if( x > 1.0 )
- {
- domerr: mtherr( "acos", DOMAIN );
- return( 0.0 );
- }
-
- if( x > 0.5 )
- return( 2.0 * asin( sqrt(0.5*(1.0-x) ) ) );
-
- return( PIO2 - asin(x) );
- }
-