]>
Commit | Line | Data |
---|---|---|
2aa62f2b | 1 | /* @(#)e_atan2.c 5.1 93/09/24 */\r |
2 | /*\r | |
3 | * ====================================================\r | |
4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.\r | |
5 | *\r | |
6 | * Developed at SunPro, a Sun Microsystems, Inc. business.\r | |
7 | * Permission to use, copy, modify, and distribute this\r | |
8 | * software is freely granted, provided that this notice\r | |
9 | * is preserved.\r | |
10 | * ====================================================\r | |
11 | */\r | |
12 | #include <LibConfig.h>\r | |
13 | #include <sys/EfiCdefs.h>\r | |
14 | #if defined(LIBM_SCCS) && !defined(lint)\r | |
15 | __RCSID("$NetBSD: e_atan2.c,v 1.12 2002/05/26 22:01:48 wiz Exp $");\r | |
16 | #endif\r | |
17 | \r | |
18 | #if defined(_MSC_VER) /* Handle Microsoft VC++ compiler specifics. */\r | |
19 | // unary minus operator applied to unsigned type, result still unsigned\r | |
20 | #pragma warning ( disable : 4146 )\r | |
21 | #endif\r | |
22 | \r | |
23 | /* __ieee754_atan2(y,x)\r | |
24 | * Method :\r | |
25 | * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).\r | |
26 | * 2. Reduce x to positive by (if x and y are unexceptional):\r | |
27 | * ARG (x+iy) = arctan(y/x) ... if x > 0,\r | |
28 | * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0,\r | |
29 | *\r | |
30 | * Special cases:\r | |
31 | *\r | |
32 | * ATAN2((anything), NaN ) is NaN;\r | |
33 | * ATAN2(NAN , (anything) ) is NaN;\r | |
34 | * ATAN2(+-0, +(anything but NaN)) is +-0 ;\r | |
35 | * ATAN2(+-0, -(anything but NaN)) is +-pi ;\r | |
36 | * ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2;\r | |
37 | * ATAN2(+-(anything but INF and NaN), +INF) is +-0 ;\r | |
38 | * ATAN2(+-(anything but INF and NaN), -INF) is +-pi;\r | |
39 | * ATAN2(+-INF,+INF ) is +-pi/4 ;\r | |
40 | * ATAN2(+-INF,-INF ) is +-3pi/4;\r | |
41 | * ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2;\r | |
42 | *\r | |
43 | * Constants:\r | |
44 | * The hexadecimal values are the intended ones for the following\r | |
45 | * constants. The decimal values may be used, provided that the\r | |
46 | * compiler will convert from decimal to binary accurately enough\r | |
47 | * to produce the hexadecimal values shown.\r | |
48 | */\r | |
49 | \r | |
50 | #include "math.h"\r | |
51 | #include "math_private.h"\r | |
52 | \r | |
53 | static const double\r | |
54 | tiny = 1.0e-300,\r | |
55 | zero = 0.0,\r | |
56 | pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */\r | |
57 | pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */\r | |
58 | pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */\r | |
59 | pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */\r | |
60 | \r | |
61 | double\r | |
62 | __ieee754_atan2(double y, double x)\r | |
63 | {\r | |
64 | double z;\r | |
65 | int32_t k,m,hx,hy,ix,iy;\r | |
66 | u_int32_t lx,ly;\r | |
67 | \r | |
68 | EXTRACT_WORDS(hx,lx,x);\r | |
69 | ix = hx&0x7fffffff;\r | |
70 | EXTRACT_WORDS(hy,ly,y);\r | |
71 | iy = hy&0x7fffffff;\r | |
72 | if(((ix|((lx|-lx)>>31))>0x7ff00000)||\r | |
73 | ((iy|((ly|-ly)>>31))>0x7ff00000)) /* x or y is NaN */\r | |
74 | return x+y;\r | |
75 | if(((hx-0x3ff00000)|lx)==0) return atan(y); /* x=1.0 */\r | |
76 | m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */\r | |
77 | \r | |
78 | /* when y = 0 */\r | |
79 | if((iy|ly)==0) {\r | |
80 | switch(m) {\r | |
81 | case 0:\r | |
82 | case 1: return y; /* atan(+-0,+anything)=+-0 */\r | |
83 | case 2: return pi+tiny;/* atan(+0,-anything) = pi */\r | |
84 | case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */\r | |
85 | }\r | |
86 | }\r | |
87 | /* when x = 0 */\r | |
88 | if((ix|lx)==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;\r | |
89 | \r | |
90 | /* when x is INF */\r | |
91 | if(ix==0x7ff00000) {\r | |
92 | if(iy==0x7ff00000) {\r | |
93 | switch(m) {\r | |
94 | case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */\r | |
95 | case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */\r | |
96 | case 2: return 3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/\r | |
97 | case 3: return -3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/\r | |
98 | }\r | |
99 | } else {\r | |
100 | switch(m) {\r | |
101 | case 0: return zero ; /* atan(+...,+INF) */\r | |
102 | case 1: return -zero ; /* atan(-...,+INF) */\r | |
103 | case 2: return pi+tiny ; /* atan(+...,-INF) */\r | |
104 | case 3: return -pi-tiny ; /* atan(-...,-INF) */\r | |
105 | }\r | |
106 | }\r | |
107 | }\r | |
108 | /* when y is INF */\r | |
109 | if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;\r | |
110 | \r | |
111 | /* compute y/x */\r | |
112 | k = (iy-ix)>>20;\r | |
113 | if(k > 60) z=pi_o_2+0.5*pi_lo; /* |y/x| > 2**60 */\r | |
114 | else if(hx<0&&k<-60) z=0.0; /* |y|/x < -2**60 */\r | |
115 | else z=atan(fabs(y/x)); /* safe to do y/x */\r | |
116 | switch (m) {\r | |
117 | case 0: return z ; /* atan(+,+) */\r | |
118 | case 1: {\r | |
119 | u_int32_t zh;\r | |
120 | GET_HIGH_WORD(zh,z);\r | |
121 | SET_HIGH_WORD(z,zh ^ 0x80000000);\r | |
122 | }\r | |
123 | return z ; /* atan(-,+) */\r | |
124 | case 2: return pi-(z-pi_lo);/* atan(+,-) */\r | |
125 | default: /* case 3 */\r | |
126 | return (z-pi_lo)-pi;/* atan(-,-) */\r | |
127 | }\r | |
128 | }\r |