CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
approx_atan2.h
Go to the documentation of this file.
1 #ifndef APPROX_ATAN2_H
2 #define APPROX_ATAN2_H
3 
4 
5 /*
6  * approximate atan2 evaluations
7  *
8  * Polynomials were obtained using Sollya scripts (in comments below)
9  *
10  *
11 */
12 
13 /*
14 f= atan((1-x)/(1+x))-atan(1);
15 I=[-1+10^(-4);1.0];
16 filename="atan.txt";
17 print("") > filename;
18 for deg from 3 to 11 do begin
19  p = fpminimax(f, deg,[|1,23...|],I, floating, absolute);
20  display=decimal;
21  acc=floor(-log2(sup(supnorm(p, f, I, absolute, 2^(-20)))));
22  print( " // degree = ", deg,
23  " => absolute accuracy is ", acc, "bits" ) >> filename;
24  print("template<> inline float approx_atan2f_P<", deg, ">(float x){") >> filename;
25  display=hexadecimal;
26  print(" return ", horner(p) , ";") >> filename;
27  print("}") >> filename;
28 end;
29 */
30 
31 
32 
33 
34 #include <cstdint>
35 #include <cmath>
36 #include <limits>
37 #include <algorithm>
38 
39 
40 // float
41 
42 template<int DEGREE>
43 inline float approx_atan2f_P(float x);
44 
45 // degree = 3 => absolute accuracy is 7 bits
46 template<> inline float approx_atan2f_P< 3 >(float x){
47  return x * (float(-0xf.8eed2p-4) + x*x * float(0x3.1238p-4)) ;
48 }
49 
50 // degree = 5 => absolute accuracy is 10 bits
51 template<> inline float approx_atan2f_P< 5 >(float x){
52  auto z = x*x;
53  return x * (float(-0xf.ecfc8p-4) + z * (float(0x4.9e79dp-4) + z * float(-0x1.44f924p-4) ) );
54 }
55 
56 // degree = 7 => absolute accuracy is 13 bits
57 template<> inline float approx_atan2f_P< 7 >(float x){
58  auto z = x*x;
59  return x * (float(-0xf.fcc7ap-4) + z * (float(0x5.23886p-4) + z * (float(-0x2.571968p-4) + z * float(0x9.fb05p-8) ) ) ) ;
60 }
61 
62 // degree = 9 => absolute accuracy is 16 bits
63 template<> inline float approx_atan2f_P< 9 >(float x){
64  auto z = x*x;
65  return x * (float(-0xf.ff73ep-4) + z * (float(0x5.48ee1p-4) + z * (float(-0x2.e1efe8p-4) + z * (float(0x1.5cce54p-4) + z * float(-0x5.56245p-8) ) ) ) );
66 }
67 
68 // degree = 11 => absolute accuracy is 19 bits
69 template<> inline float approx_atan2f_P< 11 >(float x){
70  auto z = x*x;
71  return x * (float(-0xf.ffe82p-4) + z * (float(0x5.526c8p-4) + z * (float(-0x3.18bea8p-4) + z * (float(0x1.dce3bcp-4) + z * (float(-0xd.7a64ap-8) + z * float(0x3.000eap-8))))));
72 }
73 
74 // degree = 13 => absolute accuracy is 21 bits
75 template<> inline float approx_atan2f_P< 13 >(float x){
76  auto z = x*x;
77  return x * (float(-0xf.fffbep-4) + z * (float(0x5.54adp-4) + z * (float(-0x3.2b4df8p-4) + z * (float(0x2.1df79p-4) + z * (float(-0x1.46081p-4) + z * (float(0x8.99028p-8) + z * float(-0x1.be0bc4p-8))))))) ;
78 }
79 
80 // degree = 15 => absolute accuracy is 24 bits
81 template<> inline float approx_atan2f_P< 15 >(float x){
82  auto z = x*x;
83  return x * (float(-0xf.ffff4p-4) + z * (float(0x5.552f9p-4 + z * (float(-0x3.30f728p-4) + z * (float(0x2.39826p-4) + z * (float(-0x1.8a880cp-4) + z * (float(0xe.484d6p-8) + z * (float(-0x5.93d5p-8) + z * float(0x1.0875dcp-8)))))))));
84 }
85 
86 
87 template<int DEGREE>
88 inline float unsafe_atan2f_impl(float y, float x) {
89 
90  constexpr float pi4f = 3.1415926535897932384626434/4;
91  constexpr float pi34f = 3.1415926535897932384626434*3/4;
92 
93  auto r= (std::abs(x) - std::abs(y))/(std::abs(x) + std::abs(y));
94  if (x<0) r = -r;
95 
96  auto angle = (x>=0) ? pi4f : pi34f;
97  angle += approx_atan2f_P<DEGREE>(r);
98 
99 
100  return ( (y < 0)) ? - angle : angle ;
101 
102 
103 }
104 
105 template<int DEGREE>
106 inline float unsafe_atan2f(float y, float x) {
107  return unsafe_atan2f_impl<DEGREE>(y,x);
108 
109 }
110 
111 template<int DEGREE>
112 inline float safe_atan2f(float y, float x) {
113  return unsafe_atan2f_impl<DEGREE>( y, (y==0.f)&(x==0.f) ? 0.2f : x);
114  // return (y==0.f)&(x==0.f) ? 0.f : unsafe_atan2f_impl<DEGREE>( y, x);
115 
116 }
117 
118 
119 // integer...
120 /*
121  f= (2^31/pi)*(atan((1-x)/(1+x))-atan(1));
122  I=[-1+10^(-4);1.0];
123  p = fpminimax(f, [|1,3,5,7,9,11|],[|23...|],I, floating, absolute);
124  */
125 
126 
127 template<int DEGREE>
128 inline float approx_atan2i_P(float x);
129 
130 // degree = 3 => absolute accuracy is 6*10^6
131 template<> inline float approx_atan2i_P< 3 >(float x){
132  auto z = x*x;
133  return x * (-664694912.f + z * 131209024.f);
134 }
135 
136 // degree = 5 => absolute accuracy is 4*10^5
137 template<> inline float approx_atan2i_P< 5 >(float x){
138  auto z = x*x;
139  return x * (-680392064.f + z * (197338400.f + z * (-54233256.f)));
140 }
141 
142 // degree = 7 => absolute accuracy is 6*10^4
143 template<> inline float approx_atan2i_P< 7 >(float x){
144  auto z = x*x;
145  return x * (-683027840.f + z * (219543904.f + z * (-99981040.f + z * 26649684.f)));
146 }
147 
148 // degree = 9 => absolute accuracy is 8000
149 template<> inline float approx_atan2i_P< 9 >(float x){
150  auto z = x*x;
151  return x * (-683473920.f + z * (225785056.f + z * (-123151184.f + z * (58210592.f + z * (-14249276.f)))));
152 }
153 
154 // degree = 11 => absolute accuracy is 1000
155 template<> inline float approx_atan2i_P< 11 >(float x){
156  auto z = x*x;
157  return x * (-683549696.f + z * (227369312.f + z * (-132297008.f + z * (79584144.f + z * (-35987016.f + z * 8010488.f)))));
158 }
159 
160 // degree = 13 => absolute accuracy is 163
161 template<> inline float approx_atan2i_P< 13 >(float x){
162  auto z = x*x;
163  return x * (-683562624.f + z * (227746080.f + z * (-135400128.f + z * (90460848.f + z * (-54431464.f + z * (22973256.f + z * (-4657049.f)))))));
164 }
165 
166 template<> inline float approx_atan2i_P< 15 >(float x){
167  auto z = x*x;
168  return x * (-683562624.f + z * (227746080.f + z * (-135400128.f + z * (90460848.f + z * (-54431464.f + z * (22973256.f + z * (-4657049.f)))))));
169 }
170 
171 
172 template<int DEGREE>
173 inline int unsafe_atan2i_impl(float y, float x) {
174 
175 
176  constexpr long long maxint = (long long)(std::numeric_limits<int>::max())+1LL;
177  constexpr int pi4 = int(maxint/4LL);
178  constexpr int pi34 = int(3LL*maxint/4LL);
179 
180  auto r= (std::abs(x) - std::abs(y))/(std::abs(x) + std::abs(y));
181  if (x<0) r = -r;
182 
183  auto angle = (x>=0) ? pi4 : pi34;
184  angle += int(approx_atan2i_P<DEGREE>(r));
185  // angle += int(std::round(approx_atan2i_P<DEGREE>(r)));
186 
187 
188  return (y < 0) ? - angle : angle ;
189 
190 
191 }
192 
193 template<int DEGREE>
194 inline int unsafe_atan2i(float y, float x) {
195  return unsafe_atan2i_impl<DEGREE>(y,x);
196 
197 }
198 
199 inline
200 int phi2int(float x) {
201  constexpr float p2i = ( (long long)(std::numeric_limits<int>::max())+1LL )/M_PI;
202  return std::round(x*p2i);
203 }
204 
205 inline
206 float int2phi(int x) {
207  constexpr float i2p = M_PI/( (long long)(std::numeric_limits<int>::max())+1LL );
208  return float(x)*i2p;
209 }
210 
211 inline
212 double int2dphi(int x) {
213  constexpr double i2p = M_PI/( (long long)(std::numeric_limits<int>::max())+1LL );
214  return x*i2p;
215 }
216 
217 
218 inline
219 short phi2short(float x) {
220  constexpr float p2i = ( (int)(std::numeric_limits<short>::max())+1 )/M_PI;
221  return std::round(x*p2i);
222 }
223 
224 inline
225 float short2phi(short x) {
226  constexpr float i2p = M_PI/( (int)(std::numeric_limits<short>::max())+1 );
227  return float(x)*i2p;
228 }
229 
230 
231 #endif
232 
233 
float approx_atan2i_P< 15 >(float x)
Definition: approx_atan2.h:166
float approx_atan2i_P< 11 >(float x)
Definition: approx_atan2.h:155
float approx_atan2i_P< 3 >(float x)
Definition: approx_atan2.h:131
float unsafe_atan2f(float y, float x)
Definition: approx_atan2.h:106
float approx_atan2f_P(float x)
float approx_atan2i_P< 5 >(float x)
Definition: approx_atan2.h:137
float float float z
int phi2int(float x)
Definition: approx_atan2.h:200
double int2dphi(int x)
Definition: approx_atan2.h:212
int unsafe_atan2i(float y, float x)
Definition: approx_atan2.h:194
float approx_atan2f_P< 9 >(float x)
Definition: approx_atan2.h:63
const T & max(const T &a, const T &b)
float approx_atan2f_P< 7 >(float x)
Definition: approx_atan2.h:57
float int2phi(int x)
Definition: approx_atan2.h:206
float approx_atan2i_P< 7 >(float x)
Definition: approx_atan2.h:143
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double f[11][100]
float approx_atan2f_P< 15 >(float x)
Definition: approx_atan2.h:81
float approx_atan2f_P< 11 >(float x)
Definition: approx_atan2.h:69
short phi2short(float x)
Definition: approx_atan2.h:219
#define M_PI
float approx_atan2i_P< 9 >(float x)
Definition: approx_atan2.h:149
float approx_atan2i_P< 13 >(float x)
Definition: approx_atan2.h:161
float unsafe_atan2f_impl(float y, float x)
Definition: approx_atan2.h:88
float approx_atan2f_P< 5 >(float x)
Definition: approx_atan2.h:51
int unsafe_atan2i_impl(float y, float x)
Definition: approx_atan2.h:173
float approx_atan2i_P(float x)
float short2phi(short x)
Definition: approx_atan2.h:225
float approx_atan2f_P< 13 >(float x)
Definition: approx_atan2.h:75
Definition: DDAxes.h:10
float approx_atan2f_P< 3 >(float x)
Definition: approx_atan2.h:46
float safe_atan2f(float y, float x)
Definition: approx_atan2.h:112
#define constexpr
T angle(T x1, T y1, T z1, T x2, T y2, T z2)
Definition: angle.h:11