Math.h
1 /*
2  * Copyright (C) 2006-2017 Marc Duerner
3  * Copyright (C) 2010-2017 Aloysius Indrayanto
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * As a special exception, you may use this file as part of a free
11  * software library without restriction. Specifically, if other files
12  * instantiate templates or use macros or inline functions from this
13  * file, or you compile this file and link it with other files to
14  * produce an executable, this file does not by itself cause the
15  * resulting executable to be covered by the GNU General Public
16  * License. This exception does not however invalidate any other
17  * reasons why the executable file might be covered by the GNU Library
18  * General Public License.
19  *
20  * This library is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23  * Lesser General Public License for more details.
24  *
25  * You should have received a copy of the GNU Lesser General Public
26  * License along with this library; if not, write to the Free Software
27  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28  */
29 
30 #ifndef PT_MATH_H
31 #define PT_MATH_H
32 
33 #include <Pt/Types.h>
34 #include <Pt/Api.h>
35 #include <iostream>
36 #include <cmath>
37 #include <cassert>
38 #include <math.h> // hypot
39 
40 //#include <x86intrin.h>
41 //#include <intrin.h>
42 
43 namespace Pt {
44 
47 template<typename T>
48 T pi();
49 
52 template<typename T>
53 T piDouble();
54 
57 template<typename T>
58 T piHalf();
59 
62 template<typename T>
63 T piQuart();
64 
67 template<typename T>
68 T piSquare();
69 
70 
71 template<>
72 inline float pi<float>()
73 {
74  return 3.14159265f;
75 }
76 
77 template<>
78 inline float piDouble<float>()
79 {
80  return 6.28318531f;
81 }
82 
83 template<>
84 inline float piHalf<float>()
85 {
86  return 1.57079633f;
87 }
88 
89 template<>
90 inline float piQuart<float>()
91 {
92  return 0.78539816f;
93 }
94 
95 template<>
96 inline float piSquare<float>()
97 {
98  return 9.86960440f;
99 }
100 
101 
102 template<>
103 inline double pi<double>()
104 {
105  return 3.14159265358979323846;
106 }
107 
108 template<>
109 inline double piDouble<double>()
110 {
111  return 6.28318530717958647692;
112 }
113 
114 template<>
115 inline double piHalf<double>()
116 {
117  return 1.57079632679489661923;
118 }
119 
120 template<>
121 inline double piQuart<double>()
122 {
123  return 0.78539816339744830961;
124 }
125 
126 template<>
127 inline double piSquare<double>()
128 {
129  return 9.86960440108935861883449099987615114;
130 }
131 
132 
133 static const float DegToRadF = 0.01745329f;
134 
135 static const float RadToDegF = 57.2957795f;
136 
137 static const double DegToRad = 0.0174532925199432957692;
138 
139 static const double RadToDeg = 57.295779513082320876846364344191;
140 
141 
142 inline float degToRad(float deg)
143 {
144  return deg * DegToRadF;
145 }
146 
147 inline double degToRad(double deg)
148 {
149  return deg * DegToRad;
150 }
151 
152 
153 inline float radToDeg(float rad)
154 {
155  return rad * RadToDegF;
156 }
157 
158 inline double radToDeg(double rad)
159 {
160  return rad * RadToDeg;
161 }
162 
163 
169 template <typename T>
170 T fastSin(const T& theta)
171 {
172  //return sin(theta);
173 
174  assert(theta <= piDouble<T>());
175  assert(theta >= 0);
176 
177  T localTheta = theta;
178 
179  if(localTheta > pi<T>())
180  {
181  localTheta -= piDouble<T>();
182  }
183 
184  const T B = 4 / pi<T>();
185  const T C = -4 / piSquare<T>();
186  //const float Q = 0.775;
187  const T P = static_cast<T>(0.225);
188 
189  T y = B * localTheta + C * localTheta * ::fabs(localTheta);
190  y = P * (y * std::fabs(y) - y) + y; // Q * y + P * y * abs(y)
191  return y;
192 }
193 
199 template <typename T>
200 T fastCos(const T& theta)
201 {
202  //return cos(theta);
203 
204  assert(theta <= piDouble<T>());
205  assert(theta >= 0);
206 
207  T sinTheta = theta + piHalf<T>();
208 
209  if(sinTheta > piDouble<T>()) // Original x > pi/2
210  {
211  sinTheta -= piDouble<T>(); // Wrap: cos(x) = cos(x - 2 pi)
212  }
213 
214  return fastSin(sinTheta);
215 }
216 
219 template <typename T>
220 T fastAtan2(T y, T x)
221 {
222  if(x == 0.0)
223  {
224  if(y > 0) return piHalf<T>();
225  if(y == 0) return 0;
226  return -piHalf<T>();
227  }
228 
229  const T z = y / x;
230  T atan = 0.0;
231 
232  if(std::fabs(z) < 1.0)
233  {
234  atan = z / (static_cast<T>(1.0) + static_cast<T>(0.28) * z * z);
235 
236  if(x < 0.0)
237  {
238  return y < 0 ? atan - pi<T>()
239  : atan + pi<T>();
240  }
241  }
242  else
243  {
244  atan = piHalf<T>() - z / (z * z + static_cast<T>(0.28));
245  if(y < 0.0)
246  return atan - pi<T>();
247  }
248 
249  return atan;
250 }
251 
252 inline float toPolar(float x, float y)
253 {
254  // Quadrant I and II
255  if(y >= 0)
256  return radToDeg( fastAtan2(y, x) );
257 
258  // Quadrant III and IV
259  return radToDeg( fastAtan2(y, x) ) + 360.0f;
260 }
261 
262 template <typename T>
263 T invSqrt(T x)
264 {
265  return static_cast<T>(1.0) / std::sqrt(x);
266 }
267 
268 inline float invSqrtf(float x)
269 {
270  return 1.0f / std::sqrt(x);
271 }
272 
275 inline double hypot(double x, double y)
276 {
277 #if __cplusplus == 201103L
278  return std::hypot(x, y);
279 #elif defined(_MSC_VER) || defined(_WIN32_WCE) || defined(_WIN32)
280  return _hypot(x, y);
281 #else
282  return ::hypot(x, y);
283 #endif
284 }
285 
286 
289 inline Pt::int32_t lround(float x)
290 {
291 #if __cplusplus >= 201103L
292 
293  return std::lround(x);
294 
295 #elif (_MSC_VER < 1800)
296 
297  Pt::int32_t tmp = static_cast<Pt::int32_t>(x);
298  tmp += (x - tmp >= 0.5) - (x - tmp <= -0.5);
299  return tmp;
300 
301 #else
302 
303  return ::lround(x);
304 
305 #endif
306 
307 //
308 // asm below uses bankers rounding
309 //
310 //#elif defined(_MSC_VER) && defined (_M_IX86)
311 //
312 // Pt::int32_t tmp;
313 // __asm fld x
314 // __asm fistp tmp
315 // return tmp;
316 //
317 //#elif ( defined(__GNUC__) || defined(__clang__) ) &&
318 // ( defined(__i386) || defined(__x86_64__) )
319 //
320 // Pt::int32_t tmp;
321 // __asm__ __volatile__ (
322 // "flds %1\n\t"
323 // "fistpl %0 "
324 // : "=m"(tmp)
325 // : "m"(x)
326 // : "memory"
327 // );
328 // return tmp;
329 //
330 //
331 //#elif ( defined(__GNUC__) || defined(__clang__) ) &&
332 // defined(__arm__)
333 //
334 // float tmp;
335 // Pt::int32_t res;
336 // __asm__ __volatile__ ( "ftosis %0, %1" : "=w" (tmp) : "w" (x) );
337 // __asm__ __volatile__ ( "fmrs %0, %1" : "=r" (res) : "w" (tmp) );
338 // return res;
339 
340 }
341 
344 inline Pt::int32_t lround(double x)
345 {
346 #if __cplusplus >= 201103L
347 
348  return std::lround(x);
349 
350 #elif (_MSC_VER < 1800)
351 
352  Pt::int32_t tmp = static_cast<Pt::int32_t>(x);
353  tmp += (x - tmp >= 0.5) - (x - tmp <= -0.5);
354  return tmp;
355 
356 #else
357 
358  return ::lround(x);
359 
360 #endif
361 
362 //
363 // asm below uses bankers rounding
364 //
365 //#elif defined(_MSC_VER) || defined (_M_IX86)
366 //
367 // Pt::int32_t tmp;
368 // __asm fld x
369 // __asm fistp tmp
370 // return tmp;
371 //
372 //#elif ( defined(__GNUC__) || defined(__clang__) ) &&
373 // ( defined(__i386) || defined(__x86_64__) )
374 //
375 // Pt::int32_t tmp;
376 // __asm__ __volatile__ (
377 // "fldl %1\n\t"
378 // "fistpl %0 "
379 // : "=m"(tmp)
380 // : "m"(x)
381 // : "memory"
382 // );
383 // return tmp;
384 //
385 //#elif ( defined(__GNUC__) || defined(__clang__) ) &&
386 // defined(__arm__)
387 //
388 // float tmp;
389 // Pt::int32_t res;
390 // __asm__ __volatile__ ( "ftosid %0, %P1" : "=w" (tmp) : "w" (x) );
391 // __asm__ __volatile__ ( "fmrs %0, %1" : "=r" (res) : "w" (tmp) );
392 // return res;
393 }
394 
395 } // namespace Pt
396 
397 #endif // PT_MATH_H
double hypot(double x, double y)
Return the euclidean distance of the given values.
Definition: Math.h:275
T fastSin(const T &theta)
Fast, but less precise sine calculation.
Definition: Math.h:170
T piHalf()
The constant pi/2.
int_type int32_t
Signed 32-bit integer type.
Definition: Types.h:36
T piDouble()
The constant pi*2.
Pt::int32_t lround(float x)
Rounds to nearest integer value.
Definition: Math.h:289
T fastCos(const T &theta)
Fast, less precise cosine calculation.
Definition: Math.h:200
T fastAtan2(T y, T x)
Fast, but less precise atan2 calculation.
Definition: Math.h:220
T piQuart()
The constant pi/4.
T pi()
The constant pi.
T piSquare()
The constant pi^2.