xref: /csrg-svn/lib/libm/mc68881/atan2.c (revision 61285)
142212Sbostic /*-
2*61285Sbostic  * Copyright (c) 1990, 1993
3*61285Sbostic  *	The Regents of the University of California.  All rights reserved.
442212Sbostic  *
542212Sbostic  * This code is derived from software contributed to Berkeley by
642212Sbostic  * the Systems Programming Group of the University of Utah Computer
742212Sbostic  * Science Department.
842212Sbostic  *
942212Sbostic  * %sccs.include.redist.c%
1042212Sbostic  */
1142212Sbostic 
1242212Sbostic #ifndef lint
13*61285Sbostic static char sccsid[] = "@(#)atan2.c	8.1 (Berkeley) 06/04/93";
1442212Sbostic #endif /* not lint */
1542212Sbostic 
1642212Sbostic /*
1742212Sbostic  * ATAN2(Y,X)
1842212Sbostic  * RETURN ARG (X+iY)
1942212Sbostic  * DOUBLE PRECISION (IEEE DOUBLE 53 BITS)
2042212Sbostic  *
2142212Sbostic  * Scaled down version to weed out special cases.  "Normal" cases are
2242212Sbostic  * handled by calling atan2__A(), an assembly coded support routine in
2342212Sbostic  * support.s.
2442212Sbostic  *
2542212Sbostic  * Required system supported functions :
2642212Sbostic  *	copysign(x,y)
2742212Sbostic  *	atan2__A(y,x)
2842212Sbostic  *
2942212Sbostic  * Method :
3042212Sbostic  *	1. Deal with special cases
3142212Sbostic  *	2. Call atan2__A() to do the others
3242212Sbostic  *
3342212Sbostic  * Special cases:
3442212Sbostic  * Notations: atan2(y,x) == ARG (x+iy) == ARG(x,y).
3542212Sbostic  *
3642212Sbostic  *	ARG( NAN , (anything) ) is NaN;
3742212Sbostic  *	ARG( (anything), NaN ) is NaN;
3842212Sbostic  *	ARG(+(anything but NaN), +-0) is +-0  ;
3942212Sbostic  *	ARG(-(anything but NaN), +-0) is +-PI ;
4042212Sbostic  *	ARG( 0, +-(anything but 0 and NaN) ) is +-PI/2;
4142212Sbostic  *	ARG( +INF,+-(anything but INF and NaN) ) is +-0 ;
4242212Sbostic  *	ARG( -INF,+-(anything but INF and NaN) ) is +-PI;
4342212Sbostic  *	ARG( +INF,+-INF ) is +-PI/4 ;
4442212Sbostic  *	ARG( -INF,+-INF ) is +-3PI/4;
4542212Sbostic  *	ARG( (anything but,0,NaN, and INF),+-INF ) is +-PI/2;
4642212Sbostic  *
4742212Sbostic  * Accuracy:
4842212Sbostic  *	atan2(y,x) returns (PI/pi) * the exact ARG (x+iy) nearly rounded,
4942212Sbostic  *	where
5042212Sbostic  *
5142212Sbostic  *	in decimal:
5242212Sbostic  *		pi = 3.141592653589793 23846264338327 .....
5342212Sbostic  *    53 bits   PI = 3.141592653589793 115997963 ..... ,
5442212Sbostic  *    56 bits   PI = 3.141592653589793 227020265 ..... ,
5542212Sbostic  *
5642212Sbostic  *	in hexadecimal:
5742212Sbostic  *		pi = 3.243F6A8885A308D313198A2E....
5842212Sbostic  *    53 bits   PI = 3.243F6A8885A30  =  2 * 1.921FB54442D18	error=.276ulps
5942212Sbostic  *    56 bits   PI = 3.243F6A8885A308 =  4 * .C90FDAA22168C2    error=.206ulps
6042212Sbostic  *
6142212Sbostic  *	In a test run with 356,000 random argument on [-1,1] * [-1,1] on a
6242212Sbostic  *	VAX, the maximum observed error was 1.41 ulps (units of the last place)
6342212Sbostic  *	compared with (PI/pi)*(the exact ARG(x+iy)).
6442212Sbostic  *
6542212Sbostic  * Note:
6642212Sbostic  *	We use machine PI (the true pi rounded) in place of the actual
6742212Sbostic  *	value of pi for all the trig and inverse trig functions. In general,
6842212Sbostic  *	if trig is one of sin, cos, tan, then computed trig(y) returns the
6942212Sbostic  *	exact trig(y*pi/PI) nearly rounded; correspondingly, computed arctrig
7042212Sbostic  *	returns the exact arctrig(y)*PI/pi nearly rounded. These guarantee the
7142212Sbostic  *	trig functions have period PI, and trig(arctrig(x)) returns x for
7242212Sbostic  *	all critical values x.
7342212Sbostic  *
7442212Sbostic  * Constants:
7542212Sbostic  * The hexadecimal values are the intended ones for the following constants.
7642212Sbostic  * The decimal values may be used, provided that the compiler will convert
7742212Sbostic  * from decimal to binary accurately enough to produce the hexadecimal values
7842212Sbostic  * shown.
7942212Sbostic  */
8042212Sbostic 
8142212Sbostic static double
8242212Sbostic PIo4   =  7.8539816339744827900E-1    , /*Hex  2^ -1   *  1.921FB54442D18 */
8342212Sbostic PIo2   =  1.5707963267948965580E0     , /*Hex  2^  0   *  1.921FB54442D18 */
8442212Sbostic PI     =  3.1415926535897931160E0     ; /*Hex  2^  1   *  1.921FB54442D18 */
8542212Sbostic 
atan2(y,x)8642212Sbostic double atan2(y,x)
8742212Sbostic double  y,x;
8842212Sbostic {
8942212Sbostic 	static double zero=0, one=1;
9042212Sbostic 	double copysign(),atan2__A(),signy,signx;
9142212Sbostic 	int finite();
9242212Sbostic 
9342212Sbostic     /* if x or y is NAN */
9442212Sbostic 	if(x!=x) return(x); if(y!=y) return(y);
9542212Sbostic 
9642212Sbostic     /* copy down the sign of y and x */
9742212Sbostic 	signy = copysign(one,y);
9842212Sbostic 	signx = copysign(one,x);
9942212Sbostic 
10042212Sbostic     /* when y = 0 */
10142212Sbostic 	if(y==zero) return((signx==one)?y:copysign(PI,signy));
10242212Sbostic 
10342212Sbostic     /* when x = 0 */
10442212Sbostic 	if(x==zero) return(copysign(PIo2,signy));
10542212Sbostic 
10642212Sbostic     /* when x is INF */
10742212Sbostic 	if(!finite(x))
10842212Sbostic 	    if(!finite(y))
10942212Sbostic 		return(copysign((signx==one)?PIo4:3*PIo4,signy));
11042212Sbostic 	    else
11142212Sbostic 		return(copysign((signx==one)?zero:PI,signy));
11242212Sbostic 
11342212Sbostic     /* when y is INF */
11442212Sbostic 	if(!finite(y)) return(copysign(PIo2,signy));
11542212Sbostic 
11642212Sbostic     /* else let atan2__A do the work */
11742212Sbostic 	return(atan2__A(y,x));
11842212Sbostic }
119