/*	Copyright (c) 1984, 1986, 1987, 1988 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/

#ident	"@(#)libm:i386/atan.c	1.2"
#ident "@(#)atan.c	2.2 - 87/04/20"

/*LINTLIBRARY*/

/*
 *	atan returns the arctangent of its double-precision argument,
 *	in the range [-pi/2, pi/2].
 *	There are no error returns.
 *
 *	atan2(y, x) returns the arctangent of y/x,
 *	in the range [-pi, pi].
 *	atan2 discovers what quadrant the angle is in and calls atan.
 *	atan2 returns EDOM error and value 0 if both arguments are zero.
 *
 *	Coefficients are #5077 from Hart & Cheney (19.56D).
 */

#include <math.h>
#include <values.h>
#include <errno.h>

asm	double xatan(x,y)
{
%mem	x,y;
	fldl	x
	fldl	y
	fpatan
}

double
atan(x)
double x;
{
	return(atan2(x,1.0));
}

double
atan2(y, x)
double y, x;
{
	double ay, ax, z, zero;
	struct exception exc;

	exc.arg1 = y;
	if (!x && !y) {
		exc.type = DOMAIN;
		exc.name = "atan2";
		exc.arg2 = x;
		exc.retval = 0.0;
		if (!matherr(&exc)) {
			(void) write(2, "atan2: DOMAIN error\n", 20);
			errno = EDOM;
		}
		return (exc.retval);
	}

	zero = 0.0;
	if(y+x==y)
		if(y >= zero)
			return(M_PI_2);
		else
			return(-M_PI_2);
	ay = (y > zero ? y : -y);
	ax = (x > zero ? x : -x);
	if(ay < ax) {
		if (y == zero) {
			if (x > zero)
				return(zero);
			return(M_PI);
		}
		z = xatan(ay,ax);
	} else {
		if (x == zero) {
			if (y > zero)
				return(M_PI_2);
			return(-M_PI_2);
		}
		z = M_PI_2 - xatan(ax,ay);
	}
	if (x < zero)
		z = M_PI - z;
	if (y < zero)
		z = -z;
	return(z);
}
