|
@@ -38,20 +38,6 @@
|
|
|
#include <cmath>
|
|
|
|
|
|
namespace godot {
|
|
|
-namespace Math {
|
|
|
-
|
|
|
-// This epsilon should match the one used by Godot for consistency.
|
|
|
-// Using `f` when `real_t` is float.
|
|
|
-#define CMP_EPSILON 0.00001f
|
|
|
-#define CMP_EPSILON2 (CMP_EPSILON * CMP_EPSILON)
|
|
|
-
|
|
|
-// This epsilon is for values related to a unit size (scalar or vector len).
|
|
|
-#ifdef PRECISE_MATH_CHECKS
|
|
|
-#define UNIT_EPSILON 0.00001
|
|
|
-#else
|
|
|
-// Tolerate some more floating point error normally.
|
|
|
-#define UNIT_EPSILON 0.001
|
|
|
-#endif
|
|
|
|
|
|
#define Math_SQRT12 0.7071067811865475244008443621048490
|
|
|
#define Math_SQRT2 1.4142135623730950488016887242
|
|
@@ -62,32 +48,174 @@ namespace Math {
|
|
|
#define Math_INF INFINITY
|
|
|
#define Math_NAN NAN
|
|
|
|
|
|
-// Windows badly defines a lot of stuff we'll never use. Undefine it.
|
|
|
-#ifdef _WIN32
|
|
|
-#undef MIN // override standard definition
|
|
|
-#undef MAX // override standard definition
|
|
|
-#undef CLAMP // override standard definition
|
|
|
-#endif
|
|
|
+// Make room for our constexpr's below by overriding potential system-specific macros.
|
|
|
+#undef ABS
|
|
|
+#undef SIGN
|
|
|
+#undef MIN
|
|
|
+#undef MAX
|
|
|
+#undef CLAMP
|
|
|
|
|
|
// Generic ABS function, for math uses please use Math::abs.
|
|
|
-#ifndef ABS
|
|
|
-#define ABS(m_v) (((m_v) < 0) ? (-(m_v)) : (m_v))
|
|
|
-#endif
|
|
|
+template <typename T>
|
|
|
+constexpr T ABS(T m_v) {
|
|
|
+ return m_v < 0 ? -m_v : m_v;
|
|
|
+}
|
|
|
|
|
|
-#ifndef SIGN
|
|
|
-#define SIGN(m_v) (((m_v) == 0) ? (0.0) : (((m_v) < 0) ? (-1.0) : (+1.0)))
|
|
|
-#endif
|
|
|
+template <typename T>
|
|
|
+constexpr const T SIGN(const T m_v) {
|
|
|
+ return m_v == 0 ? 0.0f : (m_v < 0 ? -1.0f : +1.0f);
|
|
|
+}
|
|
|
|
|
|
-#ifndef MIN
|
|
|
-#define MIN(m_a, m_b) (((m_a) < (m_b)) ? (m_a) : (m_b))
|
|
|
-#endif
|
|
|
+template <typename T, typename T2>
|
|
|
+constexpr auto MIN(const T m_a, const T2 m_b) {
|
|
|
+ return m_a < m_b ? m_a : m_b;
|
|
|
+}
|
|
|
+
|
|
|
+template <typename T, typename T2>
|
|
|
+constexpr auto MAX(const T m_a, const T2 m_b) {
|
|
|
+ return m_a > m_b ? m_a : m_b;
|
|
|
+}
|
|
|
+
|
|
|
+template <typename T, typename T2, typename T3>
|
|
|
+constexpr auto CLAMP(const T m_a, const T2 m_min, const T3 m_max) {
|
|
|
+ return m_a < m_min ? m_min : (m_a > m_max ? m_max : m_a);
|
|
|
+}
|
|
|
+
|
|
|
+// Generic swap template.
|
|
|
+#ifndef SWAP
|
|
|
+#define SWAP(m_x, m_y) __swap_tmpl((m_x), (m_y))
|
|
|
+template <class T>
|
|
|
+inline void __swap_tmpl(T &x, T &y) {
|
|
|
+ T aux = x;
|
|
|
+ x = y;
|
|
|
+ y = aux;
|
|
|
+}
|
|
|
+#endif // SWAP
|
|
|
+
|
|
|
+/* Functions to handle powers of 2 and shifting. */
|
|
|
+
|
|
|
+// Function to find the next power of 2 to an integer.
|
|
|
+static _FORCE_INLINE_ unsigned int next_power_of_2(unsigned int x) {
|
|
|
+ if (x == 0) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ --x;
|
|
|
+ x |= x >> 1;
|
|
|
+ x |= x >> 2;
|
|
|
+ x |= x >> 4;
|
|
|
+ x |= x >> 8;
|
|
|
+ x |= x >> 16;
|
|
|
+
|
|
|
+ return ++x;
|
|
|
+}
|
|
|
+
|
|
|
+// Function to find the previous power of 2 to an integer.
|
|
|
+static _FORCE_INLINE_ unsigned int previous_power_of_2(unsigned int x) {
|
|
|
+ x |= x >> 1;
|
|
|
+ x |= x >> 2;
|
|
|
+ x |= x >> 4;
|
|
|
+ x |= x >> 8;
|
|
|
+ x |= x >> 16;
|
|
|
+ return x - (x >> 1);
|
|
|
+}
|
|
|
+
|
|
|
+// Function to find the closest power of 2 to an integer.
|
|
|
+static _FORCE_INLINE_ unsigned int closest_power_of_2(unsigned int x) {
|
|
|
+ unsigned int nx = next_power_of_2(x);
|
|
|
+ unsigned int px = previous_power_of_2(x);
|
|
|
+ return (nx - x) > (x - px) ? px : nx;
|
|
|
+}
|
|
|
+
|
|
|
+// Get a shift value from a power of 2.
|
|
|
+static inline int get_shift_from_power_of_2(unsigned int p_bits) {
|
|
|
+ for (unsigned int i = 0; i < 32; i++) {
|
|
|
+ if (p_bits == (unsigned int)(1 << i)) {
|
|
|
+ return i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|
|
|
+template <class T>
|
|
|
+static _FORCE_INLINE_ T nearest_power_of_2_templated(T x) {
|
|
|
+ --x;
|
|
|
+
|
|
|
+ // The number of operations on x is the base two logarithm
|
|
|
+ // of the number of bits in the type. Add three to account
|
|
|
+ // for sizeof(T) being in bytes.
|
|
|
+ size_t num = get_shift_from_power_of_2(sizeof(T)) + 3;
|
|
|
+
|
|
|
+ // If the compiler is smart, it unrolls this loop.
|
|
|
+ // If it's dumb, this is a bit slow.
|
|
|
+ for (size_t i = 0; i < num; i++) {
|
|
|
+ x |= x >> (1 << i);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ++x;
|
|
|
+}
|
|
|
+
|
|
|
+// Function to find the nearest (bigger) power of 2 to an integer.
|
|
|
+static inline unsigned int nearest_shift(unsigned int p_number) {
|
|
|
+ for (int i = 30; i >= 0; i--) {
|
|
|
+ if (p_number & (1 << i)) {
|
|
|
+ return i + 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+// constexpr function to find the floored log2 of a number
|
|
|
+template <typename T>
|
|
|
+constexpr T floor_log2(T x) {
|
|
|
+ return x < 2 ? x : 1 + floor_log2(x >> 1);
|
|
|
+}
|
|
|
+
|
|
|
+// Get the number of bits needed to represent the number.
|
|
|
+// IE, if you pass in 8, you will get 4.
|
|
|
+// If you want to know how many bits are needed to store 8 values however, pass in (8 - 1).
|
|
|
+template <typename T>
|
|
|
+constexpr T get_num_bits(T x) {
|
|
|
+ return floor_log2(x);
|
|
|
+}
|
|
|
+
|
|
|
+// Swap 16, 32 and 64 bits value for endianness.
|
|
|
+#if defined(__GNUC__)
|
|
|
+#define BSWAP16(x) __builtin_bswap16(x)
|
|
|
+#define BSWAP32(x) __builtin_bswap32(x)
|
|
|
+#define BSWAP64(x) __builtin_bswap64(x)
|
|
|
+#else
|
|
|
+static inline uint16_t BSWAP16(uint16_t x) {
|
|
|
+ return (x >> 8) | (x << 8);
|
|
|
+}
|
|
|
+
|
|
|
+static inline uint32_t BSWAP32(uint32_t x) {
|
|
|
+ return ((x << 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x >> 24));
|
|
|
+}
|
|
|
|
|
|
-#ifndef MAX
|
|
|
-#define MAX(m_a, m_b) (((m_a) > (m_b)) ? (m_a) : (m_b))
|
|
|
+static inline uint64_t BSWAP64(uint64_t x) {
|
|
|
+ x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32;
|
|
|
+ x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16;
|
|
|
+ x = (x & 0x00FF00FF00FF00FF) << 8 | (x & 0xFF00FF00FF00FF00) >> 8;
|
|
|
+ return x;
|
|
|
+}
|
|
|
#endif
|
|
|
|
|
|
-#ifndef CLAMP
|
|
|
-#define CLAMP(m_a, m_min, m_max) (((m_a) < (m_min)) ? (m_min) : (((m_a) > (m_max)) ? m_max : m_a))
|
|
|
+namespace Math {
|
|
|
+
|
|
|
+// This epsilon should match the one used by Godot for consistency.
|
|
|
+// Using `f` when `real_t` is float.
|
|
|
+#define CMP_EPSILON 0.00001f
|
|
|
+#define CMP_EPSILON2 (CMP_EPSILON * CMP_EPSILON)
|
|
|
+
|
|
|
+// This epsilon is for values related to a unit size (scalar or vector len).
|
|
|
+#ifdef PRECISE_MATH_CHECKS
|
|
|
+#define UNIT_EPSILON 0.00001
|
|
|
+#else
|
|
|
+// Tolerate some more floating point error normally.
|
|
|
+#define UNIT_EPSILON 0.001
|
|
|
#endif
|
|
|
|
|
|
// Functions reproduced as in Godot's source code `math_funcs.h`.
|
|
@@ -628,20 +756,6 @@ inline double pingpong(double value, double length) {
|
|
|
return (length != 0.0) ? abs(fract((value - length) / (length * 2.0)) * length * 2.0 - length) : 0.0;
|
|
|
}
|
|
|
|
|
|
-inline unsigned int next_power_of_2(unsigned int x) {
|
|
|
- if (x == 0)
|
|
|
- return 0;
|
|
|
-
|
|
|
- --x;
|
|
|
- x |= x >> 1;
|
|
|
- x |= x >> 2;
|
|
|
- x |= x >> 4;
|
|
|
- x |= x >> 8;
|
|
|
- x |= x >> 16;
|
|
|
-
|
|
|
- return ++x;
|
|
|
-}
|
|
|
-
|
|
|
// This function should be as fast as possible and rounding mode should not matter.
|
|
|
inline int fast_ftoi(float a) {
|
|
|
static int b;
|