/*
   FUNCTION:  double atan2 (y, x)

   PURPOSE:
	To compute the double precision arctangent of y/x in radians.

   INPUT PARAMETERS:
	double y - The numerator (rise) of y/x.
	double x - The denomenator (run) of y/x.

   OUTPUT PARAMETERS:
	Returned - Arctan(y/x) in radians.

   DESCRIPTION:
	This routine computes the arctangent via polynomial evaluation. See
	the Arctangent algorithm 5076 from Hart's "Computer Approximations".

   WRITTEN BY:  Scott D. Roth		DATE:  March 27, 1981
*/


#define WHOLE_PI	3.1415926535897932d
#define HALF_PI		1.5707963267948966d
#define FORTH_PI	0.78539816339744831d
#define TAN_8TH_PI	0.41421356d
#define TAN_3_8THS_PI	2.4142136d

static double q[4] = {		/* Coefficients of polynomial q */
	.44541340059290680E2d,
	.92324801072300975E2d,
	.62835930511032377E2d,
	.15503977551421988E2d};
static double p[5] = {		/* Coefficients of polynomial p */
	.44541340059290680E2d,
	.77477687719204209E2d,
	.40969264832102256E2d,
	.66605790170092627E1d,
	.15897402884823070E0d};

double atan2 (y, x)
    double y, x;
	{
	double yx, adjust, atan_yx, s, p_val, q_val;
	register int y_pos, x_pos;			/* Booleans */

	y_pos = (y >= 0);		/* Remember signs for later */
	if (!(x_pos = (x > 0)))
	    if (x == 0)			/* Special 0 denominator case */
		return(y_pos ? HALF_PI : -HALF_PI);

	yx = y / x;
	if (y_pos ^ x_pos)		/* Make yx positive */
	    yx = -yx;
	adjust = 0;
	if (yx >= TAN_8TH_PI)		/* Adjust value to be within */
	    if (yx >= TAN_3_8THS_PI)	/* tan(PI/8) and tan(3*PI/8) */
		{
		yx = -1.0d / yx;
		adjust = HALF_PI;
		}
	    else
		{
		yx = (yx - 1.0d) / (yx + 1.0d);
		adjust = FORTH_PI;
		}		
	s = yx * yx;
					/* Evaluate P polynomial */
	p_val = ((((p[4] * s + p[3]) * s + p[2]) * s + p[1]) * s + p[0]) * yx;
					/* Evaluate Q polynomial */
	q_val = (((s + q[3]) * s + q[2]) * s + q[1]) * s + q[0];

					/* Atan = P(yx**2) / Q(yx**2) */
	atan_yx = p_val / q_val + adjust;

	if (!x_pos)
	    atan_yx = WHOLE_PI - atan_yx;
	return (y_pos ? atan_yx : -atan_yx);
	}
