AGX Dynamics 2.40.0.0
Loading...
Searching...
No Matches
Math.h
Go to the documentation of this file.
1/*
2Copyright 2007-2025. Algoryx Simulation AB.
3
4All AGX source code, intellectual property, documentation, sample code,
5tutorials, scene files and technical white papers, are copyrighted, proprietary
6and confidential material of Algoryx Simulation AB. You may not download, read,
7store, distribute, publish, copy or otherwise disseminate, use or expose this
8material unless having a written signed agreement with Algoryx Simulation AB, or having been
9advised so by Algoryx Simulation AB for a time limited evaluation, or having purchased a
10valid commercial license from Algoryx Simulation AB.
11
12Algoryx Simulation AB disclaims all responsibilities for loss or damage caused
13from using this software, unless otherwise stated in written agreements with
14Algoryx Simulation AB.
15*/
16
17#pragma once
18
19#include <agx/config.h>
20
21#include <agx/macros.h>
22#include <agx/agxCore_export.h>
23#include <agx/debug.h>
24#include <agx/Real.h>
25#include <agx/Integer.h>
26#include <agx/Random.h>
27
28#include <cmath>
29
30#ifdef _MSC_VER
31 #define _USE_MATH_DEFINES
32 #include <math.h>
33
34 #ifndef NOMINMAX
35 #define NOMINMAX
36 #endif
37
38#else
39 #include <math.h>
40#endif
41
42#include <stdlib.h>
43#include <limits>
44#include <algorithm>
45
46
47#include <float.h>
48
49namespace agx
50{
51 // physics related constants
52 static constexpr Real GRAVITY_ACCELERATION = Real(9.80665); // in m/s2, SI standard acceleration due to gravity
53
54
55 #define NUMERIC_MAX(type) std::numeric_limits<type>::max()
56 #define NUMERIC_MIN(type) std::numeric_limits<type>::min()
57 static constexpr Real AGX_EQUIVALENT_EPSILON = (double)1E-9;
58 #define AGX_BIT_MASK(bit) (1 << bit)
59 #define AGX_TEST_BIT(val, bit) (val & AGX_BIT_MASK(bit))
60 #define AGX_SET_BIT(val, bit) (val |= AGX_BIT_MASK(bit))
61 #define AGX_UNSET_BIT(val, bit) (val &= ~AGX_BIT_MASK(bit))
62
63 static constexpr Real PI = agx::Real(M_PI);
64 static constexpr Real PI_2 = agx::Real(M_PI_2);
65 static constexpr Real PI_4 = agx::Real(M_PI_4);
66
67 // define the standard trig values
68
69 static constexpr Real DEG_TO_RAD = agx::Real(0.017453292519943295769236907684886);
70 static constexpr Real RAD_TO_DEG = agx::Real(57.295779513082320876798154814105);
71
72 inline const Real Infinity = std::numeric_limits<Real>::infinity();
74
75
76
77 template <typename T>
78 AGX_FORCE_INLINE T inverse(const T& value)
79 {
80 return T(1) / value;
81 }
82
83 template <typename T>
85 {
86 return !(bool)(val & 0x1);
87 }
88
89
93 inline Real sinc( Real x, Real nearZero = Real(1E-4) )
94 {
95 if ( std::abs( x ) < nearZero )
96 {
97 return Real(1) - (x * x) / Real(6) + (x * x * x * x) / Real(120);
98 }
99 else
100 {
101 return std::sin( x ) / x;
102 }
103 }
104
110 template<typename T>
111 AGX_FORCE_INLINE bool _equivalent( T lhs, T rhs, T epsilon = T(AGX_EQUIVALENT_EPSILON) )
112 {
113 return (lhs + epsilon >= rhs) && (lhs - epsilon <= rhs);
114 }
115
121 AGX_FORCE_INLINE bool equivalent(float lhs, float rhs, float epsilon = (float)AGX_EQUIVALENT_EPSILON)
122 {
123 return _equivalent< float >(lhs, rhs, epsilon);
124 }
125
131 AGX_FORCE_INLINE bool equivalent(double lhs, double rhs, double epsilon = (double)AGX_EQUIVALENT_EPSILON)
132 {
133 return _equivalent< double >(lhs, rhs, epsilon);
134 }
135
141 AGX_FORCE_INLINE bool equivalent(float lhs, float rhs, double epsilon)
142 {
143 return _equivalent(lhs, rhs, (float)epsilon);
144 }
145
146
153 template<typename T>
154 AGX_FORCE_INLINE bool _relativelyEquivalent( T lhs, T rhs, T relativeEpsilon = T(AGX_EQUIVALENT_EPSILON) )
155 {
156 return _equivalent(lhs, rhs, (std::abs(lhs) + std::abs(rhs) + T(1)) * relativeEpsilon);
157 }
158
165 AGX_FORCE_INLINE bool relativelyEquivalent(float lhs, float rhs, float epsilon = (float)AGX_EQUIVALENT_EPSILON)
166 {
167 return _relativelyEquivalent< float >(lhs, rhs, epsilon);
168 }
169
176 AGX_FORCE_INLINE bool relativelyEquivalent(double lhs, double rhs, double epsilon = (double)AGX_EQUIVALENT_EPSILON)
177 {
178 return _relativelyEquivalent< double >(lhs, rhs, epsilon);
179 }
180
187 AGX_FORCE_INLINE bool relativelyEquivalent(float lhs, float rhs, double epsilon)
188 {
189 return _relativelyEquivalent(lhs, rhs, (float)epsilon);
190 }
191
192
194#define INT_EQUALS_ZERO( T ) \
195 AGX_FORCE_INLINE bool equalsZero( T f ) \
196 { \
197 return ( f == 0 ); \
198 }
199
200#define INT_IS_NAN( T ) \
201 AGX_FORCE_INLINE bool isNaN( T /*v*/ ) \
202 { \
203 return false; \
204 }
205
206#define INT_IS_INF( T ) \
207 AGX_FORCE_INLINE bool isInf( T /*v*/ ) \
208 { \
209 return false; \
210 }
211
212#define INT_IS_FINITE( T ) \
213 AGX_FORCE_INLINE bool isFinite( T /*v*/ ) \
214 { \
215 return true; \
216 }
217
218#define UINT_ABSOLUTE( T ) \
219 AGX_FORCE_INLINE T absolute( T v ) \
220 { \
221 return v; \
222 }
223
228
233
238
243
248
253
258
263
268
269#undef INT_EQUALS_ZERO
270#undef INT_IS_NAN
271#undef INT_IS_INF
272#undef INT_IS_FINITE
273#undef UINT_ABSOLUTE
274
276 AGX_FORCE_INLINE bool equalsZero( float f, float eps=FLT_EPSILON )
277 {
278 return ( f < eps && f > -eps );
279 }
280
282 AGX_FORCE_INLINE bool equalsZero( double d, double eps=DBL_EPSILON )
283 {
284 return ( d < eps && d > -eps );
285 }
286
287
290 template<typename T>
292 {
293 return std::abs(v);
294 }
295
296 template<typename T>
298 {
299 return std::isinf( v ) != 0;
300 }
301
302 template<typename T>
304 {
305 return std::isnan( v );
306 }
307
308 template<typename T>
310 {
311 return std::isfinite(v);
312 }
313
317 template<typename T1, typename T2, typename T3>
318 AGX_FORCE_INLINE T1 clamp( T1 v, T2 minimum, T3 maximum )
319 {
320 return v < minimum ? minimum : v > maximum ? maximum : v;
321 }
322
323
327 template<typename T>
329 {
330 return v < T(0) ? T(-1) : T(1);
331 }
332
334 template<typename T>
336 {
337 return v*v;
338 }
339
341 template<typename T>
343 {
344 return v < ( T )0 ? -v*v : v*v;
345 }
346
349 {
350 return angle * Real(DEG_TO_RAD);
351 }
352
355 {
356 return angle*Real(RAD_TO_DEG);
357 }
358
366 AGXCORE_EXPORT Real normalizedAngle( Real angle, bool positiveRange = false );
367
369 AGX_FORCE_INLINE bool leq( double a, double b, double eps = (double)AGX_EQUIVALENT_EPSILON )
370 {
371 return a < b + eps;
372 }
373
375 AGX_FORCE_INLINE bool leq(float a, float b, float eps = (float)AGX_EQUIVALENT_EPSILON)
376 {
377 return a < b + eps;
378 }
379
381 AGX_FORCE_INLINE bool geq(double a, double b, double eps = (double)AGX_EQUIVALENT_EPSILON)
382 {
383 return a > b - eps;
384 }
385
387 AGX_FORCE_INLINE bool geq(float a, float b, float eps = (float)AGX_EQUIVALENT_EPSILON)
388 {
389 return a > b - eps;
390 }
391
392
394 {
395 Int32 ret = -1;
396 while (val != 0) {
397 val >>= 1;
398 ret++;
399 }
400 return ret;
401 }
402
403
407 template <typename T>
409 {
410 return (value & (value-1)) == 0;
411 }
412
414 {
415 value--;
416 value |= (value >> 1);
417 value |= (value >> 2);
418 value |= (value >> 4);
419 value |= (value >> 8);
420 value |= (value >> 16);
421 value++;
422 return value;
423 }
424
426 {
427 value--;
428 value |= (value >> 1);
429 value |= (value >> 2);
430 value |= (value >> 4);
431 value |= (value >> 8);
432 value |= (value >> 16);
433 value++;
434 return value;
435 }
436
437
439 {
440 value--;
441 value |= (value >> 1);
442 value |= (value >> 2);
443 value |= (value >> 4);
444 value |= (value >> 8);
445 value |= (value >> 16);
446 value |= (value >> 32);
447 value++;
448 return value;
449 }
450
452 {
453 value--;
454 value |= (value >> 1);
455 value |= (value >> 2);
456 value |= (value >> 4);
457 value |= (value >> 8);
458 value |= (value >> 16);
459 value |= (value >> 32);
460 value++;
461 return value;
462 }
463
464
465 template <typename T>
466 AGX_FORCE_INLINE T align_ceil(T value, T alignment)
467 {
468 agxAssert(alignment > 0);
469 return value > 0 ? (value + (alignment-1) - ((value-1) % alignment)) : 0;
470 }
471
472 template <typename T1, typename T2>
473 AGX_FORCE_INLINE T1 *align_ceil(const T1 *ptr, T2 alignment)
474 {
475 return (T1 *)align_ceil<agx::UInt64>((agx::UInt64)ptr, (agx::UInt64)alignment);
476 }
477
478
479 template <typename T>
480 AGX_FORCE_INLINE T align_floor(T value, T alignment)
481 {
482 agxAssert(alignment > 0);
483 return value - (value % alignment);
484 }
485
486 template <typename T1, typename T2>
487 AGX_FORCE_INLINE T1 *align_floor(const T1 *ptr, T2 alignment)
488 {
489 return (T1 *)align_floor<agx::UInt64>((agx::UInt64)ptr, (agx::UInt64)alignment);
490 }
491
492 template <typename T>
493 AGX_FORCE_INLINE bool isAligned(T value, T alignment)
494 {
495 return value % alignment == 0;
496 }
497
498 template <typename T1, typename T2>
499 AGX_FORCE_INLINE bool isAligned(const T1 *ptr, T2 alignment)
500 {
501 return isAligned((uintptr_t)ptr, (uintptr_t)alignment);
502 }
503
504 template <typename T>
505 AGX_FORCE_INLINE T align_ceil2(T value, T alignment)
506 {
507 agxAssert(isPowerOfTwo(alignment));
508 T tmp = alignment-1;
509 return ((value + tmp) & ~tmp);
510 }
511
512 template <typename T1, typename T2>
513 AGX_FORCE_INLINE T1 *align_ceil2(const T1 *ptr, T2 alignment)
514 {
515 return (T1 *)align_ceil2<agx::UInt64>((agx::UInt64)ptr, (agx::UInt64)alignment);
516 }
517
518 template <typename T>
519 AGX_FORCE_INLINE T align_floor2(T value, T alignment)
520 {
521 agxAssert(isPowerOfTwo(alignment));
522 T tmp = alignment-1;
523 return (value & ~tmp);
524 }
525
526 template <typename T1, typename T2>
527 AGX_FORCE_INLINE T1 *align_floor2(const T1 *ptr, T2 alignment)
528 {
529 return (T1 *)align_floor2<agx::UInt64>((agx::UInt64)ptr, (agx::UInt64)alignment);
530 }
531
532 // basic method for generating primes
534
536 AGXCORE_EXPORT double strtod(const char *nptr, char **endptr);
537
539 AGXCORE_EXPORT float strtof(const char *nptr, char **endptr);
540
541
542
544
549 {
550 return getRandGenerator().rand() % (max - min) + min;
551 }
552
554 template <typename T>
556 {
557 Real sample = static_cast<Real>(getRandGenerator().rand());
558 Real randEnd = static_cast<Real>(RAND_MAX);
559 Real range_fraction = sample / randEnd;
560 Real range = static_cast<Real>(max - min);
561 T offset = static_cast<T>(range_fraction * range);
562 T value = static_cast<T>(min + offset);
563 return value;
564 }
565
566
570 template<typename T>
571 AGX_FORCE_INLINE Real computeVolume( const T& a, const T& b, const T& c, const T& d )
572 {
573 return fabsf( ( ( b -c ) ^ ( a - b ) )*( d - b ) );
574 }
575
577 template<typename T>
578 AGX_FORCE_INLINE Real computeVolume( const T& f1, const T& f2, const T& f3,
579 const T& b1, const T& b2, const T& b3 )
580 {
581 return computeVolume( f1, f2, f3, b1 ) +
582 computeVolume( b1, b2, b3, f2 ) +
583 computeVolume( b1, b3, f2, f3 );
584 }
585
589 template<typename T1, typename T2>
590 AGX_FORCE_INLINE T1 const lerp(T1 const& a, T1 const& b, T2 t)
591 {
592 if (t >= 1)
593 return b;
594 if (t <= 0)
595 return a;
596
597 return static_cast<T1>(a*(1-t) + b*t);
598 }
599
616 template<typename T1, typename T2>
617 AGX_FORCE_INLINE T1 const parametricBlend(T1 const& a, T1 const& b, T2 t)
618 {
619 if (t >= 1)
620 return b;
621 if (t <= 0)
622 return a;
623
624 T2 sqr = t * t;
625 return static_cast<T1>(agx::lerp(a, b, sqr / (2 * (sqr - t) + 1)));
626 }
627
637 template<typename T1, typename T2>
638 AGX_FORCE_INLINE T1 const logInterpolate(T1 const& a, T1 const& b, T2 const& t)
639 {
640 // Cap range at zero.
641 T1 lower = std::max(a, (T1)0);
642 T1 upper = std::max(b, (T1)0);
643
644 if (t >= 1)
645 return upper;
646 if (t <= 0)
647 return lower;
648
649 // When we use pow, we cannot use 0 as a base.
650 // We will cap the range at the smallest possible value we can represent.
651 lower = std::max(a, (T1)std::numeric_limits<T1>::min());
652 upper = std::max(b, (T1)std::numeric_limits<T1>::min());
653
654 return (T1)(std::pow(upper, t) * std::pow(lower, 1 - t));
655 }
656
662 template<typename T>
664 {
665 static const agx::UInt32 multiplyDeBruijnBitPosition2[ 32 ] =
666 {
667 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
668 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
669 };
670
671 return multiplyDeBruijnBitPosition2[ ( (unsigned int)value * 0x077CB531U ) >> 27 ];
672 }
673
686 template<typename T>
688 {
689 if (n == 0)
690 return 0;
691
692 agx::UInt8 msb = 0;
693 n = T(n / 2);
694 while (n != 0) {
695 n = T(n / 2);
696 msb++;
697 }
698
699 return msb;
700 }
701
702
703} // namespace agx
#define INT_IS_NAN(T)
Definition: Math.h:200
#define INT_IS_INF(T)
Definition: Math.h:206
#define UINT_ABSOLUTE(T)
Definition: Math.h:218
#define INT_IS_FINITE(T)
Definition: Math.h:212
#define INT_EQUALS_ZERO(T)
Definition: Math.h:194
#define AGXCORE_EXPORT
T rand()
Returns random number between minValue and maxValue (from constructor).
Definition: Random.h:144
#define agxAssert(expr)
Definition: debug.h:143
#define AGX_FORCE_INLINE
Definition: macros.h:58
The agx namespace contains the dynamics/math part of the AGX Dynamics API.
static constexpr Real PI_4
Definition: Math.h:65
uint16_t UInt16
Definition: Integer.h:31
int32_t Int32
Definition: Integer.h:37
T signedSquare(T v)
Definition: Math.h:342
T sign(T v)
Definition: Math.h:328
static constexpr Real GRAVITY_ACCELERATION
Definition: Math.h:52
bool isPowerOfTwo(T value)
Definition: Math.h:408
AGXCORE_EXPORT agx::UniformInt32Generator & getRandGenerator()
T absolute(T v)
return the absolute value.
Definition: Math.h:291
bool isEven(T val)
Definition: Math.h:84
uint32_t UInt32
Definition: Integer.h:32
T align_ceil(T value, T alignment)
Definition: Math.h:466
T1 const logInterpolate(T1 const &a, T1 const &b, T2 const &t)
This function calculates a linear interpolation in a logarithmic space between two positive,...
Definition: Math.h:638
AGXCORE_EXPORT float strtof(const char *nptr, char **endptr)
strtod ignoring global locale
Int32 log2(size_t val)
Definition: Math.h:393
uint64_t UInt64
Definition: Integer.h:33
bool geq(double a, double b, double eps=(double) AGX_EQUIVALENT_EPSILON)
Definition: Math.h:381
int64_t Int64
Definition: Integer.h:38
bool isNaN(T v)
Definition: Math.h:303
AGXCORE_EXPORT const Real REAL_SQRT_EPSILON
T1 clamp(T1 v, T2 minimum, T3 maximum)
Definition: Math.h:318
AGXCORE_EXPORT int nextPrime(int n)
AGXCORE_EXPORT Real normalizedAngle(Real angle, bool positiveRange=false)
Normalize an angle.
static constexpr Real RAD_TO_DEG
Definition: Math.h:70
T square(T v)
Definition: Math.h:335
Real sinc(Real x, Real nearZero=Real(1E-4))
Sinc function.
Definition: Math.h:93
constexpr Real radiansToDegrees(Real angle)
Definition: Math.h:354
Vec3T< T > min(const Vec3T< T > &lhs, const Vec3T< T > &rhs)
Definition: Vec3Template.h:861
AGXPHYSICS_EXPORT agx::Bool equalsZero(const agx::AddedMassInteraction::Matrix6x6 &matrix, agx::Real eps=agx::RealEpsilon)
int irandom(int min, int max)
Definition: Math.h:548
T align_ceil2(T value, T alignment)
Definition: Math.h:505
bool relativelyEquivalent(float lhs, float rhs, float epsilon=(float) AGX_EQUIVALENT_EPSILON)
Compare two values for relative equality.
Definition: Math.h:165
Vec3T< T > max(const Vec3T< T > &lhs, const Vec3T< T > &rhs)
Definition: Vec3Template.h:855
T random(T min, T max)
Definition: Math.h:555
bool _equivalent(T lhs, T rhs, T epsilon=T(AGX_EQUIVALENT_EPSILON))
Compare two values for equality.
Definition: Math.h:111
static constexpr Real PI_2
Definition: Math.h:64
bool _relativelyEquivalent(T lhs, T rhs, T relativeEpsilon=T(AGX_EQUIVALENT_EPSILON))
Compare two values for relative equality.
Definition: Math.h:154
static constexpr Real PI
Definition: Math.h:63
UInt32 alignPowerOfTwo(UInt32 value)
Definition: Math.h:413
agx::UInt8 highestBitToIndex(T n)
Definition: Math.h:687
bool isInf(T v)
Definition: Math.h:297
T1 const lerp(T1 const &a, T1 const &b, T2 t)
Linearly interpolate from a to b using t = {0..1}.
Definition: Math.h:590
static constexpr Real DEG_TO_RAD
Definition: Math.h:69
constexpr Real degreesToRadians(Real angle)
Definition: Math.h:348
bool isAligned(T value, T alignment)
Definition: Math.h:493
double Real
Definition: Real.h:42
uint8_t UInt8
Definition: Integer.h:30
Real computeVolume(const T &a, const T &b, const T &c, const T &d)
a, b, c, d sides of the tetrahedron
Definition: Math.h:571
bool leq(double a, double b, double eps=(double) AGX_EQUIVALENT_EPSILON)
Definition: Math.h:369
const Real Infinity
Definition: Math.h:72
static constexpr Real AGX_EQUIVALENT_EPSILON
Definition: Math.h:57
int8_t Int8
Definition: Integer.h:35
T inverse(const T &value)
Definition: Math.h:78
AGXCORE_EXPORT double strtod(const char *nptr, char **endptr)
strtod ignoring global locale
T1 const parametricBlend(T1 const &a, T1 const &b, T2 t)
Smooth interpolation from a to b using t = {0..1} The value returned will follow a ramp in/out and a ...
Definition: Math.h:617
int16_t Int16
Definition: Integer.h:36
T align_floor(T value, T alignment)
Definition: Math.h:480
bool isFinite(T v)
Definition: Math.h:309
T align_floor2(T value, T alignment)
Definition: Math.h:519
AGXPHYSICS_EXPORT agx::Bool equivalent(const agx::AddedMassInteraction::Matrix6x6 &lhs, const agx::AddedMassInteraction::Matrix6x6 &rhs, agx::Real eps=agx::RealEpsilon)
agx::UInt32 pow2Exponent(T value)
Finds and returns n given value = 2^n.
Definition: Math.h:663