diff options
author | Christopher Faylor <me@cgf.cx> | 2000-02-17 19:39:52 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2000-02-17 19:39:52 +0000 |
commit | 8a0efa53e44919bcf5ccb1d3353618a82afdf8bc (patch) | |
tree | 68c3dbf3f2c6fd5d49777def9914d77b5cd4589d /newlib/libm/mathfp/sf_atangent.c | |
parent | 1fd5e000ace55b323124c7e556a7a864b972a5c4 (diff) | |
download | cygnal-8a0efa53e44919bcf5ccb1d3353618a82afdf8bc.tar.gz cygnal-8a0efa53e44919bcf5ccb1d3353618a82afdf8bc.tar.bz2 cygnal-8a0efa53e44919bcf5ccb1d3353618a82afdf8bc.zip |
import newlib-2000-02-17 snapshot
Diffstat (limited to 'newlib/libm/mathfp/sf_atangent.c')
-rw-r--r-- | newlib/libm/mathfp/sf_atangent.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/newlib/libm/mathfp/sf_atangent.c b/newlib/libm/mathfp/sf_atangent.c new file mode 100644 index 000000000..55a90063c --- /dev/null +++ b/newlib/libm/mathfp/sf_atangent.c @@ -0,0 +1,140 @@ + +/* @(#)z_atangentf.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. + ******************************************************************/ +/****************************************************************** + * Arctangent + * + * Input: + * x - floating point value + * + * Output: + * arctangent of x + * + * Description: + * This routine calculates arctangents. + * + *****************************************************************/ + +#include <float.h> +#include "fdlibm.h" +#include "zmath.h" + +static const float ROOT3 = 1.732050807; +static const float a[] = { 0.0, 0.523598775, 1.570796326, + 1.047197551 }; +static const float q[] = { 0.1412500740e+1 }; +static const float p[] = { -0.4708325141, -0.5090958253e-1 }; + +float +_DEFUN (atangentf, (float, float, float, int), + float x _AND + float v _AND + float u _AND + int arctan2) +{ + float 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_f.f); + } + else + { + branch = 1; + res = __PI_OVER_TWO; + } + + if (!branch) + { + int e; + /* Get the exponent values of the inputs. */ + g = frexpf (v, &expv); + g = frexpf (u, &expu); + + /* See if a divide will overflow. */ + e = expv - expu; + if (e > FLT_MAX_EXP) + { + branch = 1; + res = __PI_OVER_TWO; + } + + /* Also check for underflow. */ + else if (e < FLT_MIN_EXP) + { + branch = 2; + res = 0.0; + } + } + } + + if (!branch) + { + if (arctan2) + f = fabsf (v / u); + else + f = fabsf (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 && f < z_rooteps_f) + res = f; + + /* Calculate the Taylor series. */ + else + { + g = f * f; + P = (p[1] * g + p[0]) * g; + Q = g + q[0]; + R = P / Q; + + res = f + f * R; + } + + if (N > 1) + res = -res; + + res += a[N]; + } + + if (arctan2) + { + if (u < 0.0 || branch == 2) + res = __PI - res; + if (v < 0.0 || branch == 1) + res = -res; + } + else if (x < 0.0) + { + res = -res; + } + + return (res); +} |