| |
| /* @(#)z_atangent.c 1.0 98/08/13 */ |
| /****************************************************************** |
| * The following routines are coded directly from the algorithms |
| * and coefficients given in "Software Manual for the Elementary |
| * Functions" by William J. Cody, Jr. and William Waite, Prentice |
| * Hall, 1980. |
| ******************************************************************/ |
| |
| /* |
| FUNCTION |
| <<atan>>, <<atanf>>, <<atan2>>, <<atan2f>>, <<atangent>>, <<atangentf>>---arc tangent |
| |
| INDEX |
| atan2 |
| INDEX |
| atan2f |
| INDEX |
| atan |
| INDEX |
| atanf |
| |
| ANSI_SYNOPSIS |
| #include <math.h> |
| double atan(double <[x]>); |
| float atan(float <[x]>); |
| double atan2(double <[y]>,double <[x]>); |
| float atan2f(float <[y]>,float <[x]>); |
| |
| TRAD_SYNOPSIS |
| #include <math.h> |
| double atan2(<[y]>,<[x]>); |
| double <[y]>; |
| double <[x]>; |
| |
| float atan2f(<[y]>,<[x]>); |
| float <[y]>; |
| float <[x]>; |
| |
| #include <math.h> |
| double atan(<[x]>); |
| double <[x]>; |
| |
| float atanf(<[x]>); |
| float <[x]>; |
| |
| DESCRIPTION |
| |
| <<atan2>> computes the inverse tangent (arc tangent) of y / x. |
| |
| <<atan2f>> is identical to <<atan2>>, save that it operates on <<floats>>. |
| |
| <<atan>> computes the inverse tangent (arc tangent) of the input value. |
| |
| <<atanf>> is identical to <<atan>>, save that it operates on <<floats>>. |
| |
| RETURNS |
| @ifnottex |
| <<atan>> returns a value in radians, in the range of -pi/2 to pi/2. |
| <<atan2>> returns a value in radians, in the range of -pi/2 to pi/2. |
| @end ifnottex |
| @tex |
| <<atan>> returns a value in radians, in the range of $-\pi/2$ to $\pi/2$. |
| <<atan2>> returns a value in radians, in the range of $-\pi/2$ to $\pi/2$. |
| @end tex |
| |
| PORTABILITY |
| <<atan>> is ANSI C. <<atanf>> is an extension. |
| <<atan2>> is ANSI C. <<atan2f>> is an extension. |
| |
| */ |
| |
| /****************************************************************** |
| * Arctangent |
| * |
| * Input: |
| * x - floating point value |
| * |
| * Output: |
| * arctangent of x |
| * |
| * Description: |
| * This routine calculates arctangents. |
| * |
| *****************************************************************/ |
| #include <float.h> |
| #include "fdlibm.h" |
| #include "zmath.h" |
| |
| #ifndef _DOUBLE_IS_32BITS |
| |
| static const double ROOT3 = 1.73205080756887729353; |
| static const double a[] = { 0.0, 0.52359877559829887308, 1.57079632679489661923, |
| 1.04719755119659774615 }; |
| static const double q[] = { 0.41066306682575781263e+2, |
| 0.86157349597130242515e+2, |
| 0.59578436142597344465e+2, |
| 0.15024001160028576121e+2 }; |
| static const double p[] = { -0.13688768894191926929e+2, |
| -0.20505855195861651981e+2, |
| -0.84946240351320683534e+1, |
| -0.83758299368150059274 }; |
| |
| double |
| _DEFUN (atangent, (double, double, double, int), |
| double x _AND |
| double v _AND |
| double u _AND |
| int arctan2) |
| { |
| double f, g, R, P, Q, A, res; |
| int N; |
| int branch = 0; |
| int expv, expu; |
| |
| /* Preparation for calculating arctan2. */ |
| if (arctan2) |
| { |
| if (u == 0.0) |
| if (v == 0.0) |
| { |
| errno = ERANGE; |
| return (z_notanum.d); |
| } |
| else |
| { |
| branch = 1; |
| res = __PI_OVER_TWO; |
| } |
| |
| if (!branch) |
| { |
| int e; |
| /* Get the exponent values of the inputs. */ |
| g = frexp (v, &expv); |
| g = frexp (u, &expu); |
| |
| /* See if a divide will overflow. */ |
| e = expv - expu; |
| if (e > DBL_MAX_EXP) |
| { |
| branch = 1; |
| res = __PI_OVER_TWO; |
| } |
| |
| /* Also check for underflow. */ |
| else if (e < DBL_MIN_EXP) |
| { |
| branch = 2; |
| res = 0.0; |
| } |
| } |
| } |
| |
| if (!branch) |
| { |
| if (arctan2) |
| f = fabs (v / u); |
| else |
| f = fabs (x); |
| |
| if (f > 1.0) |
| { |
| f = 1.0 / f; |
| N = 2; |
| } |
| else |
| N = 0; |
| |
| if (f > (2.0 - ROOT3)) |
| { |
| A = ROOT3 - 1.0; |
| f = (((A * f - 0.5) - 0.5) + f) / (ROOT3 + f); |
| N++; |
| } |
| |
| /* Check for values that are too small. */ |
| if (-z_rooteps < f && f < z_rooteps) |
| res = f; |
| |
| /* Calculate the Taylor series. */ |
| else |
| { |
| g = f * f; |
| P = (((p[3] * g + p[2]) * g + p[1]) * g + p[0]) * g; |
| Q = (((g + q[3]) * g + q[2]) * g + q[1]) * g + q[0]; |
| R = P / Q; |
| |
| res = f + f * R; |
| } |
| |
| if (N > 1) |
| res = -res; |
| |
| res += a[N]; |
| } |
| |
| if (arctan2) |
| { |
| if (u < 0.0) |
| res = __PI - res; |
| if (v < 0.0) |
| res = -res; |
| } |
| else if (x < 0.0) |
| { |
| res = -res; |
| } |
| |
| return (res); |
| } |
| |
| #endif /* _DOUBLE_IS_32BITS */ |