1 | // |
2 | // Redistribution and use in source and binary forms, with or without |
3 | // modification, are permitted provided that the following conditions |
4 | // are met: |
5 | // * Redistributions of source code must retain the above copyright |
6 | // notice, this list of conditions and the following disclaimer. |
7 | // * Redistributions in binary form must reproduce the above copyright |
8 | // notice, this list of conditions and the following disclaimer in the |
9 | // documentation and/or other materials provided with the distribution. |
10 | // * Neither the name of NVIDIA CORPORATION nor the names of its |
11 | // contributors may be used to endorse or promote products derived |
12 | // from this software without specific prior written permission. |
13 | // |
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY |
15 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
17 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
18 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
19 | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
20 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
21 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
22 | // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
23 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
24 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | // |
26 | // Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved. |
27 | // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. |
28 | // Copyright (c) 2001-2004 NovodeX AG. All rights reserved. |
29 | |
30 | #ifndef PXFOUNDATION_PXMATH_H |
31 | #define PXFOUNDATION_PXMATH_H |
32 | |
33 | /** \addtogroup foundation |
34 | @{ |
35 | */ |
36 | |
37 | #include "foundation/PxPreprocessor.h" |
38 | |
39 | #if PX_VC |
40 | #pragma warning(push) |
41 | #pragma warning(disable : 4985) // 'symbol name': attributes not present on previous declaration |
42 | #endif |
43 | #include <math.h> |
44 | #if PX_VC |
45 | #pragma warning(pop) |
46 | #endif |
47 | |
48 | #include <float.h> |
49 | #include "foundation/PxIntrinsics.h" |
50 | #include "foundation/PxSharedAssert.h" |
51 | |
52 | #if !PX_DOXYGEN |
53 | namespace physx |
54 | { |
55 | #endif |
56 | |
57 | // constants |
58 | static const float PxPi = float(3.141592653589793); |
59 | static const float PxHalfPi = float(1.57079632679489661923); |
60 | static const float PxTwoPi = float(6.28318530717958647692); |
61 | static const float PxInvPi = float(0.31830988618379067154); |
62 | static const float PxInvTwoPi = float(0.15915494309189533577); |
63 | static const float PxPiDivTwo = float(1.57079632679489661923); |
64 | static const float PxPiDivFour = float(0.78539816339744830962); |
65 | |
66 | /** |
67 | \brief The return value is the greater of the two specified values. |
68 | */ |
69 | template <class T> |
70 | PX_CUDA_CALLABLE PX_FORCE_INLINE T PxMax(T a, T b) |
71 | { |
72 | return a < b ? b : a; |
73 | } |
74 | |
75 | //! overload for float to use fsel on xbox |
76 | template <> |
77 | PX_CUDA_CALLABLE PX_FORCE_INLINE float PxMax(float a, float b) |
78 | { |
79 | return intrinsics::selectMax(a, b); |
80 | } |
81 | |
82 | /** |
83 | \brief The return value is the lesser of the two specified values. |
84 | */ |
85 | template <class T> |
86 | PX_CUDA_CALLABLE PX_FORCE_INLINE T PxMin(T a, T b) |
87 | { |
88 | return a < b ? a : b; |
89 | } |
90 | |
91 | template <> |
92 | //! overload for float to use fsel on xbox |
93 | PX_CUDA_CALLABLE PX_FORCE_INLINE float PxMin(float a, float b) |
94 | { |
95 | return intrinsics::selectMin(a, b); |
96 | } |
97 | |
98 | /* |
99 | Many of these are just implemented as PX_CUDA_CALLABLE PX_FORCE_INLINE calls to the C lib right now, |
100 | but later we could replace some of them with some approximations or more |
101 | clever stuff. |
102 | */ |
103 | |
104 | /** |
105 | \brief abs returns the absolute value of its argument. |
106 | */ |
107 | PX_CUDA_CALLABLE PX_FORCE_INLINE float PxAbs(float a) |
108 | { |
109 | return intrinsics::abs(a); |
110 | } |
111 | |
112 | PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxEquals(float a, float b, float eps) |
113 | { |
114 | return (PxAbs(a: a - b) < eps); |
115 | } |
116 | |
117 | /** |
118 | \brief abs returns the absolute value of its argument. |
119 | */ |
120 | PX_CUDA_CALLABLE PX_FORCE_INLINE double PxAbs(double a) |
121 | { |
122 | return ::fabs(x: a); |
123 | } |
124 | |
125 | /** |
126 | \brief abs returns the absolute value of its argument. |
127 | */ |
128 | PX_CUDA_CALLABLE PX_FORCE_INLINE int32_t PxAbs(int32_t a) |
129 | { |
130 | return ::abs(x: a); |
131 | } |
132 | |
133 | /** |
134 | \brief Clamps v to the range [hi,lo] |
135 | */ |
136 | template <class T> |
137 | PX_CUDA_CALLABLE PX_FORCE_INLINE T PxClamp(T v, T lo, T hi) |
138 | { |
139 | PX_SHARED_ASSERT(lo <= hi); |
140 | return PxMin(hi, PxMax(lo, v)); |
141 | } |
142 | |
143 | //! \brief Square root. |
144 | PX_CUDA_CALLABLE PX_FORCE_INLINE float PxSqrt(float a) |
145 | { |
146 | return intrinsics::sqrt(a); |
147 | } |
148 | |
149 | //! \brief Square root. |
150 | PX_CUDA_CALLABLE PX_FORCE_INLINE double PxSqrt(double a) |
151 | { |
152 | return ::sqrt(x: a); |
153 | } |
154 | |
155 | //! \brief reciprocal square root. |
156 | PX_CUDA_CALLABLE PX_FORCE_INLINE float PxRecipSqrt(float a) |
157 | { |
158 | return intrinsics::recipSqrt(a); |
159 | } |
160 | |
161 | //! \brief reciprocal square root. |
162 | PX_CUDA_CALLABLE PX_FORCE_INLINE double PxRecipSqrt(double a) |
163 | { |
164 | return 1 / ::sqrt(x: a); |
165 | } |
166 | |
167 | //! trigonometry -- all angles are in radians. |
168 | |
169 | //! \brief Sine of an angle ( <b>Unit:</b> Radians ) |
170 | PX_CUDA_CALLABLE PX_FORCE_INLINE float PxSin(float a) |
171 | { |
172 | return intrinsics::sin(a); |
173 | } |
174 | |
175 | //! \brief Sine of an angle ( <b>Unit:</b> Radians ) |
176 | PX_CUDA_CALLABLE PX_FORCE_INLINE double PxSin(double a) |
177 | { |
178 | return ::sin(x: a); |
179 | } |
180 | |
181 | //! \brief Cosine of an angle (<b>Unit:</b> Radians) |
182 | PX_CUDA_CALLABLE PX_FORCE_INLINE float PxCos(float a) |
183 | { |
184 | return intrinsics::cos(a); |
185 | } |
186 | |
187 | //! \brief Cosine of an angle (<b>Unit:</b> Radians) |
188 | PX_CUDA_CALLABLE PX_FORCE_INLINE double PxCos(double a) |
189 | { |
190 | return ::cos(x: a); |
191 | } |
192 | |
193 | /** |
194 | \brief Tangent of an angle. |
195 | <b>Unit:</b> Radians |
196 | */ |
197 | PX_CUDA_CALLABLE PX_FORCE_INLINE float PxTan(float a) |
198 | { |
199 | return ::tanf(x: a); |
200 | } |
201 | |
202 | /** |
203 | \brief Tangent of an angle. |
204 | <b>Unit:</b> Radians |
205 | */ |
206 | PX_CUDA_CALLABLE PX_FORCE_INLINE double PxTan(double a) |
207 | { |
208 | return ::tan(x: a); |
209 | } |
210 | |
211 | /** |
212 | \brief Arcsine. |
213 | Returns angle between -PI/2 and PI/2 in radians |
214 | <b>Unit:</b> Radians |
215 | */ |
216 | PX_CUDA_CALLABLE PX_FORCE_INLINE float PxAsin(float f) |
217 | { |
218 | return ::asinf(x: PxClamp(v: f, lo: -1.0f, hi: 1.0f)); |
219 | } |
220 | |
221 | /** |
222 | \brief Arcsine. |
223 | Returns angle between -PI/2 and PI/2 in radians |
224 | <b>Unit:</b> Radians |
225 | */ |
226 | PX_CUDA_CALLABLE PX_FORCE_INLINE double PxAsin(double f) |
227 | { |
228 | return ::asin(x: PxClamp(v: f, lo: -1.0, hi: 1.0)); |
229 | } |
230 | |
231 | /** |
232 | \brief Arccosine. |
233 | Returns angle between 0 and PI in radians |
234 | <b>Unit:</b> Radians |
235 | */ |
236 | PX_CUDA_CALLABLE PX_FORCE_INLINE float PxAcos(float f) |
237 | { |
238 | return ::acosf(x: PxClamp(v: f, lo: -1.0f, hi: 1.0f)); |
239 | } |
240 | |
241 | /** |
242 | \brief Arccosine. |
243 | Returns angle between 0 and PI in radians |
244 | <b>Unit:</b> Radians |
245 | */ |
246 | PX_CUDA_CALLABLE PX_FORCE_INLINE double PxAcos(double f) |
247 | { |
248 | return ::acos(x: PxClamp(v: f, lo: -1.0, hi: 1.0)); |
249 | } |
250 | |
251 | /** |
252 | \brief ArcTangent. |
253 | Returns angle between -PI/2 and PI/2 in radians |
254 | <b>Unit:</b> Radians |
255 | */ |
256 | PX_CUDA_CALLABLE PX_FORCE_INLINE float PxAtan(float a) |
257 | { |
258 | return ::atanf(x: a); |
259 | } |
260 | |
261 | /** |
262 | \brief ArcTangent. |
263 | Returns angle between -PI/2 and PI/2 in radians |
264 | <b>Unit:</b> Radians |
265 | */ |
266 | PX_CUDA_CALLABLE PX_FORCE_INLINE double PxAtan(double a) |
267 | { |
268 | return ::atan(x: a); |
269 | } |
270 | |
271 | /** |
272 | \brief Arctangent of (x/y) with correct sign. |
273 | Returns angle between -PI and PI in radians |
274 | <b>Unit:</b> Radians |
275 | */ |
276 | PX_CUDA_CALLABLE PX_FORCE_INLINE float PxAtan2(float x, float y) |
277 | { |
278 | return ::atan2f(y: x, x: y); |
279 | } |
280 | |
281 | /** |
282 | \brief Arctangent of (x/y) with correct sign. |
283 | Returns angle between -PI and PI in radians |
284 | <b>Unit:</b> Radians |
285 | */ |
286 | PX_CUDA_CALLABLE PX_FORCE_INLINE double PxAtan2(double x, double y) |
287 | { |
288 | return ::atan2(y: x, x: y); |
289 | } |
290 | |
291 | //! \brief returns true if the passed number is a finite floating point number as opposed to INF, NAN, etc. |
292 | PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxIsFinite(float f) |
293 | { |
294 | return intrinsics::isFinite(a: f); |
295 | } |
296 | |
297 | //! \brief returns true if the passed number is a finite floating point number as opposed to INF, NAN, etc. |
298 | PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxIsFinite(double f) |
299 | { |
300 | return intrinsics::isFinite(a: f); |
301 | } |
302 | |
303 | PX_CUDA_CALLABLE PX_FORCE_INLINE float PxFloor(float a) |
304 | { |
305 | return ::floorf(x: a); |
306 | } |
307 | |
308 | PX_CUDA_CALLABLE PX_FORCE_INLINE float PxExp(float a) |
309 | { |
310 | return ::expf(x: a); |
311 | } |
312 | |
313 | PX_CUDA_CALLABLE PX_FORCE_INLINE float PxCeil(float a) |
314 | { |
315 | return ::ceilf(x: a); |
316 | } |
317 | |
318 | PX_CUDA_CALLABLE PX_FORCE_INLINE float PxSign(float a) |
319 | { |
320 | return physx::intrinsics::sign(a); |
321 | } |
322 | |
323 | PX_CUDA_CALLABLE PX_FORCE_INLINE float PxPow(float x, float y) |
324 | { |
325 | return ::powf(x: x, y: y); |
326 | } |
327 | |
328 | PX_CUDA_CALLABLE PX_FORCE_INLINE float PxLog(float x) |
329 | { |
330 | return ::logf(x: x); |
331 | } |
332 | |
333 | #if !PX_DOXYGEN |
334 | } // namespace physx |
335 | #endif |
336 | |
337 | /** @} */ |
338 | #endif // #ifndef PXFOUNDATION_PXMATH_H |
339 | |