gwnavruntime/math/fastmath.h Source File

fastmath.h
Go to the documentation of this file.
1 /*
2 * Copyright 2016 Autodesk, Inc. All rights reserved.
3 * Use of this software is subject to the terms of the Autodesk license agreement and any attachments or Appendices thereto provided at the time of installation or download,
4 * or which otherwise accompanies this software in either electronic or hard copy form, or which is signed by you and accepted by Autodesk.
5 */
6 
7 #pragma once
8 
10 #include <math.h>
11 
12 namespace Kaim
13 {
14 
15 //----------------------------------------------------------------------------------------
16 // Fsel
17 
19 KY_INLINE KyFloat32 Fsel(KyFloat32 a, KyFloat32 x, KyFloat32 y) { return a >= 0.0f ? x : y; }
20 
21 //----------------------------------------------------------------------------------------
22 // Isel Lsel
23 
26 KY_INLINE KyInt32 Isel(KyInt32 a, KyInt32 x, KyInt32 y)
27 {
28  // mask=0xFFFFFFFFFFFFFFFF if (a < 0) mask=0x0000000000000000 if (a >= 0)
29  const KyInt32 mask = a >> 31;
30  return x + ((y - x) & mask);
31 };
32 
35 KY_INLINE KyInt64 Lsel(KyInt64 a, KyInt64 x, KyInt64 y)
36 {
37  // mask=0xFFFFFFFFFFFFFFFF if a<0, mask=0x0000000000000000 if a>=0
38  const KyInt64 mask = a >> 63;
39  return x + ((y - x) & mask);
40 };
41 
43 KY_INLINE KyInt64 Lsign(KyInt64 x) { return (x >> 63) - ((-x) >> 63); };
44 KY_INLINE KyInt32 Isign(KyInt32 x) { return (x >> 31) - ((-x) >> 31); };
45 
46 //----------------------------------------------------------------------------------------
47 // Min / Max
48 
49 template <typename T> KY_INLINE T Min(const T& a, const T& b) { return (a < b) ? a : b; }
50 template <typename T> KY_INLINE T Max(const T& a, const T& b) { return (a < b) ? b : a; }
51 
52 template <typename T> KY_INLINE T Min(const T& a, const T& b, const T& c) { return Min(Min(a, b), c); }
53 template <typename T> KY_INLINE T Max(const T& a, const T& b, const T& c) { return Max(Max(a, b), c); }
54 
55 template <typename T> KY_INLINE T Min(const T& a, const T& b, const T& c, const T& d) { return Min(Min(a, b), Min(c, d)); }
56 template <typename T> KY_INLINE T Max(const T& a, const T& b, const T& c, const T& d) { return Max(Max(a, b), Max(c, d)); }
57 
58 template <typename T> KY_INLINE T Min(const T& a, const T& b, const T& c, const T& d, const T& e) { return Min(Min(a, b, c, d), e); }
59 template <typename T> KY_INLINE T Max(const T& a, const T& b, const T& c, const T& d, const T& e) { return Max(Max(a, b, c, d), e); }
60 
61 template <typename T> KY_INLINE T Clamp(const T& x, const T& min_, const T& max_)
62 {
63  if (x > max_) return max_;
64  if (x < min_) return min_;
65  return x;
66 }
67 
68 template <typename T> inline bool Less(const T& a, const T& b, const T& c) { return a < b && b < c; }
69 template <typename T> inline bool LessEq(const T& a, const T& b, const T& c) { return a <= b && b <= c; }
70 
71 //---------------------------------------------------------------------
72 // Fsel specialization for floats
73 #if defined(KY_CPU_PPC) || defined(KY_CPU_PPC64)
74 
75 template<>
76 KY_INLINE KyFloat32 Min(const KyFloat32& a, const KyFloat32& b) { return Fsel(a - b, b, a);}
77 template<>
78 KY_INLINE KyFloat32 Max(const KyFloat32& a, const KyFloat32& b) { return Fsel(a - b, a, b); }
79 
80 #endif
81 //---------------------------------------------------------------------
82 
83 KY_INLINE KyUInt32 FastDivisionBy3(KyUInt32 i) { return (i * 0x0000AAAB) >> 17; } // WARNING : Can overflow
84 KY_INLINE KyUInt32 FastModuloBy3(KyUInt32 i) { return i - 3 * FastDivisionBy3(i); } // WARNING : Can overflow
85 
86 
87 KY_INLINE KyInt32 FastMin(KyInt32 a, KyInt32 b) { return Isel(a - b, b, a); } // WARNING : Can overflow because of the a - b
88 KY_INLINE KyInt32 FastMax(KyInt32 a, KyInt32 b) { return Isel(a - b, a, b); } // WARNING : Can overflow because of the a - b
89 
90 KY_INLINE KyInt32 FastMin(KyInt32 a, KyInt32 b, KyInt32 c) { return FastMin(FastMin(a, b), c); }
91 KY_INLINE KyInt32 FastMax(KyInt32 a, KyInt32 b, KyInt32 c) { return FastMax(FastMax(a, b), c); }
92 KY_INLINE KyInt32 FastMin(KyInt32 a, KyInt32 b, KyInt32 c, KyInt32 d) { return FastMin(FastMin(FastMin(a, b), c), d); }
93 KY_INLINE KyInt32 FastMax(KyInt32 a, KyInt32 b, KyInt32 c, KyInt32 d) { return FastMin(FastMax(FastMax(a, b), c), d); }
94 
95 
96 KY_INLINE KyInt64 FastMin(KyInt64 a, KyInt64 b) { return Lsel(a - b, b, a); } // WARNING : Can overflow because of the a - b
97 KY_INLINE KyInt64 FastMax(KyInt64 a, KyInt64 b) { return Lsel(a - b, a, b); } // WARNING : Can overflow because of the a - b
98 
99 KY_INLINE KyInt64 FastMin(KyInt64 a, KyInt64 b, KyInt64 c) { return FastMin(FastMin(a, b), c); }
100 KY_INLINE KyInt64 FastMax(KyInt64 a, KyInt64 b, KyInt64 c) { return FastMax(FastMax(a, b), c); }
101 KY_INLINE KyInt64 FastMin(KyInt64 a, KyInt64 b, KyInt64 c, KyInt64 d) { return FastMin(FastMin(FastMin(a, b), c), d); }
102 KY_INLINE KyInt64 FastMax(KyInt64 a, KyInt64 b, KyInt64 c, KyInt64 d) { return FastMin(FastMax(FastMax(a, b), c), d); }
103 
104 
105 // remove this function and replace it with template<class T> struct OperatorLess
106 template <typename T1, typename T2 = T1>
107 class DefaultLess
108 {
109 public:
110  KY_INLINE bool operator()(const T1& lhs, const T2& rhs) const { return lhs < rhs; }
111 };
112 
113 
114 //----------------------------------------------------------------------------------------
115 // Float32 to signed int32
116 
117 KY_INLINE KyInt32 NearestInt(KyFloat32 x) { return (KyInt32)(x + Kaim::Fsel(x, 0.5f, -0.5f)); }
118 
119 // LowerInt( 1.0f) = 1
120 // LowerInt(-1.0f) = -1
121 KY_INLINE KyInt32 LowerInt(KyFloat32 x) { return (KyInt32)(floorf(x)); }
122 
123 // FastLowerInt( 1.0f) = 1
124 // FastLowerInt(-1.0f) = -2 !!
125 KY_INLINE KyInt32 FastLowerInt(KyFloat32 x) { return (KyInt32)(x + Kaim::Fsel(x, 0.0f, -1.0f)); }
126 
127 // UpperInt( 1.0f) = 1
128 // UpperInt(-1.0f) = -1
129 KY_INLINE KyInt32 UpperInt(KyFloat32 x) { return (KyInt32)(ceilf(x)); }
130 
131 
132 // -----------------------------------------------------------
133 // Rotation and angles
134 
135 // Cap the input to [-1.0, 1.0] to be robust to float precision errors and to avoid returning NaN
136 KY_INLINE KyFloat32 Acosf(KyFloat32 x) { return acosf(Clamp(x, -1.0f, 1.0f)); }
137 
138 KY_INLINE KyFloat32 Sqrtf(KyFloat32 x) { return sqrtf(x); }
139 KY_INLINE KyFloat32 Cosf(KyFloat32 angleRad) { return cosf(angleRad); }
140 KY_INLINE KyFloat32 Sinf(KyFloat32 angleRad) { return sinf(angleRad); }
141 
142 static const KyFloat32 KY_PI = 3.14159265f;
143 static const KyFloat32 KY_2_PI = 2.0f * KY_PI;
144 static const KyFloat32 KY_PI_DIVIDED_BY_180 = KY_PI / 180.0f;
145 static const KyFloat32 KY_180_DIVIDED_BY_PI = 180.0f / KY_PI;
146 KY_INLINE KyFloat32 RadFromDeg(KyFloat32 degrees) { return degrees * KY_PI_DIVIDED_BY_180; }
147 KY_INLINE KyFloat32 DegFromRad(KyFloat32 radians) { return radians * KY_180_DIVIDED_BY_PI; }
148 
149 // Commented because never used at the moment
150 //KY_INLINE KyFloat32 Asinf(KyFloat32 input)
151 //{
152 // // Cap the input to [-1.0, 1.0] to be robust to float precision errors and to avoid returning a NaN
153 // const KyFloat32 normalizeDotProd = Kaim::Min(1.f, Kaim::Max(-1.f, input));
154 // return asinf(normalizeDotProd);
155 //}
156 
157 //----------------------------------------------------------------------------------------
158 // Floating points
159 
160 static const KyFloat32 KY_MIN_NORMALIZED_FLOAT = FLT_MIN; // min normalized positive value
161 static const KyFloat32 KY_EPSILON = FLT_EPSILON; // smallest such that 1.0+FLT_EPSILON != 1.0
162 
163 KY_INLINE bool IsFloatDenormalized(KyFloat32 x) { return x < KY_MIN_NORMALIZED_FLOAT && x > -KY_MIN_NORMALIZED_FLOAT; }
164 KY_INLINE bool IsFloatNormalized(KyFloat32 x) { return x >= KY_MIN_NORMALIZED_FLOAT || x <= -KY_MIN_NORMALIZED_FLOAT; }
165 KY_INLINE bool CanDivideBy(KyFloat32 x) { return x >= KY_MIN_NORMALIZED_FLOAT || x <= -KY_MIN_NORMALIZED_FLOAT; }
166 
167 KY_INLINE bool IsEpsilonPositive(KyFloat32 x) { return x > KY_EPSILON; }
168 KY_INLINE bool IsEpsilonNegative(KyFloat32 x) { return x < -KY_EPSILON; }
169 KY_INLINE bool IsEpsilonZero(KyFloat32 x) { return x <= KY_EPSILON && x >= -KY_EPSILON; }
170 KY_INLINE bool IsEpsilonEqual(KyFloat32 a, KyFloat32 b) { return IsEpsilonZero(a - b); };
171 
172 KY_INLINE bool IsNearZero(KyFloat32 x, KyFloat32 dist) { return x <= dist && x >= -dist; }
173 KY_INLINE bool IsNearEqual(KyFloat32 a, KyFloat32 b, KyFloat32 dist) { return IsNearZero(a - b, dist); };
174 
175 //----------------------------------------------------------------------------------------
176 // Other stuff
177 
178 namespace Winding { enum Enum { CCW = 0, CW = 1}; }
179 
180 template<typename T>
181 KY_INLINE T Square(const T& x) { return x * x; }
182 
183 #define KY_SQRT1_2 ((KyFloat32)0.70710678118654752440f) // 1/sqrt(2)
184 
185 
186 //----------------------------------------------------------------------------------------
187 // integer division rounded toward nearest
188 // 5/3=1.66 -5/3=-1.66 5/2=1.5 -5/2=-1.5
189 // regular integer division rounds towards zero : 5/3=1 -5/3=-1 5/2=1 -5/2=-1
190 // DivNearest() rounds towards the nearest integer : 5/3=2 -5/3=-2 5/2=1 -5/2=-2
191 KY_INLINE KyInt64 DivNearest(KyInt64 a, KyInt64 b)
192 {
193  KyInt64 a2 = a * 2;
194  KyInt64 d2 = a2 / b;
195  KyInt64 m2 = a2 % b;
196  KyInt64 sab = (a ^ b) >> 63; // a/b<0 ? -1 : 0
197  KyInt64 c = (m2 == 0 && sab == 0) ? 0 : 2 * sab + 1;
198  return (d2 + c) / 2;
199 }
200 
201 // 20% slower than DivNearest but does not multiply a by 2, so has 1 less bit chance to overflow
202 KY_INLINE KyInt64 DivNearestAlt(KyInt64 a, KyInt64 b)
203 {
204  KyInt64 sab = ((a ^ b) >> 63);
205  KyInt64 sb = 2 * (b >> 63) + 1;
206  KyInt64 c = (1 + sab) * (b - sb) + sab * b; // c(sab=0)=(b - sb) c(sab=-1)=-b
207  return (a + c / 2) / b;
208 }
209 
210 //----------------------------------------------------------------------------------------
211 // integer division rounded toward -infinite
212 // 5/3=1.66 -5/3=-1.66 5/2=1.5 -5/2=-1.5
213 // regular integer division rounds towards zero : 5/3=1 -5/3=-1 5/2=1 -5/2=-1
214 // DivFloor() rounds towards the lower integer : 5/3=1 -5/3=-2 5/2=1 -5/2=-2
215 inline KyInt64 DivFloor(KyInt64 a, KyInt64 b)
216 {
217  KyInt64 sab = (a ^ b) >> 63; // a/b<0 ? -1 : 0
218  KyInt64 sb = 2 * (b >> 63) + 1; // b<0 ? -1 : 1
219  KyInt64 c = sab * (b - sb);
220  return (a + c) / b;
221 }
222 
223 }
static const KyFloat32 KY_PI
Stores the value of pi.
Definition: fastmath.h:142
static const KyFloat32 KY_180_DIVIDED_BY_PI
Stores the value of 180 divided by KY_PI.
Definition: fastmath.h:145
std::uint32_t KyUInt32
uint32_t
Definition: types.h:29
KyInt64 Lsign(KyInt64 x)
return -1 if x<0, 0="" if="" x="=0," 1="" if="" x="">0
Definition: fastmath.h:43
KyFloat32 DegFromRad(KyFloat32 radians)
Converts radians into degrees.
Definition: fastmath.h:147
KyInt32 Isel(KyInt32 a, KyInt32 x, KyInt32 y)
If a is greater than 0, returns x.
Definition: fastmath.h:26
KyFloat32 RadFromDeg(KyFloat32 degrees)
Converts degrees into radians.
Definition: fastmath.h:146
std::int64_t KyInt64
int64_t
Definition: types.h:25
The Autodesk Navigation namespace.
Definition: gamekitcrowddispersion.cpp:17
std::int32_t KyInt32
int32_t
Definition: types.h:24
static const KyFloat32 KY_PI_DIVIDED_BY_180
Stores the value of KY_PI divided by 180.
Definition: fastmath.h:144
static const KyFloat32 KY_2_PI
Stores the value of 2*pi.
Definition: fastmath.h:143
KyFloat32 Fsel(KyFloat32 a, KyFloat32 x, KyFloat32 y)
x if a>=0.0f, y if a<0.0f>
Definition: fastmath.h:19
float KyFloat32
float
Definition: types.h:32
KyInt64 Lsel(KyInt64 a, KyInt64 x, KyInt64 y)
If a is greater than 0, returns x.
Definition: fastmath.h:35