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
43namespace Pt {
44
47template<typename T>
48T pi();
49
52template<typename T>
54
57template<typename T>
59
62template<typename T>
64
67template<typename T>
69
70
71template<>
72inline float pi<float>()
73{
74 return 3.14159265f;
75}
76
77template<>
78inline float piDouble<float>()
79{
80 return 6.28318531f;
81}
82
83template<>
84inline float piHalf<float>()
85{
86 return 1.57079633f;
87}
88
89template<>
90inline float piQuart<float>()
91{
92 return 0.78539816f;
93}
94
95template<>
96inline float piSquare<float>()
97{
98 return 9.86960440f;
99}
100
101
102template<>
103inline double pi<double>()
104{
105 return 3.14159265358979323846;
106}
107
108template<>
109inline double piDouble<double>()
110{
111 return 6.28318530717958647692;
112}
113
114template<>
115inline double piHalf<double>()
116{
117 return 1.57079632679489661923;
118}
119
120template<>
121inline double piQuart<double>()
122{
123 return 0.78539816339744830961;
124}
125
126template<>
127inline double piSquare<double>()
128{
129 return 9.86960440108935861883449099987615114;
130}
131
132
133static const float DegToRadF = 0.01745329f;
134
135static const float RadToDegF = 57.2957795f;
136
137static const double DegToRad = 0.0174532925199432957692;
138
139static const double RadToDeg = 57.295779513082320876846364344191;
140
141
142inline float degToRad(float deg)
143{
144 return deg * DegToRadF;
145}
146
147inline double degToRad(double deg)
148{
149 return deg * DegToRad;
150}
151
152
153inline float radToDeg(float rad)
154{
155 return rad * RadToDegF;
156}
157
158inline double radToDeg(double rad)
159{
160 return rad * RadToDeg;
161}
162
163
169template <typename T>
170T 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
199template <typename T>
200T 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
219template <typename T>
220T 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
252inline 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
262template <typename T>
263T invSqrt(T x)
264{
265 return static_cast<T>(1.0) / std::sqrt(x);
266}
267
268inline float invSqrtf(float x)
269{
270 return 1.0f / std::sqrt(x);
271}
272
275inline 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
289inline 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
344inline 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
int_type int32_t
Signed 32-bit integer type.
Definition Api-Types.h:45
Core module.
Definition Allocator.h:33
T fastAtan2(T y, T x)
Fast, but less precise atan2 calculation.
Definition Math.h:220
T piSquare()
The constant pi^2.
double hypot(double x, double y)
Return the euclidean distance of the given values.
Definition Math.h:275
T fastCos(const T &theta)
Fast, less precise cosine calculation.
Definition Math.h:200
T piQuart()
The constant pi/4.
T pi()
The constant pi.
T piDouble()
The constant pi*2.
Pt::int32_t lround(float x)
Rounds to nearest integer value.
Definition Math.h:289
T piHalf()
The constant pi/2.
T fastSin(const T &theta)
Fast, but less precise sine calculation.
Definition Math.h:170