mirror of
https://github.com/Relintai/codot.git
synced 2025-04-22 05:41:17 +02:00
Fix compile for math funcs.
This commit is contained in:
parent
db8c5ac829
commit
c6cec44559
@ -66,6 +66,8 @@ env_base["x86_libtheora_opt_vc"] = False
|
||||
# avoid issues when building with different versions of python out of the same directory
|
||||
env_base.SConsignFile(".sconsign{0}.dblite".format(pickle.HIGHEST_PROTOCOL))
|
||||
|
||||
env_base.Prepend(CPPPATH=["#"])
|
||||
|
||||
# Build options
|
||||
|
||||
env = env_base.Clone()
|
||||
|
93
core/error_list.h
Normal file
93
core/error_list.h
Normal file
@ -0,0 +1,93 @@
|
||||
/*************************************************************************/
|
||||
/* error_list.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef ERROR_LIST_H
|
||||
#define ERROR_LIST_H
|
||||
|
||||
/** Error List. Please never compare an error against FAILED
|
||||
* Either do result != OK , or !result. This way, Error fail
|
||||
* values can be more detailed in the future.
|
||||
*
|
||||
* This is a generic error list, mainly for organizing a language of returning errors.
|
||||
*/
|
||||
|
||||
enum Error {
|
||||
OK, // (0)
|
||||
FAILED, ///< Generic fail error
|
||||
ERR_UNAVAILABLE, ///< What is requested is unsupported/unavailable
|
||||
ERR_UNCONFIGURED, ///< The object being used hasn't been properly set up yet
|
||||
ERR_UNAUTHORIZED, ///< Missing credentials for requested resource
|
||||
ERR_PARAMETER_RANGE_ERROR, ///< Parameter given out of range (5)
|
||||
ERR_OUT_OF_MEMORY, ///< Out of memory
|
||||
ERR_FILE_NOT_FOUND,
|
||||
ERR_FILE_BAD_DRIVE,
|
||||
ERR_FILE_BAD_PATH,
|
||||
ERR_FILE_NO_PERMISSION, // (10)
|
||||
ERR_FILE_ALREADY_IN_USE,
|
||||
ERR_FILE_CANT_OPEN,
|
||||
ERR_FILE_CANT_WRITE,
|
||||
ERR_FILE_CANT_READ,
|
||||
ERR_FILE_UNRECOGNIZED, // (15)
|
||||
ERR_FILE_CORRUPT,
|
||||
ERR_FILE_MISSING_DEPENDENCIES,
|
||||
ERR_FILE_EOF,
|
||||
ERR_CANT_OPEN, ///< Can't open a resource/socket/file
|
||||
ERR_CANT_CREATE, // (20)
|
||||
ERR_QUERY_FAILED,
|
||||
ERR_ALREADY_IN_USE,
|
||||
ERR_LOCKED, ///< resource is locked
|
||||
ERR_TIMEOUT,
|
||||
ERR_CANT_CONNECT, // (25)
|
||||
ERR_CANT_RESOLVE,
|
||||
ERR_CONNECTION_ERROR,
|
||||
ERR_CANT_ACQUIRE_RESOURCE,
|
||||
ERR_CANT_FORK,
|
||||
ERR_INVALID_DATA, ///< Data passed is invalid (30)
|
||||
ERR_INVALID_PARAMETER, ///< Parameter passed is invalid
|
||||
ERR_ALREADY_EXISTS, ///< When adding, item already exists
|
||||
ERR_DOES_NOT_EXIST, ///< When retrieving/erasing, if item does not exist
|
||||
ERR_DATABASE_CANT_READ, ///< database is full
|
||||
ERR_DATABASE_CANT_WRITE, ///< database is full (35)
|
||||
ERR_COMPILATION_FAILED,
|
||||
ERR_METHOD_NOT_FOUND,
|
||||
ERR_LINK_FAILED,
|
||||
ERR_SCRIPT_FAILED,
|
||||
ERR_CYCLIC_LINK, // (40)
|
||||
ERR_INVALID_DECLARATION,
|
||||
ERR_DUPLICATE_SYMBOL,
|
||||
ERR_PARSE_ERROR,
|
||||
ERR_BUSY,
|
||||
ERR_SKIP, // (45)
|
||||
ERR_HELP, ///< user requested help!!
|
||||
ERR_BUG, ///< a bug in the software certainly happened, due to a double check failing or unexpected behavior.
|
||||
ERR_PRINTER_ON_FIRE, /// the parallel port printer is engulfed in flames
|
||||
};
|
||||
|
||||
#endif
|
59
core/int_types.h
Normal file
59
core/int_types.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*************************************************************************/
|
||||
/* int_types.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
typedef signed __int8 int8_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
#else
|
||||
|
||||
#ifdef NO_STDINT_H
|
||||
typedef unsigned char uint8_t;
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef signed short int16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef signed int int32_t;
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#endif
|
@ -30,34 +30,38 @@
|
||||
|
||||
#include "math_funcs.h"
|
||||
|
||||
#include "core/error_macros.h"
|
||||
//#include "core/error_macros.h"
|
||||
|
||||
RandomPCG Math::default_rand(RandomPCG::DEFAULT_SEED, RandomPCG::DEFAULT_INC);
|
||||
//RandomPCG math_default_rand(RandomPCG::DEFAULT_SEED, RandomPCG::DEFAULT_INC);
|
||||
|
||||
#define PHI 0x9e3779b9
|
||||
|
||||
uint32_t Math::rand_from_seed(uint64_t *seed) {
|
||||
uint32_t math_rand_from_seed(uint64_t *seed) {
|
||||
/*
|
||||
RandomPCG rng = RandomPCG(*seed, RandomPCG::DEFAULT_INC);
|
||||
uint32_t r = rng.rand();
|
||||
*seed = rng.get_seed();
|
||||
return r;
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Math::seed(uint64_t x) {
|
||||
default_rand.seed(x);
|
||||
void math_seed(uint64_t x) {
|
||||
//default_rand.seed(x);
|
||||
}
|
||||
|
||||
void Math::randomize() {
|
||||
default_rand.randomize();
|
||||
void math_randomize() {
|
||||
//default_rand.randomize();
|
||||
}
|
||||
|
||||
uint32_t Math::rand() {
|
||||
return default_rand.rand();
|
||||
uint32_t math_rand() {
|
||||
//return default_rand.rand();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Math::step_decimals(double p_step) {
|
||||
int math_step_decimals(double p_step) {
|
||||
static const int maxn = 10;
|
||||
static const double sd[maxn] = {
|
||||
static const double sd[10] = {
|
||||
0.9999, // somehow compensate for floating point error
|
||||
0.09999,
|
||||
0.009999,
|
||||
@ -70,7 +74,7 @@ int Math::step_decimals(double p_step) {
|
||||
0.0000000009999
|
||||
};
|
||||
|
||||
double abs = Math::abs(p_step);
|
||||
double abs = math_absd(p_step);
|
||||
double decs = abs - (int)abs; // Strip away integer part
|
||||
for (int i = 0; i < maxn; i++) {
|
||||
if (decs >= sd[i]) {
|
||||
@ -83,17 +87,17 @@ int Math::step_decimals(double p_step) {
|
||||
|
||||
// Only meant for editor usage in float ranges, where a step of 0
|
||||
// means that decimal digits should not be limited in String::num.
|
||||
int Math::range_step_decimals(double p_step) {
|
||||
int math_range_step_decimals(double p_step) {
|
||||
if (p_step < 0.0000000000001) {
|
||||
return 16; // Max value hardcoded in String::num
|
||||
}
|
||||
return step_decimals(p_step);
|
||||
}
|
||||
|
||||
double Math::dectime(double p_value, double p_amount, double p_step) {
|
||||
WARN_DEPRECATED_MSG("The `dectime()` function has been deprecated and will be removed in Godot 4.0. Use `move_toward()` instead.");
|
||||
double math_dectime(double p_value, double p_amount, double p_step) {
|
||||
//WARN_DEPRECATED_MSG("The `dectime()` function has been deprecated and will be removed in Godot 4.0. Use `move_toward()` instead.");
|
||||
double sgn = p_value < 0 ? -1.0 : 1.0;
|
||||
double val = Math::abs(p_value);
|
||||
double val = math_absd(p_value);
|
||||
val -= p_amount * p_step;
|
||||
if (val < 0.0) {
|
||||
val = 0.0;
|
||||
@ -101,7 +105,7 @@ double Math::dectime(double p_value, double p_amount, double p_step) {
|
||||
return val * sgn;
|
||||
}
|
||||
|
||||
double Math::ease(double p_x, double p_c) {
|
||||
double math_ease(double p_x, double p_c) {
|
||||
if (p_x < 0) {
|
||||
p_x = 0;
|
||||
} else if (p_x > 1.0) {
|
||||
@ -109,31 +113,38 @@ double Math::ease(double p_x, double p_c) {
|
||||
}
|
||||
if (p_c > 0) {
|
||||
if (p_c < 1.0) {
|
||||
return 1.0 - Math::pow(1.0 - p_x, 1.0 / p_c);
|
||||
return 1.0 - math_powd(1.0 - p_x, 1.0 / p_c);
|
||||
} else {
|
||||
return Math::pow(p_x, p_c);
|
||||
return math_powd(p_x, p_c);
|
||||
}
|
||||
} else if (p_c < 0) {
|
||||
//inout ease
|
||||
|
||||
if (p_x < 0.5) {
|
||||
return Math::pow(p_x * 2.0, -p_c) * 0.5;
|
||||
return math_powd(p_x * 2.0, -p_c) * 0.5;
|
||||
} else {
|
||||
return (1.0 - Math::pow(1.0 - (p_x - 0.5) * 2.0, -p_c)) * 0.5 + 0.5;
|
||||
return (1.0 - math_powd(1.0 - (p_x - 0.5) * 2.0, -p_c)) * 0.5 + 0.5;
|
||||
}
|
||||
} else {
|
||||
return 0; // no ease (raw)
|
||||
}
|
||||
}
|
||||
|
||||
double Math::stepify(double p_value, double p_step) {
|
||||
float math_stepifyf(float p_value, float p_step) {
|
||||
if (p_step != 0) {
|
||||
p_value = Math::floor(p_value / p_step + 0.5) * p_step;
|
||||
p_value = math_floorf(p_value / p_step + 0.5) * p_step;
|
||||
}
|
||||
return p_value;
|
||||
}
|
||||
|
||||
uint32_t Math::larger_prime(uint32_t p_val) {
|
||||
double math_stepifyd(double p_value, double p_step) {
|
||||
if (p_step != 0) {
|
||||
p_value = math_floord(p_value / p_step + 0.5) * p_step;
|
||||
}
|
||||
return p_value;
|
||||
}
|
||||
|
||||
uint32_t math_larger_prime(uint32_t p_val) {
|
||||
static const uint32_t primes[] = {
|
||||
5,
|
||||
13,
|
||||
@ -169,7 +180,7 @@ uint32_t Math::larger_prime(uint32_t p_val) {
|
||||
|
||||
int idx = 0;
|
||||
while (true) {
|
||||
ERR_FAIL_COND_V(primes[idx] == 0, 0);
|
||||
//ERR_FAIL_COND_V(primes[idx] == 0, 0);
|
||||
if (primes[idx] > p_val) {
|
||||
return primes[idx];
|
||||
}
|
||||
@ -177,10 +188,14 @@ uint32_t Math::larger_prime(uint32_t p_val) {
|
||||
}
|
||||
}
|
||||
|
||||
double Math::random(double from, double to) {
|
||||
return default_rand.random(from, to);
|
||||
double math_randomd(double from, double to) {
|
||||
//return default_rand.random(from, to);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float Math::random(float from, float to) {
|
||||
return default_rand.random(from, to);
|
||||
float math_randomf(float from, float to) {
|
||||
//return default_rand.random(from, to);
|
||||
|
||||
return 0;
|
||||
}
|
@ -32,466 +32,604 @@
|
||||
#define MATH_FUNCS_H
|
||||
|
||||
#include "core/math/math_defs.h"
|
||||
#include "core/math/random_pcg.h"
|
||||
#include "core/typedefs.h"
|
||||
|
||||
#include "thirdparty/misc/pcg.h"
|
||||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
class Math {
|
||||
static RandomPCG default_rand;
|
||||
// Not using 'RANDOM_MAX' to avoid conflict with system headers on some OSes (at least NetBSD).
|
||||
static const uint64_t MATH_RANDOM_32BIT_MAX = 0xFFFFFFFF;
|
||||
|
||||
public:
|
||||
Math() {} // useless to instance
|
||||
static _ALWAYS_INLINE_ double math_sind(double p_x) {
|
||||
return sin(p_x);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_sinf(float p_x) {
|
||||
return sinf(p_x);
|
||||
}
|
||||
|
||||
// Not using 'RANDOM_MAX' to avoid conflict with system headers on some OSes (at least NetBSD).
|
||||
static const uint64_t RANDOM_32BIT_MAX = 0xFFFFFFFF;
|
||||
static _ALWAYS_INLINE_ double math_cosd(double p_x) {
|
||||
return cos(p_x);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_cosf(float p_x) {
|
||||
return cosf(p_x);
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double sin(double p_x) { return ::sin(p_x); }
|
||||
static _ALWAYS_INLINE_ float sin(float p_x) { return ::sinf(p_x); }
|
||||
static _ALWAYS_INLINE_ double math_tand(double p_x) {
|
||||
return tan(p_x);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_tanf(float p_x) {
|
||||
return tanf(p_x);
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double cos(double p_x) { return ::cos(p_x); }
|
||||
static _ALWAYS_INLINE_ float cos(float p_x) { return ::cosf(p_x); }
|
||||
static _ALWAYS_INLINE_ double math_sinhd(double p_x) {
|
||||
return sinh(p_x);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_sinhf(float p_x) {
|
||||
return sinhf(p_x);
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double tan(double p_x) { return ::tan(p_x); }
|
||||
static _ALWAYS_INLINE_ float tan(float p_x) { return ::tanf(p_x); }
|
||||
static _ALWAYS_INLINE_ float math_sincf(float p_x) {
|
||||
return p_x == 0 ? 1 : sinf(p_x) / p_x;
|
||||
}
|
||||
static _ALWAYS_INLINE_ double math_sincd(double p_x) {
|
||||
return p_x == 0 ? 1 : sin(p_x) / p_x;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double sinh(double p_x) { return ::sinh(p_x); }
|
||||
static _ALWAYS_INLINE_ float sinh(float p_x) { return ::sinhf(p_x); }
|
||||
static _ALWAYS_INLINE_ float math_sincnf(float p_x) {
|
||||
return math_sincf((float)Math_PI * p_x);
|
||||
}
|
||||
static _ALWAYS_INLINE_ double math_sincnd(double p_x) {
|
||||
return math_sincd(Math_PI * p_x);
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ float sinc(float p_x) { return p_x == 0 ? 1 : ::sin(p_x) / p_x; }
|
||||
static _ALWAYS_INLINE_ double sinc(double p_x) { return p_x == 0 ? 1 : ::sin(p_x) / p_x; }
|
||||
static _ALWAYS_INLINE_ double math_coshd(double p_x) {
|
||||
return cosh(p_x);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_coshf(float p_x) {
|
||||
return coshf(p_x);
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ float sincn(float p_x) { return sinc((float)Math_PI * p_x); }
|
||||
static _ALWAYS_INLINE_ double sincn(double p_x) { return sinc(Math_PI * p_x); }
|
||||
static _ALWAYS_INLINE_ double math_tanhd(double p_x) {
|
||||
return tanh(p_x);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_tanhf(float p_x) {
|
||||
return tanhf(p_x);
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double cosh(double p_x) { return ::cosh(p_x); }
|
||||
static _ALWAYS_INLINE_ float cosh(float p_x) { return ::coshf(p_x); }
|
||||
static _ALWAYS_INLINE_ double math_asind(double p_x) {
|
||||
return asin(p_x);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_asinf(float p_x) {
|
||||
return asinf(p_x);
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double tanh(double p_x) { return ::tanh(p_x); }
|
||||
static _ALWAYS_INLINE_ float tanh(float p_x) { return ::tanhf(p_x); }
|
||||
static _ALWAYS_INLINE_ double math_acosd(double p_x) {
|
||||
return acos(p_x);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_acosf(float p_x) {
|
||||
return acosf(p_x);
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double asin(double p_x) { return ::asin(p_x); }
|
||||
static _ALWAYS_INLINE_ float asin(float p_x) { return ::asinf(p_x); }
|
||||
static _ALWAYS_INLINE_ double math_atand(double p_x) {
|
||||
return atan(p_x);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_atanf(float p_x) {
|
||||
return atanf(p_x);
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double acos(double p_x) { return ::acos(p_x); }
|
||||
static _ALWAYS_INLINE_ float acos(float p_x) { return ::acosf(p_x); }
|
||||
static _ALWAYS_INLINE_ double math_atan2d(double p_y, double p_x) {
|
||||
return atan2(p_y, p_x);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_atan2f(float p_y, float p_x) {
|
||||
return atan2f(p_y, p_x);
|
||||
}
|
||||
|
||||
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 math_sqrtd(double p_x) {
|
||||
return sqrt(p_x);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_sqrtf(float p_x) {
|
||||
return sqrtf(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 math_fmodd(double p_x, double p_y) {
|
||||
return fmod(p_x, p_y);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_fmodf(float p_x, float p_y) {
|
||||
return fmodf(p_x, p_y);
|
||||
}
|
||||
|
||||
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 math_floord(double p_x) {
|
||||
return floor(p_x);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_floorf(float p_x) {
|
||||
return floorf(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 math_ceild(double p_x) {
|
||||
return ceil(p_x);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_ceilf(float p_x) {
|
||||
return ceilf(p_x);
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double floor(double p_x) { return ::floor(p_x); }
|
||||
static _ALWAYS_INLINE_ float floor(float p_x) { return ::floorf(p_x); }
|
||||
static _ALWAYS_INLINE_ double math_powd(double p_x, double p_y) {
|
||||
return pow(p_x, p_y);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_powf(float p_x, float p_y) {
|
||||
return powf(p_x, p_y);
|
||||
}
|
||||
|
||||
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 math_logd(double p_x) {
|
||||
return log(p_x);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_logf(float p_x) {
|
||||
return logf(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 math_expd(double p_x) {
|
||||
return exp(p_x);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_expf(float p_x) {
|
||||
return expf(p_x);
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double log(double p_x) { return ::log(p_x); }
|
||||
static _ALWAYS_INLINE_ float log(float p_x) { return ::logf(p_x); }
|
||||
|
||||
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) {
|
||||
static _ALWAYS_INLINE_ bool math_is_nand(double p_val) {
|
||||
#ifdef _MSC_VER
|
||||
return _isnan(p_val);
|
||||
return _isnan(p_val);
|
||||
#elif defined(__GNUC__) && __GNUC__ < 6
|
||||
union {
|
||||
uint64_t u;
|
||||
double f;
|
||||
} ieee754;
|
||||
ieee754.f = p_val;
|
||||
// (unsigned)(0x7ff0000000000001 >> 32) : 0x7ff00000
|
||||
return ((((unsigned)(ieee754.u >> 32) & 0x7fffffff) + ((unsigned)ieee754.u != 0)) > 0x7ff00000);
|
||||
union {
|
||||
uint64_t u;
|
||||
double f;
|
||||
} ieee754;
|
||||
ieee754.f = p_val;
|
||||
// (unsigned)(0x7ff0000000000001 >> 32) : 0x7ff00000
|
||||
return ((((unsigned)(ieee754.u >> 32) & 0x7fffffff) + ((unsigned)ieee754.u != 0)) > 0x7ff00000);
|
||||
#else
|
||||
return isnan(p_val);
|
||||
return isnan(p_val);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ bool is_nan(float p_val) {
|
||||
static _ALWAYS_INLINE_ bool math_is_nanf(float p_val) {
|
||||
#ifdef _MSC_VER
|
||||
return _isnan(p_val);
|
||||
return _isnan(p_val);
|
||||
#elif defined(__GNUC__) && __GNUC__ < 6
|
||||
union {
|
||||
uint32_t u;
|
||||
float f;
|
||||
} ieee754;
|
||||
ieee754.f = p_val;
|
||||
// -----------------------------------
|
||||
// (single-precision floating-point)
|
||||
// NaN : s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx
|
||||
// : (> 0x7f800000)
|
||||
// where,
|
||||
// s : sign
|
||||
// x : non-zero number
|
||||
// -----------------------------------
|
||||
return ((ieee754.u & 0x7fffffff) > 0x7f800000);
|
||||
union {
|
||||
uint32_t u;
|
||||
float f;
|
||||
} ieee754;
|
||||
ieee754.f = p_val;
|
||||
// -----------------------------------
|
||||
// (single-precision floating-point)
|
||||
// NaN : s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx
|
||||
// : (> 0x7f800000)
|
||||
// where,
|
||||
// s : sign
|
||||
// x : non-zero number
|
||||
// -----------------------------------
|
||||
return ((ieee754.u & 0x7fffffff) > 0x7f800000);
|
||||
#else
|
||||
return isnan(p_val);
|
||||
return isnan(p_val);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ bool is_inf(double p_val) {
|
||||
static _ALWAYS_INLINE_ bool math_is_infd(double p_val) {
|
||||
#ifdef _MSC_VER
|
||||
return !_finite(p_val);
|
||||
return !_finite(p_val);
|
||||
// use an inline implementation of isinf as a workaround for problematic libstdc++ versions from gcc 5.x era
|
||||
#elif defined(__GNUC__) && __GNUC__ < 6
|
||||
union {
|
||||
uint64_t u;
|
||||
double f;
|
||||
} ieee754;
|
||||
ieee754.f = p_val;
|
||||
return ((unsigned)(ieee754.u >> 32) & 0x7fffffff) == 0x7ff00000 &&
|
||||
((unsigned)ieee754.u == 0);
|
||||
union {
|
||||
uint64_t u;
|
||||
double f;
|
||||
} ieee754;
|
||||
ieee754.f = p_val;
|
||||
return ((unsigned)(ieee754.u >> 32) & 0x7fffffff) == 0x7ff00000 &&
|
||||
((unsigned)ieee754.u == 0);
|
||||
#else
|
||||
return isinf(p_val);
|
||||
return isinf(p_val);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ bool is_inf(float p_val) {
|
||||
static _ALWAYS_INLINE_ bool math_is_inff(float p_val) {
|
||||
#ifdef _MSC_VER
|
||||
return !_finite(p_val);
|
||||
return !_finite(p_val);
|
||||
// use an inline implementation of isinf as a workaround for problematic libstdc++ versions from gcc 5.x era
|
||||
#elif defined(__GNUC__) && __GNUC__ < 6
|
||||
union {
|
||||
uint32_t u;
|
||||
float f;
|
||||
} ieee754;
|
||||
ieee754.f = p_val;
|
||||
return (ieee754.u & 0x7fffffff) == 0x7f800000;
|
||||
union {
|
||||
uint32_t u;
|
||||
float f;
|
||||
} ieee754;
|
||||
ieee754.f = p_val;
|
||||
return (ieee754.u & 0x7fffffff) == 0x7f800000;
|
||||
#else
|
||||
return isinf(p_val);
|
||||
return isinf(p_val);
|
||||
#endif
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ float math_absf(float g) {
|
||||
union {
|
||||
float f;
|
||||
uint32_t i;
|
||||
} u;
|
||||
|
||||
u.f = g;
|
||||
u.i &= 2147483647u;
|
||||
return u.f;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double math_absd(double g) {
|
||||
union {
|
||||
double d;
|
||||
uint64_t i;
|
||||
} u;
|
||||
u.d = g;
|
||||
u.i &= (uint64_t)9223372036854775807ll;
|
||||
return u.d;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ int math_absi(int g) {
|
||||
return g > 0 ? g : -g;
|
||||
}
|
||||
static _ALWAYS_INLINE_ int64_t math_absi64(int64_t g) {
|
||||
return g > 0 ? g : -g;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double math_fposmodd(double p_x, double p_y) {
|
||||
double value = math_fmodd(p_x, p_y);
|
||||
if (((value < 0) && (p_y > 0)) || ((value > 0) && (p_y < 0))) {
|
||||
value += p_y;
|
||||
}
|
||||
|
||||
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_ int64_t abs(int64_t g) { return g > 0 ? g : -g; }
|
||||
|
||||
static _ALWAYS_INLINE_ double fposmod(double p_x, double p_y) {
|
||||
double value = Math::fmod(p_x, p_y);
|
||||
if (((value < 0) && (p_y > 0)) || ((value > 0) && (p_y < 0))) {
|
||||
value += p_y;
|
||||
}
|
||||
value += 0.0;
|
||||
return value;
|
||||
value += 0.0;
|
||||
return value;
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_fposmodf(float p_x, float p_y) {
|
||||
float value = math_fmodf(p_x, p_y);
|
||||
if (((value < 0) && (p_y > 0)) || ((value > 0) && (p_y < 0))) {
|
||||
value += p_y;
|
||||
}
|
||||
static _ALWAYS_INLINE_ float fposmod(float p_x, float p_y) {
|
||||
float value = Math::fmod(p_x, p_y);
|
||||
if (((value < 0) && (p_y > 0)) || ((value > 0) && (p_y < 0))) {
|
||||
value += p_y;
|
||||
}
|
||||
value += 0.0f;
|
||||
return value;
|
||||
value += 0.0f;
|
||||
return value;
|
||||
}
|
||||
static _ALWAYS_INLINE_ int64_t math_posmodi(int64_t p_x, int64_t p_y) {
|
||||
int64_t value = p_x % p_y;
|
||||
if (((value < 0) && (p_y > 0)) || ((value > 0) && (p_y < 0))) {
|
||||
value += p_y;
|
||||
}
|
||||
static _ALWAYS_INLINE_ int64_t posmod(int64_t p_x, int64_t p_y) {
|
||||
int64_t value = p_x % p_y;
|
||||
if (((value < 0) && (p_y > 0)) || ((value > 0) && (p_y < 0))) {
|
||||
value += p_y;
|
||||
}
|
||||
return value;
|
||||
return value;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double math_deg2radd(double p_y) {
|
||||
return p_y * Math_PI / 180.0;
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_deg2radf(float p_y) {
|
||||
return p_y * (float)(Math_PI / 180.0);
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double math_rad2degd(double p_y) {
|
||||
return p_y * 180.0 / Math_PI;
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_rad2degf(float p_y) {
|
||||
return p_y * (float)(180.0 / Math_PI);
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double math_lerpd(double p_from, double p_to, double p_weight) {
|
||||
return p_from + (p_to - p_from) * p_weight;
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_lerpf(float p_from, float p_to, float p_weight) {
|
||||
return p_from + (p_to - p_from) * p_weight;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double math_lerp_angled(double p_from, double p_to, double p_weight) {
|
||||
double difference = fmod(p_to - p_from, Math_TAU);
|
||||
double distance = fmod(2.0 * difference, Math_TAU) - difference;
|
||||
return p_from + distance * p_weight;
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_lerp_anglef(float p_from, float p_to, float p_weight) {
|
||||
float difference = fmodf(p_to - p_from, (float)Math_TAU);
|
||||
float distance = fmodf(2.0f * difference, (float)Math_TAU) - difference;
|
||||
return p_from + distance * p_weight;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double math_inverse_lerpd(double p_from, double p_to, double p_value) {
|
||||
return (p_value - p_from) / (p_to - p_from);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_inverse_lerpf(float p_from, float p_to, float p_value) {
|
||||
return (p_value - p_from) / (p_to - p_from);
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double math_range_lerpd(double p_value, double p_istart, double p_istop, double p_ostart, double p_ostop) {
|
||||
return math_lerpd(p_ostart, p_ostop, math_inverse_lerpd(p_istart, p_istop, p_value));
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_range_lerpf(float p_value, float p_istart, float p_istop, float p_ostart, float p_ostop) {
|
||||
return math_lerpf(p_ostart, p_ostop, math_inverse_lerpf(p_istart, p_istop, p_value));
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double math_linear2dbd(double p_linear) {
|
||||
return math_logd(p_linear) * 8.6858896380650365530225783783321;
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_linear2dbf(float p_linear) {
|
||||
return math_logf(p_linear) * (float)8.6858896380650365530225783783321;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double math_db2lineard(double p_db) {
|
||||
return math_expd(p_db * 0.11512925464970228420089957273422);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_db2linearf(float p_db) {
|
||||
return math_expf(p_db * (float)0.11512925464970228420089957273422);
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double math_roundd(double p_val) {
|
||||
return round(p_val);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_roundf(float p_val) {
|
||||
return roundf(p_val);
|
||||
}
|
||||
|
||||
// double only, as these functions are mainly used by the editor and not performance-critical,
|
||||
static double ease(double p_x, double p_c);
|
||||
int step_decimals(double p_step);
|
||||
static int range_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 uint32_t larger_prime(uint32_t p_val);
|
||||
|
||||
static void seed(uint64_t x);
|
||||
static void randomize();
|
||||
static uint32_t rand_from_seed(uint64_t *seed);
|
||||
uint32_t rand();
|
||||
static _ALWAYS_INLINE_ double randd() {
|
||||
return (double)rand() / (double)MATH_RANDOM_32BIT_MAX;
|
||||
}
|
||||
static _ALWAYS_INLINE_ float randf() {
|
||||
return (float)rand() / (float)MATH_RANDOM_32BIT_MAX;
|
||||
}
|
||||
|
||||
static double math_randomd(double from, double to);
|
||||
static float math_randomf(float from, float to);
|
||||
|
||||
static real_t math_randomr(int from, int to) {
|
||||
return (real_t)math_randomf((real_t)from, (real_t)to);
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ bool math_is_equal_approx_ratio(real_t a, real_t b) {
|
||||
// this is an approximate way to check that numbers are close, as a ratio of their average size
|
||||
// helps compare approximate numbers that may be very big or very small
|
||||
real_t diff = math_absf(a - b);
|
||||
if (diff == 0 || diff < CMP_EPSILON) {
|
||||
return true;
|
||||
}
|
||||
real_t avg_size = (math_absf(a) + math_absf(b)) / 2;
|
||||
diff /= avg_size;
|
||||
return diff < CMP_EPSILON;
|
||||
}
|
||||
|
||||
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 * (float)(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 * (float)(180.0 / Math_PI); }
|
||||
|
||||
static _ALWAYS_INLINE_ double lerp(double p_from, double p_to, double p_weight) { return p_from + (p_to - p_from) * p_weight; }
|
||||
static _ALWAYS_INLINE_ float lerp(float p_from, float p_to, float p_weight) { return p_from + (p_to - p_from) * p_weight; }
|
||||
|
||||
static _ALWAYS_INLINE_ double lerp_angle(double p_from, double p_to, double p_weight) {
|
||||
double difference = fmod(p_to - p_from, Math_TAU);
|
||||
double distance = fmod(2.0 * difference, Math_TAU) - difference;
|
||||
return p_from + distance * p_weight;
|
||||
static _ALWAYS_INLINE_ bool math_is_equal_approx_ratioe(real_t a, real_t b, real_t epsilon) {
|
||||
// this is an approximate way to check that numbers are close, as a ratio of their average size
|
||||
// helps compare approximate numbers that may be very big or very small
|
||||
real_t diff = math_absf(a - b);
|
||||
if (diff == 0 || diff < CMP_EPSILON) {
|
||||
return true;
|
||||
}
|
||||
static _ALWAYS_INLINE_ float lerp_angle(float p_from, float p_to, float p_weight) {
|
||||
float difference = fmod(p_to - p_from, (float)Math_TAU);
|
||||
float distance = fmod(2.0f * difference, (float)Math_TAU) - difference;
|
||||
return p_from + distance * p_weight;
|
||||
real_t avg_size = (math_absf(a) + math_absf(b)) / 2;
|
||||
diff /= avg_size;
|
||||
return diff < epsilon;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ bool math_is_equal_approx_ratioem(real_t a, real_t b, real_t epsilon, real_t min_epsilon) {
|
||||
// this is an approximate way to check that numbers are close, as a ratio of their average size
|
||||
// helps compare approximate numbers that may be very big or very small
|
||||
real_t diff = math_absf(a - b);
|
||||
if (diff == 0 || diff < min_epsilon) {
|
||||
return true;
|
||||
}
|
||||
real_t avg_size = (math_absf(a) + math_absf(b)) / 2;
|
||||
diff /= avg_size;
|
||||
return diff < epsilon;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double inverse_lerp(double p_from, double p_to, double p_value) { return (p_value - p_from) / (p_to - p_from); }
|
||||
static _ALWAYS_INLINE_ float inverse_lerp(float p_from, float p_to, float p_value) { return (p_value - p_from) / (p_to - p_from); }
|
||||
|
||||
static _ALWAYS_INLINE_ double range_lerp(double p_value, double p_istart, double p_istop, double p_ostart, double p_ostop) { return Math::lerp(p_ostart, p_ostop, Math::inverse_lerp(p_istart, p_istop, p_value)); }
|
||||
static _ALWAYS_INLINE_ float range_lerp(float p_value, float p_istart, float p_istop, float p_ostart, float p_ostop) { return Math::lerp(p_ostart, p_ostop, Math::inverse_lerp(p_istart, p_istop, p_value)); }
|
||||
|
||||
static _ALWAYS_INLINE_ double smoothstep(double p_from, double p_to, double p_s) {
|
||||
if (is_equal_approx(p_from, p_to)) {
|
||||
return p_from;
|
||||
}
|
||||
double s = CLAMP((p_s - p_from) / (p_to - p_from), 0.0, 1.0);
|
||||
return s * s * (3.0 - 2.0 * s);
|
||||
static _ALWAYS_INLINE_ bool math_is_equal_approxf(float a, float b) {
|
||||
// Check for exact equality first, required to handle "infinity" values.
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
static _ALWAYS_INLINE_ float smoothstep(float p_from, float p_to, float p_s) {
|
||||
if (is_equal_approx(p_from, p_to)) {
|
||||
return p_from;
|
||||
}
|
||||
float s = CLAMP((p_s - p_from) / (p_to - p_from), 0.0f, 1.0f);
|
||||
return s * s * (3.0f - 2.0f * s);
|
||||
// Then check for approximate equality.
|
||||
float tolerance = (float)CMP_EPSILON * math_absf(a);
|
||||
if (tolerance < (float)CMP_EPSILON) {
|
||||
tolerance = (float)CMP_EPSILON;
|
||||
}
|
||||
static _ALWAYS_INLINE_ double move_toward(double p_from, double p_to, double p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SGN(p_to - p_from) * p_delta; }
|
||||
static _ALWAYS_INLINE_ float move_toward(float p_from, float p_to, float p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SGN(p_to - p_from) * p_delta; }
|
||||
return math_absf(a - b) < tolerance;
|
||||
}
|
||||
|
||||
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) * (float)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 * (float)0.11512925464970228420089957273422); }
|
||||
|
||||
static _ALWAYS_INLINE_ double round(double p_val) { return ::round(p_val); }
|
||||
static _ALWAYS_INLINE_ float round(float p_val) { return ::roundf(p_val); }
|
||||
|
||||
static _ALWAYS_INLINE_ int64_t wrapi(int64_t value, int64_t min, int64_t max) {
|
||||
int64_t range = max - min;
|
||||
return range == 0 ? min : min + ((((value - min) % range) + range) % range);
|
||||
static _ALWAYS_INLINE_ bool math_is_equal_approxft(float a, float b, float tolerance) {
|
||||
// Check for exact equality first, required to handle "infinity" values.
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
static _ALWAYS_INLINE_ double wrapf(double value, double min, double max) {
|
||||
double range = max - min;
|
||||
return is_zero_approx(range) ? min : value - (range * Math::floor((value - min) / range));
|
||||
// Then check for approximate equality.
|
||||
return math_absf(a - b) < tolerance;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ bool math_is_zero_approxf(float s) {
|
||||
return math_absf(s) < (float)CMP_EPSILON;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ bool math_is_equal_approxd(double a, double b) {
|
||||
// Check for exact equality first, required to handle "infinity" values.
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
static _ALWAYS_INLINE_ float wrapf(float value, float min, float max) {
|
||||
float range = max - min;
|
||||
return is_zero_approx(range) ? min : value - (range * Math::floor((value - min) / range));
|
||||
// Then check for approximate equality.
|
||||
double tolerance = CMP_EPSILON * math_absd(a);
|
||||
if (tolerance < CMP_EPSILON) {
|
||||
tolerance = CMP_EPSILON;
|
||||
}
|
||||
return math_absd(a - b) < tolerance;
|
||||
}
|
||||
|
||||
// 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 int range_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 uint32_t larger_prime(uint32_t p_val);
|
||||
|
||||
static void seed(uint64_t x);
|
||||
static void randomize();
|
||||
static uint32_t rand_from_seed(uint64_t *seed);
|
||||
static uint32_t rand();
|
||||
static _ALWAYS_INLINE_ double randd() { return (double)rand() / (double)Math::RANDOM_32BIT_MAX; }
|
||||
static _ALWAYS_INLINE_ float randf() { return (float)rand() / (float)Math::RANDOM_32BIT_MAX; }
|
||||
|
||||
static double random(double from, double to);
|
||||
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 is_equal_approx_ratio(real_t a, real_t b, real_t epsilon = CMP_EPSILON, real_t min_epsilon = CMP_EPSILON) {
|
||||
// this is an approximate way to check that numbers are close, as a ratio of their average size
|
||||
// helps compare approximate numbers that may be very big or very small
|
||||
real_t diff = abs(a - b);
|
||||
if (diff == 0 || diff < min_epsilon) {
|
||||
return true;
|
||||
}
|
||||
real_t avg_size = (abs(a) + abs(b)) / 2;
|
||||
diff /= avg_size;
|
||||
return diff < epsilon;
|
||||
static _ALWAYS_INLINE_ bool math_is_equal_approxdt(double a, double b, double tolerance) {
|
||||
// Check for exact equality first, required to handle "infinity" values.
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
// Then check for approximate equality.
|
||||
return math_absd(a - b) < tolerance;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ bool is_equal_approx(float a, float b) {
|
||||
// Check for exact equality first, required to handle "infinity" values.
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
// Then check for approximate equality.
|
||||
float tolerance = (float)CMP_EPSILON * abs(a);
|
||||
if (tolerance < (float)CMP_EPSILON) {
|
||||
tolerance = (float)CMP_EPSILON;
|
||||
}
|
||||
return abs(a - b) < tolerance;
|
||||
static _ALWAYS_INLINE_ bool math_is_zero_approxd(double s) {
|
||||
return math_absd(s) < CMP_EPSILON;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double math_smoothstepd(double p_from, double p_to, double p_s) {
|
||||
if (math_is_equal_approxd(p_from, p_to)) {
|
||||
return p_from;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ bool is_equal_approx(float a, float b, float tolerance) {
|
||||
// Check for exact equality first, required to handle "infinity" values.
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
// Then check for approximate equality.
|
||||
return abs(a - b) < tolerance;
|
||||
double s = CLAMP((p_s - p_from) / (p_to - p_from), 0.0, 1.0);
|
||||
return s * s * (3.0 - 2.0 * s);
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_smoothstepf(float p_from, float p_to, float p_s) {
|
||||
if (math_is_equal_approxf(p_from, p_to)) {
|
||||
return p_from;
|
||||
}
|
||||
float s = CLAMP((p_s - p_from) / (p_to - p_from), 0.0f, 1.0f);
|
||||
return s * s * (3.0f - 2.0f * s);
|
||||
}
|
||||
static _ALWAYS_INLINE_ double math_move_towardd(double p_from, double p_to, double p_delta) {
|
||||
return math_absd(p_to - p_from) <= p_delta ? p_to : p_from + SGN(p_to - p_from) * p_delta;
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_move_towardf(float p_from, float p_to, float p_delta) {
|
||||
return math_absf(p_to - p_from) <= p_delta ? p_to : p_from + SGN(p_to - p_from) * p_delta;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ bool is_zero_approx(float s) {
|
||||
return abs(s) < (float)CMP_EPSILON;
|
||||
}
|
||||
static _ALWAYS_INLINE_ int64_t math_wrapi(int64_t value, int64_t min, int64_t max) {
|
||||
int64_t range = max - min;
|
||||
return range == 0 ? min : min + ((((value - min) % range) + range) % range);
|
||||
}
|
||||
static _ALWAYS_INLINE_ double math_wrapd(double value, double min, double max) {
|
||||
double range = max - min;
|
||||
return math_is_zero_approxd(range) ? min : value - (range * math_floord((value - min) / range));
|
||||
}
|
||||
static _ALWAYS_INLINE_ float math_wrapf(float value, float min, float max) {
|
||||
float range = max - min;
|
||||
return math_is_zero_approxf(range) ? min : value - (range * math_floorf((value - min) / range));
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ bool is_equal_approx(double a, double b) {
|
||||
// Check for exact equality first, required to handle "infinity" values.
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
// Then check for approximate equality.
|
||||
double tolerance = CMP_EPSILON * abs(a);
|
||||
if (tolerance < CMP_EPSILON) {
|
||||
tolerance = CMP_EPSILON;
|
||||
}
|
||||
return abs(a - b) < tolerance;
|
||||
}
|
||||
// This function should be as fast as possible and rounding mode should not matter.
|
||||
static _ALWAYS_INLINE_ int math_fast_ftoi(float a) {
|
||||
// Assuming every supported compiler has `lrint()`.
|
||||
return lrintf(a);
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ bool is_equal_approx(double a, double b, double tolerance) {
|
||||
// Check for exact equality first, required to handle "infinity" values.
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
// Then check for approximate equality.
|
||||
return abs(a - b) < tolerance;
|
||||
}
|
||||
static _ALWAYS_INLINE_ uint32_t math_halfbits_to_floatbits(uint16_t h) {
|
||||
uint16_t h_exp, h_sig;
|
||||
uint32_t f_sgn, f_exp, f_sig;
|
||||
|
||||
static _ALWAYS_INLINE_ bool is_zero_approx(double s) {
|
||||
return abs(s) < CMP_EPSILON;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ float absf(float g) {
|
||||
union {
|
||||
float f;
|
||||
uint32_t i;
|
||||
} u;
|
||||
|
||||
u.f = g;
|
||||
u.i &= 2147483647u;
|
||||
return u.f;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double absd(double g) {
|
||||
union {
|
||||
double d;
|
||||
uint64_t i;
|
||||
} u;
|
||||
u.d = g;
|
||||
u.i &= (uint64_t)9223372036854775807ll;
|
||||
return u.d;
|
||||
}
|
||||
|
||||
// This function should be as fast as possible and rounding mode should not matter.
|
||||
static _ALWAYS_INLINE_ int fast_ftoi(float a) {
|
||||
// Assuming every supported compiler has `lrint()`.
|
||||
return lrintf(a);
|
||||
}
|
||||
|
||||
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_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;
|
||||
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) {
|
||||
union {
|
||||
uint32_t u32;
|
||||
float f32;
|
||||
} u;
|
||||
|
||||
u.u32 = halfbits_to_floatbits(*h);
|
||||
return u.f32;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ float half_to_float(const uint16_t h) {
|
||||
return halfptr_to_float(&h);
|
||||
}
|
||||
|
||||
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;
|
||||
h_exp++;
|
||||
}
|
||||
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
|
||||
exp = (0x38000000 - exp) >> 23;
|
||||
mantissa >>= (14 + 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);
|
||||
}
|
||||
}
|
||||
|
||||
hf = (((uint16_t)sign) << 15) | (uint16_t)(mantissa);
|
||||
*/
|
||||
hf = 0; //denormals do not work for 3D, convert to zero
|
||||
static _ALWAYS_INLINE_ float math_halfptr_to_float(const uint16_t *h) {
|
||||
union {
|
||||
uint32_t u32;
|
||||
float f32;
|
||||
} u;
|
||||
|
||||
u.u32 = math_halfbits_to_floatbits(*h);
|
||||
return u.f32;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ float math_half_to_float(const uint16_t h) {
|
||||
return math_halfptr_to_float(&h);
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ uint16_t math_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 {
|
||||
hf = (((uint16_t)sign) << 15) |
|
||||
(uint16_t)((exp - 0x38000000) >> 13) |
|
||||
(uint16_t)(mantissa >> 13);
|
||||
// 16-bit half-float representation stores number as Inf
|
||||
mantissa = 0;
|
||||
}
|
||||
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
|
||||
exp = (0x38000000 - exp) >> 23;
|
||||
mantissa >>= (14 + exp);
|
||||
|
||||
return hf;
|
||||
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);
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ float snap_scalar(float p_offset, float p_step, float p_target) {
|
||||
return p_step != 0 ? Math::stepify(p_target - p_offset, p_step) + p_offset : p_target;
|
||||
}
|
||||
return hf;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ float snap_scalar_separation(float p_offset, float p_step, float p_target, float p_separation) {
|
||||
if (p_step != 0) {
|
||||
float a = Math::stepify(p_target - p_offset, p_step + p_separation) + p_offset;
|
||||
float b = a;
|
||||
if (p_target >= 0) {
|
||||
b -= p_separation;
|
||||
} else {
|
||||
b += p_step;
|
||||
}
|
||||
return (Math::abs(p_target - a) < Math::abs(p_target - b)) ? a : b;
|
||||
float math_stepifyf(float p_value, float p_step);
|
||||
double math_stepifyd(double p_value, double p_step);
|
||||
|
||||
static _ALWAYS_INLINE_ float math_snap_scalar(float p_offset, float p_step, float p_target) {
|
||||
return p_step != 0 ? math_stepifyf(p_target - p_offset, p_step) + p_offset : p_target;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ float math_snap_scalar_separation(float p_offset, float p_step, float p_target, float p_separation) {
|
||||
if (p_step != 0) {
|
||||
float a = math_stepifyf(p_target - p_offset, p_step + p_separation) + p_offset;
|
||||
float b = a;
|
||||
if (p_target >= 0) {
|
||||
b -= p_separation;
|
||||
} else {
|
||||
b += p_step;
|
||||
}
|
||||
return p_target;
|
||||
return (math_absf(p_target - a) < math_absf(p_target - b)) ? a : b;
|
||||
}
|
||||
};
|
||||
return p_target;
|
||||
}
|
||||
|
||||
#endif // MATH_FUNCS_H
|
||||
|
@ -32,7 +32,6 @@
|
||||
#define VECTOR2_H
|
||||
|
||||
#include "core/math/math_funcs.h"
|
||||
#include "core/ustring.h"
|
||||
|
||||
struct Vector2i;
|
||||
|
||||
|
417
core/typedefs.h
Normal file
417
core/typedefs.h
Normal file
@ -0,0 +1,417 @@
|
||||
/*************************************************************************/
|
||||
/* typedefs.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef TYPEDEFS_H
|
||||
#define TYPEDEFS_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* Basic definitions and simple functions to be used everywhere.
|
||||
*/
|
||||
|
||||
//#include "platform_config.h"
|
||||
|
||||
#ifndef _STR
|
||||
#define _STR(m_x) #m_x
|
||||
#define _MKSTR(m_x) _STR(m_x)
|
||||
#endif
|
||||
|
||||
//should always inline no matter what
|
||||
#ifndef _ALWAYS_INLINE_
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
#define _ALWAYS_INLINE_ __attribute__((always_inline)) inline
|
||||
#elif defined(__llvm__)
|
||||
#define _ALWAYS_INLINE_ __attribute__((always_inline)) inline
|
||||
#elif defined(_MSC_VER)
|
||||
#define _ALWAYS_INLINE_ __forceinline
|
||||
#else
|
||||
#define _ALWAYS_INLINE_ inline
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// Should always inline, except in dev builds because it makes debugging harder.
|
||||
#ifndef _FORCE_INLINE_
|
||||
#ifdef DEV_ENABLED
|
||||
#define _FORCE_INLINE_ inline
|
||||
#else
|
||||
#define _FORCE_INLINE_ _ALWAYS_INLINE_
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// No discard allows the compiler to flag warnings if we don't use the return value of functions / classes
|
||||
#ifndef _NO_DISCARD_
|
||||
// c++ 17 onwards
|
||||
#if __cplusplus >= 201703L
|
||||
#define _NO_DISCARD_ [[nodiscard]]
|
||||
#else
|
||||
// __warn_unused_result__ supported on clang and GCC
|
||||
#if (defined(__clang__) || defined(__GNUC__)) && defined(__has_attribute)
|
||||
#if __has_attribute(__warn_unused_result__)
|
||||
#define _NO_DISCARD_ __attribute__((__warn_unused_result__))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Visual Studio 2012 onwards
|
||||
#if _MSC_VER >= 1700
|
||||
#define _NO_DISCARD_ _Check_return_
|
||||
#endif
|
||||
|
||||
// If nothing supported, just noop the macro
|
||||
#ifndef _NO_DISCARD_
|
||||
#define _NO_DISCARD_
|
||||
#endif
|
||||
#endif // not c++ 17
|
||||
#endif // not defined _NO_DISCARD_
|
||||
|
||||
// In some cases _NO_DISCARD_ will get false positives,
|
||||
// we can prevent the warning in specific cases by preceding the call with a cast.
|
||||
#ifndef _ALLOW_DISCARD_
|
||||
#define _ALLOW_DISCARD_ (void)
|
||||
#endif
|
||||
|
||||
// GCC (prior to c++ 17) Does not seem to support no discard with classes, only functions.
|
||||
// So we will use a specific macro for classes.
|
||||
#ifndef _NO_DISCARD_CLASS_
|
||||
#if (defined(__clang__) || defined(_MSC_VER))
|
||||
#define _NO_DISCARD_CLASS_ _NO_DISCARD_
|
||||
#else
|
||||
#define _NO_DISCARD_CLASS_
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//custom, gcc-safe offsetof, because gcc complains a lot.
|
||||
/*
|
||||
template <class T>
|
||||
T *_nullptr() {
|
||||
T *t = NULL;
|
||||
return t;
|
||||
}
|
||||
|
||||
#define OFFSET_OF(st, m) \
|
||||
((size_t)((char *)&(_nullptr<st>()->m) - (char *)0))
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* Some platforms (devices) don't define NULL
|
||||
*/
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* 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 ERROR // override (really stupid) wingdi.h standard definition
|
||||
#undef DELETE // override (another really stupid) winnt.h standard definition
|
||||
#undef MessageBox // override winuser.h standard definition
|
||||
#undef MIN // override standard definition
|
||||
#undef MAX // override standard definition
|
||||
#undef CLAMP // override standard definition
|
||||
#undef Error
|
||||
#undef OK
|
||||
#undef CONNECT_DEFERRED // override from Windows SDK, clashes with Object enum
|
||||
#endif
|
||||
|
||||
#include "core/int_types.h"
|
||||
|
||||
#include "core/error_list.h"
|
||||
|
||||
/** Generic ABS function, for math uses please use Math::abs */
|
||||
|
||||
#ifndef ABS
|
||||
#define ABS(m_v) (((m_v) < 0) ? (-(m_v)) : (m_v))
|
||||
#endif
|
||||
|
||||
#define ABSDIFF(x, y) (((x) < (y)) ? ((y) - (x)) : ((x) - (y)))
|
||||
|
||||
#ifndef SGN
|
||||
#define SGN(m_v) (((m_v) < 0) ? (-1.0f) : (+1.0f))
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(m_a, m_b) (((m_a) < (m_b)) ? (m_a) : (m_b))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(m_a, m_b) (((m_a) > (m_b)) ? (m_a) : (m_b))
|
||||
#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))
|
||||
#endif
|
||||
|
||||
/** 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;
|
||||
}
|
||||
*/
|
||||
|
||||
#define SWAP(type, a, b) \
|
||||
{ \
|
||||
type __swap_temp; \
|
||||
__swap_temp = (b); \
|
||||
(b) = (a); \
|
||||
(a) = __swap_temp; \
|
||||
}
|
||||
|
||||
#endif //swap
|
||||
|
||||
/* clang-format off */
|
||||
#define HEX2CHR(m_hex) \
|
||||
((m_hex >= '0' && m_hex <= '9') ? (m_hex - '0') : \
|
||||
((m_hex >= 'A' && m_hex <= 'F') ? (10 + m_hex - 'A') : \
|
||||
((m_hex >= 'a' && m_hex <= 'f') ? (10 + m_hex - 'a') : 0)))
|
||||
/* clang-format on */
|
||||
|
||||
// Macro to check whether we are compiled by clang
|
||||
// and we have a specific builtin
|
||||
#if defined(__llvm__) && defined(__has_builtin)
|
||||
#define _llvm_has_builtin(x) __has_builtin(x)
|
||||
#else
|
||||
#define _llvm_has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 5)) || _llvm_has_builtin(__builtin_mul_overflow)
|
||||
#define _mul_overflow __builtin_mul_overflow
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 5)) || _llvm_has_builtin(__builtin_add_overflow)
|
||||
#define _add_overflow __builtin_add_overflow
|
||||
#endif
|
||||
|
||||
/** 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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// We need this definition inside the function below.
|
||||
static inline int get_shift_from_power_of_2(unsigned int p_pixel);
|
||||
|
||||
/*
|
||||
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 p_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 its 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;
|
||||
}
|
||||
|
||||
/** get a shift value from a power of 2 */
|
||||
static inline int get_shift_from_power_of_2(unsigned int p_pixel) {
|
||||
// return a GL_TEXTURE_SIZE_ENUM
|
||||
|
||||
for (unsigned int i = 0; i < 32; i++) {
|
||||
if (p_pixel == (unsigned int)(1 << i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Swap 16 bits value for endianness */
|
||||
#if defined(__GNUC__) || _llvm_has_builtin(__builtin_bswap16)
|
||||
#define BSWAP16(x) __builtin_bswap16(x)
|
||||
#else
|
||||
static inline uint16_t BSWAP16(uint16_t x) {
|
||||
return (x >> 8) | (x << 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Swap 32 bits value for endianness */
|
||||
#if defined(__GNUC__) || _llvm_has_builtin(__builtin_bswap32)
|
||||
#define BSWAP32(x) __builtin_bswap32(x)
|
||||
#else
|
||||
static inline uint32_t BSWAP32(uint32_t x) {
|
||||
return ((x << 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x >> 24));
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Swap 64 bits value for endianness */
|
||||
#if defined(__GNUC__) || _llvm_has_builtin(__builtin_bswap64)
|
||||
#define BSWAP64(x) __builtin_bswap64(x)
|
||||
#else
|
||||
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
|
||||
|
||||
/** When compiling with RTTI, we can add an "extra"
|
||||
* layer of safeness in many operations, so dynamic_cast
|
||||
* is used besides casting by enum.
|
||||
*/
|
||||
|
||||
/*
|
||||
template <class T>
|
||||
struct Comparator {
|
||||
_ALWAYS_INLINE_ bool operator()(const T &p_a, const T &p_b) const { return (p_a < p_b); }
|
||||
};*/
|
||||
|
||||
void _global_lock();
|
||||
void _global_unlock();
|
||||
|
||||
/*
|
||||
struct _GlobalLock {
|
||||
_GlobalLock() { _global_lock(); }
|
||||
~_GlobalLock() { _global_unlock(); }
|
||||
};
|
||||
*/
|
||||
|
||||
#define GLOBAL_LOCK_FUNCTION _GlobalLock _global_lock_;
|
||||
|
||||
/*
|
||||
#ifdef NO_SAFE_CAST
|
||||
#define SAFE_CAST static_cast
|
||||
#else
|
||||
#define SAFE_CAST dynamic_cast
|
||||
#endif
|
||||
*/
|
||||
|
||||
#define MT_SAFE
|
||||
|
||||
#define __STRX(m_index) #m_index
|
||||
#define __STR(m_index) __STRX(m_index)
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#else
|
||||
#define likely(x) x
|
||||
#define unlikely(x) x
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define _PRINTF_FORMAT_ATTRIBUTE_2_0 __attribute__((format(printf, 2, 0)))
|
||||
#define _PRINTF_FORMAT_ATTRIBUTE_2_3 __attribute__((format(printf, 2, 3)))
|
||||
#else
|
||||
#define _PRINTF_FORMAT_ATTRIBUTE_2_0
|
||||
#define _PRINTF_FORMAT_ATTRIBUTE_2_3
|
||||
#endif
|
||||
|
||||
/** This is needed due to a strange OpenGL API that expects a pointer
|
||||
* type for an argument that is actually an offset.
|
||||
*/
|
||||
#define CAST_INT_TO_UCHAR_PTR(ptr) ((uint8_t *)(uintptr_t)(ptr))
|
||||
|
||||
/** Hint for compilers that this fallthrough in a switch is intentional.
|
||||
* Can be replaced by [[fallthrough]] annotation if we move to C++17.
|
||||
* Including conditional support for it for people who set -std=c++17
|
||||
* themselves.
|
||||
* Requires a trailing semicolon when used.
|
||||
*/
|
||||
#if __cplusplus >= 201703L
|
||||
#define FALLTHROUGH [[fallthrough]]
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 7
|
||||
#define FALLTHROUGH __attribute__((fallthrough))
|
||||
#elif defined(__llvm__) && __cplusplus >= 201103L && defined(__has_feature)
|
||||
#if __has_feature(cxx_attributes) && defined(__has_warning)
|
||||
#if __has_warning("-Wimplicit-fallthrough")
|
||||
#define FALLTHROUGH [[clang::fallthrough]]
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef FALLTHROUGH
|
||||
#define FALLTHROUGH
|
||||
#endif
|
||||
|
||||
// Limit the depth of recursive algorithms when dealing with Array/Dictionary
|
||||
#define MAX_RECURSION 100
|
||||
|
||||
#endif // TYPEDEFS_H
|
Loading…
Reference in New Issue
Block a user