xref: /aosp_15_r20/external/fdlibm/e_atan2.c (revision 1e651e1ef2b613db2c4b29ae59c1de74cf0222ae)
1*1e651e1eSRoland Levillain 
2*1e651e1eSRoland Levillain /* @(#)e_atan2.c 1.3 95/01/18 */
3*1e651e1eSRoland Levillain /*
4*1e651e1eSRoland Levillain  * ====================================================
5*1e651e1eSRoland Levillain  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
6*1e651e1eSRoland Levillain  *
7*1e651e1eSRoland Levillain  * Developed at SunSoft, a Sun Microsystems, Inc. business.
8*1e651e1eSRoland Levillain  * Permission to use, copy, modify, and distribute this
9*1e651e1eSRoland Levillain  * software is freely granted, provided that this notice
10*1e651e1eSRoland Levillain  * is preserved.
11*1e651e1eSRoland Levillain  * ====================================================
12*1e651e1eSRoland Levillain  *
13*1e651e1eSRoland Levillain  */
14*1e651e1eSRoland Levillain 
15*1e651e1eSRoland Levillain /* __ieee754_atan2(y,x)
16*1e651e1eSRoland Levillain  * Method :
17*1e651e1eSRoland Levillain  *	1. Reduce y to positive by ieee_atan2(y,x)=-ieee_atan2(-y,x).
18*1e651e1eSRoland Levillain  *	2. Reduce x to positive by (if x and y are unexceptional):
19*1e651e1eSRoland Levillain  *		ARG (x+iy) = arctan(y/x)   	   ... if x > 0,
20*1e651e1eSRoland Levillain  *		ARG (x+iy) = pi - arctan[y/(-x)]   ... if x < 0,
21*1e651e1eSRoland Levillain  *
22*1e651e1eSRoland Levillain  * Special cases:
23*1e651e1eSRoland Levillain  *
24*1e651e1eSRoland Levillain  *	ATAN2((anything), NaN ) is NaN;
25*1e651e1eSRoland Levillain  *	ATAN2(NAN , (anything) ) is NaN;
26*1e651e1eSRoland Levillain  *	ATAN2(+-0, +(anything but NaN)) is +-0  ;
27*1e651e1eSRoland Levillain  *	ATAN2(+-0, -(anything but NaN)) is +-pi ;
28*1e651e1eSRoland Levillain  *	ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2;
29*1e651e1eSRoland Levillain  *	ATAN2(+-(anything but INF and NaN), +INF) is +-0 ;
30*1e651e1eSRoland Levillain  *	ATAN2(+-(anything but INF and NaN), -INF) is +-pi;
31*1e651e1eSRoland Levillain  *	ATAN2(+-INF,+INF ) is +-pi/4 ;
32*1e651e1eSRoland Levillain  *	ATAN2(+-INF,-INF ) is +-3pi/4;
33*1e651e1eSRoland Levillain  *	ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2;
34*1e651e1eSRoland Levillain  *
35*1e651e1eSRoland Levillain  * Constants:
36*1e651e1eSRoland Levillain  * The hexadecimal values are the intended ones for the following
37*1e651e1eSRoland Levillain  * constants. The decimal values may be used, provided that the
38*1e651e1eSRoland Levillain  * compiler will convert from decimal to binary accurately enough
39*1e651e1eSRoland Levillain  * to produce the hexadecimal values shown.
40*1e651e1eSRoland Levillain  */
41*1e651e1eSRoland Levillain 
42*1e651e1eSRoland Levillain #include "fdlibm.h"
43*1e651e1eSRoland Levillain 
44*1e651e1eSRoland Levillain #ifdef __STDC__
45*1e651e1eSRoland Levillain static const double
46*1e651e1eSRoland Levillain #else
47*1e651e1eSRoland Levillain static double
48*1e651e1eSRoland Levillain #endif
49*1e651e1eSRoland Levillain tiny  = 1.0e-300,
50*1e651e1eSRoland Levillain zero  = 0.0,
51*1e651e1eSRoland Levillain pi_o_4  = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */
52*1e651e1eSRoland Levillain pi_o_2  = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */
53*1e651e1eSRoland Levillain pi      = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */
54*1e651e1eSRoland Levillain pi_lo   = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
55*1e651e1eSRoland Levillain 
56*1e651e1eSRoland Levillain #ifdef __STDC__
__ieee754_atan2(double y,double x)57*1e651e1eSRoland Levillain 	double __ieee754_atan2(double y, double x)
58*1e651e1eSRoland Levillain #else
59*1e651e1eSRoland Levillain 	double __ieee754_atan2(y,x)
60*1e651e1eSRoland Levillain 	double  y,x;
61*1e651e1eSRoland Levillain #endif
62*1e651e1eSRoland Levillain {
63*1e651e1eSRoland Levillain 	double z;
64*1e651e1eSRoland Levillain 	int k,m,hx,hy,ix,iy;
65*1e651e1eSRoland Levillain 	unsigned lx,ly;
66*1e651e1eSRoland Levillain 
67*1e651e1eSRoland Levillain 	hx = __HI(x); ix = hx&0x7fffffff;
68*1e651e1eSRoland Levillain 	lx = __LO(x);
69*1e651e1eSRoland Levillain 	hy = __HI(y); iy = hy&0x7fffffff;
70*1e651e1eSRoland Levillain 	ly = __LO(y);
71*1e651e1eSRoland Levillain 	if(((ix|((lx|-lx)>>31))>0x7ff00000)||
72*1e651e1eSRoland Levillain 	   ((iy|((ly|-ly)>>31))>0x7ff00000))	/* x or y is NaN */
73*1e651e1eSRoland Levillain 	   return x+y;
74*1e651e1eSRoland Levillain 	if((hx-0x3ff00000|lx)==0) return ieee_atan(y);   /* x=1.0 */
75*1e651e1eSRoland Levillain 	m = ((hy>>31)&1)|((hx>>30)&2);	/* 2*sign(x)+sign(y) */
76*1e651e1eSRoland Levillain 
77*1e651e1eSRoland Levillain     /* when y = 0 */
78*1e651e1eSRoland Levillain 	if((iy|ly)==0) {
79*1e651e1eSRoland Levillain 	    switch(m) {
80*1e651e1eSRoland Levillain 		case 0:
81*1e651e1eSRoland Levillain 		case 1: return y; 	/* ieee_atan(+-0,+anything)=+-0 */
82*1e651e1eSRoland Levillain 		case 2: return  pi+tiny;/* ieee_atan(+0,-anything) = pi */
83*1e651e1eSRoland Levillain 		case 3: return -pi-tiny;/* ieee_atan(-0,-anything) =-pi */
84*1e651e1eSRoland Levillain 	    }
85*1e651e1eSRoland Levillain 	}
86*1e651e1eSRoland Levillain     /* when x = 0 */
87*1e651e1eSRoland Levillain 	if((ix|lx)==0) return (hy<0)?  -pi_o_2-tiny: pi_o_2+tiny;
88*1e651e1eSRoland Levillain 
89*1e651e1eSRoland Levillain     /* when x is INF */
90*1e651e1eSRoland Levillain 	if(ix==0x7ff00000) {
91*1e651e1eSRoland Levillain 	    if(iy==0x7ff00000) {
92*1e651e1eSRoland Levillain 		switch(m) {
93*1e651e1eSRoland Levillain 		    case 0: return  pi_o_4+tiny;/* ieee_atan(+INF,+INF) */
94*1e651e1eSRoland Levillain 		    case 1: return -pi_o_4-tiny;/* ieee_atan(-INF,+INF) */
95*1e651e1eSRoland Levillain 		    case 2: return  3.0*pi_o_4+tiny;/*ieee_atan(+INF,-INF)*/
96*1e651e1eSRoland Levillain 		    case 3: return -3.0*pi_o_4-tiny;/*ieee_atan(-INF,-INF)*/
97*1e651e1eSRoland Levillain 		}
98*1e651e1eSRoland Levillain 	    } else {
99*1e651e1eSRoland Levillain 		switch(m) {
100*1e651e1eSRoland Levillain 		    case 0: return  zero  ;	/* ieee_atan(+...,+INF) */
101*1e651e1eSRoland Levillain 		    case 1: return -zero  ;	/* ieee_atan(-...,+INF) */
102*1e651e1eSRoland Levillain 		    case 2: return  pi+tiny  ;	/* ieee_atan(+...,-INF) */
103*1e651e1eSRoland Levillain 		    case 3: return -pi-tiny  ;	/* ieee_atan(-...,-INF) */
104*1e651e1eSRoland Levillain 		}
105*1e651e1eSRoland Levillain 	    }
106*1e651e1eSRoland Levillain 	}
107*1e651e1eSRoland Levillain     /* when y is INF */
108*1e651e1eSRoland Levillain 	if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
109*1e651e1eSRoland Levillain 
110*1e651e1eSRoland Levillain     /* compute y/x */
111*1e651e1eSRoland Levillain 	k = (iy-ix)>>20;
112*1e651e1eSRoland Levillain 	if(k > 60) z=pi_o_2+0.5*pi_lo; 	/* |y/x| >  2**60 */
113*1e651e1eSRoland Levillain 	else if(hx<0&&k<-60) z=0.0; 	/* |y|/x < -2**60 */
114*1e651e1eSRoland Levillain 	else z=ieee_atan(ieee_fabs(y/x));		/* safe to do y/x */
115*1e651e1eSRoland Levillain 	switch (m) {
116*1e651e1eSRoland Levillain 	    case 0: return       z  ;	/* ieee_atan(+,+) */
117*1e651e1eSRoland Levillain 	    case 1: __HI(z) ^= 0x80000000;
118*1e651e1eSRoland Levillain 		    return       z  ;	/* ieee_atan(-,+) */
119*1e651e1eSRoland Levillain 	    case 2: return  pi-(z-pi_lo);/* ieee_atan(+,-) */
120*1e651e1eSRoland Levillain 	    default: /* case 3 */
121*1e651e1eSRoland Levillain 	    	    return  (z-pi_lo)-pi;/* ieee_atan(-,-) */
122*1e651e1eSRoland Levillain 	}
123*1e651e1eSRoland Levillain }
124