1 | /* e_atan2f.c -- float version of e_atan2.c. |
2 | */ |
3 | |
4 | /* |
5 | * ==================================================== |
6 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. |
7 | * |
8 | * Developed at SunPro, a Sun Microsystems, Inc. business. |
9 | * Permission to use, copy, modify, and distribute this |
10 | * software is freely granted, provided that this notice |
11 | * is preserved. |
12 | * ==================================================== |
13 | */ |
14 | |
15 | #include <math.h> |
16 | #include <math_private.h> |
17 | #include <libm-alias-finite.h> |
18 | |
19 | static const float |
20 | tiny = 1.0e-30, |
21 | zero = 0.0, |
22 | pi_o_4 = 7.8539818525e-01, /* 0x3f490fdb */ |
23 | pi_o_2 = 1.5707963705e+00, /* 0x3fc90fdb */ |
24 | pi = 3.1415927410e+00, /* 0x40490fdb */ |
25 | pi_lo = -8.7422776573e-08; /* 0xb3bbbd2e */ |
26 | |
27 | float |
28 | __ieee754_atan2f (float y, float x) |
29 | { |
30 | float z; |
31 | int32_t k,m,hx,hy,ix,iy; |
32 | |
33 | GET_FLOAT_WORD(hx,x); |
34 | ix = hx&0x7fffffff; |
35 | GET_FLOAT_WORD(hy,y); |
36 | iy = hy&0x7fffffff; |
37 | if((ix>0x7f800000)|| |
38 | (iy>0x7f800000)) /* x or y is NaN */ |
39 | return x+y; |
40 | if(hx==0x3f800000) return __atanf(y); /* x=1.0 */ |
41 | m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */ |
42 | |
43 | /* when y = 0 */ |
44 | if(iy==0) { |
45 | switch(m) { |
46 | case 0: |
47 | case 1: return y; /* atan(+-0,+anything)=+-0 */ |
48 | case 2: return pi+tiny;/* atan(+0,-anything) = pi */ |
49 | case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */ |
50 | } |
51 | } |
52 | /* when x = 0 */ |
53 | if(ix==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; |
54 | |
55 | /* when x is INF */ |
56 | if(ix==0x7f800000) { |
57 | if(iy==0x7f800000) { |
58 | switch(m) { |
59 | case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */ |
60 | case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */ |
61 | case 2: return (float)3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/ |
62 | case 3: return (float)-3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/ |
63 | } |
64 | } else { |
65 | switch(m) { |
66 | case 0: return zero ; /* atan(+...,+INF) */ |
67 | case 1: return -zero ; /* atan(-...,+INF) */ |
68 | case 2: return pi+tiny ; /* atan(+...,-INF) */ |
69 | case 3: return -pi-tiny ; /* atan(-...,-INF) */ |
70 | } |
71 | } |
72 | } |
73 | /* when y is INF */ |
74 | if(iy==0x7f800000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; |
75 | |
76 | /* compute y/x */ |
77 | k = (iy-ix)>>23; |
78 | if(k > 60) z=pi_o_2+(float)0.5*pi_lo; /* |y/x| > 2**60 */ |
79 | else if(hx<0&&k<-60) z=0.0; /* |y|/x < -2**60 */ |
80 | else z=__atanf(fabsf(y/x)); /* safe to do y/x */ |
81 | switch (m) { |
82 | case 0: return z ; /* atan(+,+) */ |
83 | case 1: { |
84 | uint32_t zh; |
85 | GET_FLOAT_WORD(zh,z); |
86 | SET_FLOAT_WORD(z,zh ^ 0x80000000); |
87 | } |
88 | return z ; /* atan(-,+) */ |
89 | case 2: return pi-(z-pi_lo);/* atan(+,-) */ |
90 | default: /* case 3 */ |
91 | return (z-pi_lo)-pi;/* atan(-,-) */ |
92 | } |
93 | } |
94 | libm_alias_finite (__ieee754_atan2f, __atan2f) |
95 | |