summaryrefslogtreecommitdiff
path: root/core/math/math_funcs.h
diff options
context:
space:
mode:
Diffstat (limited to 'core/math/math_funcs.h')
-rw-r--r--core/math/math_funcs.h249
1 files changed, 115 insertions, 134 deletions
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index ae461eda2e..3e02ac0bb8 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -29,13 +29,13 @@
#ifndef MATH_FUNCS_H
#define MATH_FUNCS_H
-#include "typedefs.h"
#include "math_defs.h"
#include "pcg.h"
+#include "typedefs.h"
-#include <math.h>
#include <float.h>
-
+#include <math.h>
+
#define Math_PI 3.14159265358979323846
#define Math_SQRT12 0.7071067811865475244008443621048490
#define Math_LN2 0.693147180559945309417
@@ -50,10 +50,9 @@ public:
Math() {} // useless to instance
enum {
- RANDOM_MAX=4294967295L
+ RANDOM_MAX = 4294967295L
};
-
static _ALWAYS_INLINE_ double sin(double p_x) { return ::sin(p_x); }
static _ALWAYS_INLINE_ float sin(float p_x) { return ::sinf(p_x); }
@@ -81,14 +80,14 @@ public:
static _ALWAYS_INLINE_ double atan(double p_x) { return ::atan(p_x); }
static _ALWAYS_INLINE_ float atan(float p_x) { return ::atanf(p_x); }
- static _ALWAYS_INLINE_ double atan2(double p_y, double p_x) { return ::atan2(p_y,p_x); }
- static _ALWAYS_INLINE_ float atan2(float p_y, float p_x) { return ::atan2f(p_y,p_x); }
+ static _ALWAYS_INLINE_ double atan2(double p_y, double p_x) { return ::atan2(p_y, p_x); }
+ static _ALWAYS_INLINE_ float atan2(float p_y, float p_x) { return ::atan2f(p_y, p_x); }
static _ALWAYS_INLINE_ double sqrt(double p_x) { return ::sqrt(p_x); }
static _ALWAYS_INLINE_ float sqrt(float p_x) { return ::sqrtf(p_x); }
- static _ALWAYS_INLINE_ double fmod(double p_x,double p_y) { return ::fmod(p_x,p_y); }
- static _ALWAYS_INLINE_ float fmod(float p_x,float p_y) { return ::fmodf(p_x,p_y); }
+ static _ALWAYS_INLINE_ double fmod(double p_x, double p_y) { return ::fmod(p_x, p_y); }
+ static _ALWAYS_INLINE_ float fmod(float p_x, float p_y) { return ::fmodf(p_x, p_y); }
static _ALWAYS_INLINE_ double floor(double p_x) { return ::floor(p_x); }
static _ALWAYS_INLINE_ float floor(float p_x) { return ::floorf(p_x); }
@@ -96,8 +95,8 @@ public:
static _ALWAYS_INLINE_ double ceil(double p_x) { return ::ceil(p_x); }
static _ALWAYS_INLINE_ float ceil(float p_x) { return ::ceilf(p_x); }
- static _ALWAYS_INLINE_ double pow(double p_x, double p_y) { return ::pow(p_x,p_y); }
- static _ALWAYS_INLINE_ float pow(float p_x, float p_y) { return ::powf(p_x,p_y); }
+ static _ALWAYS_INLINE_ double pow(double p_x, double p_y) { return ::pow(p_x, p_y); }
+ static _ALWAYS_INLINE_ float pow(float p_x, float p_y) { return ::powf(p_x, p_y); }
static _ALWAYS_INLINE_ double log(double p_x) { return ::log(p_x); }
static _ALWAYS_INLINE_ float log(float p_x) { return ::logf(p_x); }
@@ -105,59 +104,59 @@ public:
static _ALWAYS_INLINE_ double exp(double p_x) { return ::exp(p_x); }
static _ALWAYS_INLINE_ float exp(float p_x) { return ::expf(p_x); }
- static _ALWAYS_INLINE_ bool is_nan(double p_val) { return (p_val!=p_val); }
- static _ALWAYS_INLINE_ bool is_nan(float p_val) { return (p_val!=p_val); }
+ static _ALWAYS_INLINE_ bool is_nan(double p_val) { return (p_val != p_val); }
+ static _ALWAYS_INLINE_ bool is_nan(float p_val) { return (p_val != p_val); }
static _ALWAYS_INLINE_ bool is_inf(double p_val) {
- #ifdef _MSC_VER
+#ifdef _MSC_VER
return !_finite(p_val);
- #else
+#else
return isinf(p_val);
- #endif
+#endif
}
-
+
static _ALWAYS_INLINE_ bool is_inf(float p_val) {
- #ifdef _MSC_VER
+#ifdef _MSC_VER
return !_finite(p_val);
- #else
+#else
return isinf(p_val);
- #endif
+#endif
}
-
+
static _ALWAYS_INLINE_ double abs(double g) { return absd(g); }
static _ALWAYS_INLINE_ float abs(float g) { return absf(g); }
static _ALWAYS_INLINE_ int abs(int g) { return g > 0 ? g : -g; }
- static _ALWAYS_INLINE_ double fposmod(double p_x,double p_y) { return (p_x>=0) ? Math::fmod(p_x,p_y) : p_y-Math::fmod(-p_x,p_y); }
- static _ALWAYS_INLINE_ float fposmod(float p_x,float p_y) { return (p_x>=0) ? Math::fmod(p_x,p_y) : p_y-Math::fmod(-p_x,p_y); }
+ static _ALWAYS_INLINE_ double fposmod(double p_x, double p_y) { return (p_x >= 0) ? Math::fmod(p_x, p_y) : p_y - Math::fmod(-p_x, p_y); }
+ static _ALWAYS_INLINE_ float fposmod(float p_x, float p_y) { return (p_x >= 0) ? Math::fmod(p_x, p_y) : p_y - Math::fmod(-p_x, p_y); }
- static _ALWAYS_INLINE_ double deg2rad(double p_y) { return p_y*Math_PI/180.0; }
- static _ALWAYS_INLINE_ float deg2rad(float p_y) { return p_y*Math_PI/180.0; }
+ static _ALWAYS_INLINE_ double deg2rad(double p_y) { return p_y * Math_PI / 180.0; }
+ static _ALWAYS_INLINE_ float deg2rad(float p_y) { return p_y * Math_PI / 180.0; }
- static _ALWAYS_INLINE_ double rad2deg(double p_y) { return p_y*180.0/Math_PI; }
- static _ALWAYS_INLINE_ float rad2deg(float p_y) { return p_y*180.0/Math_PI; }
+ static _ALWAYS_INLINE_ double rad2deg(double p_y) { return p_y * 180.0 / Math_PI; }
+ static _ALWAYS_INLINE_ float rad2deg(float p_y) { return p_y * 180.0 / Math_PI; }
- static _ALWAYS_INLINE_ double lerp(double a, double b, double c) { return a+(b-a)*c; }
- static _ALWAYS_INLINE_ float lerp(float a, float b, float c) { return a+(b-a)*c; }
+ static _ALWAYS_INLINE_ double lerp(double a, double b, double c) { return a + (b - a) * c; }
+ static _ALWAYS_INLINE_ float lerp(float a, float b, float c) { return a + (b - a) * c; }
- static _ALWAYS_INLINE_ double linear2db(double p_linear) { return Math::log( p_linear ) * 8.6858896380650365530225783783321; }
- static _ALWAYS_INLINE_ float linear2db(float p_linear) { return Math::log( p_linear ) * 8.6858896380650365530225783783321; }
+ static _ALWAYS_INLINE_ double linear2db(double p_linear) { return Math::log(p_linear) * 8.6858896380650365530225783783321; }
+ static _ALWAYS_INLINE_ float linear2db(float p_linear) { return Math::log(p_linear) * 8.6858896380650365530225783783321; }
- static _ALWAYS_INLINE_ double db2linear(double p_db) { return Math::exp( p_db * 0.11512925464970228420089957273422 ); }
- static _ALWAYS_INLINE_ float db2linear(float p_db) { return Math::exp( p_db * 0.11512925464970228420089957273422 ); }
+ static _ALWAYS_INLINE_ double db2linear(double p_db) { return Math::exp(p_db * 0.11512925464970228420089957273422); }
+ static _ALWAYS_INLINE_ float db2linear(float p_db) { return Math::exp(p_db * 0.11512925464970228420089957273422); }
- static _ALWAYS_INLINE_ double round(double p_val) { return (p_val>=0) ? Math::floor(p_val+0.5) : -Math::floor(-p_val+0.5); }
- static _ALWAYS_INLINE_ float round(float p_val) { return (p_val>=0) ? Math::floor(p_val+0.5) : -Math::floor(-p_val+0.5); }
+ static _ALWAYS_INLINE_ double round(double p_val) { return (p_val >= 0) ? Math::floor(p_val + 0.5) : -Math::floor(-p_val + 0.5); }
+ static _ALWAYS_INLINE_ float round(float p_val) { return (p_val >= 0) ? Math::floor(p_val + 0.5) : -Math::floor(-p_val + 0.5); }
// double only, as these functions are mainly used by the editor and not performance-critical,
static double ease(double p_x, double p_c);
static int step_decimals(double p_step);
- static double stepify(double p_value,double p_step);
- static double dectime(double p_value,double p_amount, double p_step);
+ static double stepify(double p_value, double p_step);
+ static double dectime(double p_value, double p_amount, double p_step);
static uint32_t larger_prime(uint32_t p_val);
- static void seed(uint64_t x=0);
+ static void seed(uint64_t x = 0);
static void randomize();
static uint32_t rand_from_seed(uint64_t *seed);
static uint32_t rand();
@@ -168,17 +167,15 @@ public:
static float random(float from, float to);
static real_t random(int from, int to) { return (real_t)random((real_t)from, (real_t)to); }
-
static _ALWAYS_INLINE_ bool isequal_approx(real_t a, real_t b) {
// TODO: Comparing floats for approximate-equality is non-trivial.
// Using epsilon should cover the typical cases in Godot (where a == b is used to compare two reals), such as matrix and vector comparison operators.
// A proper implementation in terms of ULPs should eventually replace the contents of this function.
// See https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ for details.
- return abs(a-b) < CMP_EPSILON;
+ return abs(a - b) < CMP_EPSILON;
}
-
static _ALWAYS_INLINE_ float absf(float g) {
union {
@@ -186,8 +183,8 @@ public:
uint32_t i;
} u;
- u.f=g;
- u.i&=2147483647u;
+ u.f = g;
+ u.i &= 2147483647u;
return u.f;
}
@@ -197,8 +194,8 @@ public:
double d;
uint64_t i;
} u;
- u.d=g;
- u.i&=(uint64_t)9223372036854775807ll;
+ u.d = g;
+ u.i &= (uint64_t)9223372036854775807ll;
return u.d;
}
@@ -208,11 +205,10 @@ public:
static int b;
#if (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0603) || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP // windows 8 phone?
- b = (int)((a>0.0) ? (a + 0.5):(a -0.5));
+ b = (int)((a > 0.0) ? (a + 0.5) : (a - 0.5));
#elif defined(_MSC_VER) && _MSC_VER < 1800
- __asm fld a
- __asm fistp b
+ __asm fld a __asm fistp b
/*#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) )
// use AT&T inline assembly style, document that
// we use memory as output (=m) and input (m)
@@ -223,12 +219,11 @@ public:
: "m" (a));*/
#else
- b=lrintf(a); //assuming everything but msvc 2012 or earlier has lrint
+ b = lrintf(a); //assuming everything but msvc 2012 or earlier has lrint
#endif
- return b;
+ return b;
}
-
#if defined(__GNUC__)
static _ALWAYS_INLINE_ int64_t dtoll(double p_double) { return (int64_t)p_double; } ///@TODO OPTIMIZE
@@ -239,37 +234,35 @@ public:
static _ALWAYS_INLINE_ int64_t dtoll(float p_float) { return (int64_t)p_float; } ///@TODO OPTIMIZE and rename
#endif
-
- static _ALWAYS_INLINE_ uint32_t halfbits_to_floatbits(uint16_t h)
- {
- uint16_t h_exp, h_sig;
- uint32_t f_sgn, f_exp, f_sig;
-
- h_exp = (h&0x7c00u);
- f_sgn = ((uint32_t)h&0x8000u) << 16;
- switch (h_exp) {
- case 0x0000u: /* 0 or subnormal */
- h_sig = (h&0x03ffu);
- /* Signed zero */
- if (h_sig == 0) {
- return f_sgn;
- }
- /* Subnormal */
- h_sig <<= 1;
- while ((h_sig&0x0400u) == 0) {
- h_sig <<= 1;
- h_exp++;
- }
- f_exp = ((uint32_t)(127 - 15 - h_exp)) << 23;
- f_sig = ((uint32_t)(h_sig&0x03ffu)) << 13;
- return f_sgn + f_exp + f_sig;
- case 0x7c00u: /* inf or NaN */
- /* All-ones exponent and a copy of the significand */
- return f_sgn + 0x7f800000u + (((uint32_t)(h&0x03ffu)) << 13);
- default: /* normalized */
- /* Just need to adjust the exponent and shift */
- return f_sgn + (((uint32_t)(h&0x7fffu) + 0x1c000u) << 13);
- }
+ static _ALWAYS_INLINE_ uint32_t halfbits_to_floatbits(uint16_t h) {
+ uint16_t h_exp, h_sig;
+ uint32_t f_sgn, f_exp, f_sig;
+
+ h_exp = (h & 0x7c00u);
+ f_sgn = ((uint32_t)h & 0x8000u) << 16;
+ switch (h_exp) {
+ case 0x0000u: /* 0 or subnormal */
+ h_sig = (h & 0x03ffu);
+ /* Signed zero */
+ if (h_sig == 0) {
+ return f_sgn;
+ }
+ /* Subnormal */
+ h_sig <<= 1;
+ while ((h_sig & 0x0400u) == 0) {
+ h_sig <<= 1;
+ h_exp++;
+ }
+ f_exp = ((uint32_t)(127 - 15 - h_exp)) << 23;
+ f_sig = ((uint32_t)(h_sig & 0x03ffu)) << 13;
+ return f_sgn + f_exp + f_sig;
+ case 0x7c00u: /* inf or NaN */
+ /* All-ones exponent and a copy of the significand */
+ return f_sgn + 0x7f800000u + (((uint32_t)(h & 0x03ffu)) << 13);
+ default: /* normalized */
+ /* Just need to adjust the exponent and shift */
+ return f_sgn + (((uint32_t)(h & 0x7fffu) + 0x1c000u) << 13);
+ }
}
static _ALWAYS_INLINE_ float halfptr_to_float(const uint16_t *h) {
@@ -279,70 +272,58 @@ public:
float f32;
} u;
- u.u32=halfbits_to_floatbits(*h);
+ u.u32 = halfbits_to_floatbits(*h);
return u.f32;
}
static _ALWAYS_INLINE_ uint16_t make_half_float(float f) {
- union {
- float fv;
- uint32_t ui;
- } ci;
- ci.fv=f;
-
- uint32_t x = ci.ui;
- uint32_t sign = (unsigned short)(x >> 31);
- uint32_t mantissa;
- uint32_t exp;
- uint16_t hf;
-
- // get mantissa
- mantissa = x & ((1 << 23) - 1);
- // get exponent bits
- exp = x & (0xFF << 23);
- if (exp >= 0x47800000)
- {
- // check if the original single precision float number is a NaN
- if (mantissa && (exp == (0xFF << 23)))
- {
- // we have a single precision NaN
- mantissa = (1 << 23) - 1;
- }
- else
- {
- // 16-bit half-float representation stores number as Inf
- mantissa = 0;
+ union {
+ float fv;
+ uint32_t ui;
+ } ci;
+ ci.fv = f;
+
+ uint32_t x = ci.ui;
+ uint32_t sign = (unsigned short)(x >> 31);
+ uint32_t mantissa;
+ uint32_t exp;
+ uint16_t hf;
+
+ // get mantissa
+ mantissa = x & ((1 << 23) - 1);
+ // get exponent bits
+ exp = x & (0xFF << 23);
+ if (exp >= 0x47800000) {
+ // check if the original single precision float number is a NaN
+ if (mantissa && (exp == (0xFF << 23))) {
+ // we have a single precision NaN
+ mantissa = (1 << 23) - 1;
+ } else {
+ // 16-bit half-float representation stores number as Inf
+ mantissa = 0;
+ }
+ hf = (((uint16_t)sign) << 15) | (uint16_t)((0x1F << 10)) |
+ (uint16_t)(mantissa >> 13);
}
- hf = (((uint16_t)sign) << 15) | (uint16_t)((0x1F << 10)) |
- (uint16_t)(mantissa >> 13);
- }
- // check if exponent is <= -15
- else if (exp <= 0x38000000)
- {
-
- /*// store a denorm half-float value or zero
+ // check if exponent is <= -15
+ else if (exp <= 0x38000000) {
+
+ /*// store a denorm half-float value or zero
exp = (0x38000000 - exp) >> 23;
mantissa >>= (14 + exp);
hf = (((uint16_t)sign) << 15) | (uint16_t)(mantissa);
*/
- hf=0; //denormals do not work for 3D, convert to zero
- }
- else
- {
- hf = (((uint16_t)sign) << 15) |
- (uint16_t)((exp - 0x38000000) >> 13) |
- (uint16_t)(mantissa >> 13);
- }
-
- return hf;
- }
-
-
+ hf = 0; //denormals do not work for 3D, convert to zero
+ } else {
+ hf = (((uint16_t)sign) << 15) |
+ (uint16_t)((exp - 0x38000000) >> 13) |
+ (uint16_t)(mantissa >> 13);
+ }
+ return hf;
+ }
};
-
-
#endif // MATH_FUNCS_H