Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/sdl/libm/e_atan2.c
9903 views
1
#include "SDL_internal.h"
2
/*
3
* ====================================================
4
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5
*
6
* Developed at SunPro, a Sun Microsystems, Inc. business.
7
* Permission to use, copy, modify, and distribute this
8
* software is freely granted, provided that this notice
9
* is preserved.
10
* ====================================================
11
*/
12
13
/* __ieee754_atan2(y,x)
14
* Method :
15
* 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).
16
* 2. Reduce x to positive by (if x and y are unexceptional):
17
* ARG (x+iy) = arctan(y/x) ... if x > 0,
18
* ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0,
19
*
20
* Special cases:
21
*
22
* ATAN2((anything), NaN ) is NaN;
23
* ATAN2(NAN , (anything) ) is NaN;
24
* ATAN2(+-0, +(anything but NaN)) is +-0 ;
25
* ATAN2(+-0, -(anything but NaN)) is +-pi ;
26
* ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2;
27
* ATAN2(+-(anything but INF and NaN), +INF) is +-0 ;
28
* ATAN2(+-(anything but INF and NaN), -INF) is +-pi;
29
* ATAN2(+-INF,+INF ) is +-pi/4 ;
30
* ATAN2(+-INF,-INF ) is +-3pi/4;
31
* ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2;
32
*
33
* Constants:
34
* The hexadecimal values are the intended ones for the following
35
* constants. The decimal values may be used, provided that the
36
* compiler will convert from decimal to binary accurately enough
37
* to produce the hexadecimal values shown.
38
*/
39
40
#include "math_libm.h"
41
#include "math_private.h"
42
43
static const double
44
tiny = 1.0e-300,
45
zero = 0.0,
46
pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */
47
pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */
48
pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */
49
pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
50
51
double attribute_hidden __ieee754_atan2(double y, double x)
52
{
53
double z;
54
int32_t k,m,hx,hy,ix,iy;
55
u_int32_t lx,ly;
56
57
EXTRACT_WORDS(hx,lx,x);
58
ix = hx&0x7fffffff;
59
EXTRACT_WORDS(hy,ly,y);
60
iy = hy&0x7fffffff;
61
if(((ix|((lx|-(int32_t)lx)>>31))>0x7ff00000)||
62
((iy|((ly|-(int32_t)ly)>>31))>0x7ff00000)) /* x or y is NaN */
63
return x+y;
64
if(((hx-0x3ff00000)|lx)==0) return atan(y); /* x=1.0 */
65
m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */
66
67
/* when y = 0 */
68
if((iy|ly)==0) {
69
switch(m) {
70
case 0:
71
case 1: return y; /* atan(+-0,+anything)=+-0 */
72
case 2: return pi+tiny;/* atan(+0,-anything) = pi */
73
case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */
74
}
75
}
76
/* when x = 0 */
77
if((ix|lx)==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
78
79
/* when x is INF */
80
if(ix==0x7ff00000) {
81
if(iy==0x7ff00000) {
82
switch(m) {
83
case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */
84
case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */
85
case 2: return 3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/
86
case 3: return -3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/
87
}
88
} else {
89
switch(m) {
90
case 0: return zero ; /* atan(+...,+INF) */
91
case 1: return -zero ; /* atan(-...,+INF) */
92
case 2: return pi+tiny ; /* atan(+...,-INF) */
93
case 3: return -pi-tiny ; /* atan(-...,-INF) */
94
}
95
}
96
}
97
/* when y is INF */
98
if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
99
100
/* compute y/x */
101
k = (iy-ix)>>20;
102
if(k > 60) z=pi_o_2+0.5*pi_lo; /* |y/x| > 2**60 */
103
else if(hx<0&&k<-60) z=0.0; /* |y|/x < -2**60 */
104
else z=atan(fabs(y/x)); /* safe to do y/x */
105
switch (m) {
106
case 0: return z ; /* atan(+,+) */
107
case 1: {
108
u_int32_t zh;
109
GET_HIGH_WORD(zh,z);
110
SET_HIGH_WORD(z,zh ^ 0x80000000);
111
}
112
return z ; /* atan(-,+) */
113
case 2: return pi-(z-pi_lo);/* atan(+,-) */
114
default: /* case 3 */
115
return (z-pi_lo)-pi;/* atan(-,-) */
116
}
117
}
118
119
/*
120
* wrapper atan2(y,x)
121
*/
122
#ifndef _IEEE_LIBM
123
double atan2(double y, double x)
124
{
125
double z = __ieee754_atan2(y, x);
126
if (_LIB_VERSION == _IEEE_ || isnan(x) || isnan(y))
127
return z;
128
if (x == 0.0 && y == 0.0)
129
return __kernel_standard(y,x,3); /* atan2(+-0,+-0) */
130
return z;
131
}
132
#else
133
strong_alias(__ieee754_atan2, atan2)
134
#endif
135
libm_hidden_def(atan2)
136
137