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
|
# 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.SConsignFile(".sconsign{0}.dblite".format(pickle.HIGHEST_PROTOCOL))
|
||||||
|
|
||||||
|
env_base.Prepend(CPPPATH=["#"])
|
||||||
|
|
||||||
# Build options
|
# Build options
|
||||||
|
|
||||||
env = env_base.Clone()
|
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 "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
|
#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);
|
RandomPCG rng = RandomPCG(*seed, RandomPCG::DEFAULT_INC);
|
||||||
uint32_t r = rng.rand();
|
uint32_t r = rng.rand();
|
||||||
*seed = rng.get_seed();
|
*seed = rng.get_seed();
|
||||||
return r;
|
return r;
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Math::seed(uint64_t x) {
|
void math_seed(uint64_t x) {
|
||||||
default_rand.seed(x);
|
//default_rand.seed(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Math::randomize() {
|
void math_randomize() {
|
||||||
default_rand.randomize();
|
//default_rand.randomize();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Math::rand() {
|
uint32_t math_rand() {
|
||||||
return default_rand.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 int maxn = 10;
|
||||||
static const double sd[maxn] = {
|
static const double sd[10] = {
|
||||||
0.9999, // somehow compensate for floating point error
|
0.9999, // somehow compensate for floating point error
|
||||||
0.09999,
|
0.09999,
|
||||||
0.009999,
|
0.009999,
|
||||||
@ -70,7 +74,7 @@ int Math::step_decimals(double p_step) {
|
|||||||
0.0000000009999
|
0.0000000009999
|
||||||
};
|
};
|
||||||
|
|
||||||
double abs = Math::abs(p_step);
|
double abs = math_absd(p_step);
|
||||||
double decs = abs - (int)abs; // Strip away integer part
|
double decs = abs - (int)abs; // Strip away integer part
|
||||||
for (int i = 0; i < maxn; i++) {
|
for (int i = 0; i < maxn; i++) {
|
||||||
if (decs >= sd[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
|
// Only meant for editor usage in float ranges, where a step of 0
|
||||||
// means that decimal digits should not be limited in String::num.
|
// 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) {
|
if (p_step < 0.0000000000001) {
|
||||||
return 16; // Max value hardcoded in String::num
|
return 16; // Max value hardcoded in String::num
|
||||||
}
|
}
|
||||||
return step_decimals(p_step);
|
return step_decimals(p_step);
|
||||||
}
|
}
|
||||||
|
|
||||||
double Math::dectime(double p_value, double p_amount, double 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.");
|
//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 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;
|
val -= p_amount * p_step;
|
||||||
if (val < 0.0) {
|
if (val < 0.0) {
|
||||||
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;
|
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) {
|
if (p_x < 0) {
|
||||||
p_x = 0;
|
p_x = 0;
|
||||||
} else if (p_x > 1.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 > 0) {
|
||||||
if (p_c < 1.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 {
|
} else {
|
||||||
return Math::pow(p_x, p_c);
|
return math_powd(p_x, p_c);
|
||||||
}
|
}
|
||||||
} else if (p_c < 0) {
|
} else if (p_c < 0) {
|
||||||
//inout ease
|
//inout ease
|
||||||
|
|
||||||
if (p_x < 0.5) {
|
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 {
|
} 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 {
|
} else {
|
||||||
return 0; // no ease (raw)
|
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) {
|
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;
|
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[] = {
|
static const uint32_t primes[] = {
|
||||||
5,
|
5,
|
||||||
13,
|
13,
|
||||||
@ -169,7 +180,7 @@ uint32_t Math::larger_prime(uint32_t p_val) {
|
|||||||
|
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
ERR_FAIL_COND_V(primes[idx] == 0, 0);
|
//ERR_FAIL_COND_V(primes[idx] == 0, 0);
|
||||||
if (primes[idx] > p_val) {
|
if (primes[idx] > p_val) {
|
||||||
return primes[idx];
|
return primes[idx];
|
||||||
}
|
}
|
||||||
@ -177,10 +188,14 @@ uint32_t Math::larger_prime(uint32_t p_val) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double Math::random(double from, double to) {
|
double math_randomd(double from, double to) {
|
||||||
return default_rand.random(from, to);
|
//return default_rand.random(from, to);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Math::random(float from, float to) {
|
float math_randomf(float from, float to) {
|
||||||
return default_rand.random(from, to);
|
//return default_rand.random(from, to);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
@ -32,81 +32,148 @@
|
|||||||
#define MATH_FUNCS_H
|
#define MATH_FUNCS_H
|
||||||
|
|
||||||
#include "core/math/math_defs.h"
|
#include "core/math/math_defs.h"
|
||||||
#include "core/math/random_pcg.h"
|
|
||||||
#include "core/typedefs.h"
|
#include "core/typedefs.h"
|
||||||
|
|
||||||
#include "thirdparty/misc/pcg.h"
|
|
||||||
|
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
class Math {
|
// Not using 'RANDOM_MAX' to avoid conflict with system headers on some OSes (at least NetBSD).
|
||||||
static RandomPCG default_rand;
|
static const uint64_t MATH_RANDOM_32BIT_MAX = 0xFFFFFFFF;
|
||||||
|
|
||||||
public:
|
static _ALWAYS_INLINE_ double math_sind(double p_x) {
|
||||||
Math() {} // useless to instance
|
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 _ALWAYS_INLINE_ double math_cosd(double p_x) {
|
||||||
static const uint64_t RANDOM_32BIT_MAX = 0xFFFFFFFF;
|
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_ double math_tand(double p_x) {
|
||||||
static _ALWAYS_INLINE_ float sin(float p_x) { return ::sinf(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_ double math_sinhd(double p_x) {
|
||||||
static _ALWAYS_INLINE_ float cos(float p_x) { return ::cosf(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 math_sincf(float p_x) {
|
||||||
static _ALWAYS_INLINE_ float tan(float p_x) { return ::tanf(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 math_sincnf(float p_x) {
|
||||||
static _ALWAYS_INLINE_ float sinh(float p_x) { return ::sinhf(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 math_coshd(double p_x) {
|
||||||
static _ALWAYS_INLINE_ double sinc(double p_x) { return p_x == 0 ? 1 : ::sin(p_x) / 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 math_tanhd(double p_x) {
|
||||||
static _ALWAYS_INLINE_ double sincn(double p_x) { return sinc(Math_PI * 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_ double math_asind(double p_x) {
|
||||||
static _ALWAYS_INLINE_ float cosh(float p_x) { return ::coshf(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_ double math_acosd(double p_x) {
|
||||||
static _ALWAYS_INLINE_ float tanh(float p_x) { return ::tanhf(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_ double math_atand(double p_x) {
|
||||||
static _ALWAYS_INLINE_ float asin(float p_x) { return ::asinf(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_ double math_atan2d(double p_y, double p_x) {
|
||||||
static _ALWAYS_INLINE_ float acos(float p_x) { return ::acosf(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_ double math_sqrtd(double p_x) {
|
||||||
static _ALWAYS_INLINE_ float atan(float p_x) { return ::atanf(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_ double math_fmodd(double p_x, double p_y) {
|
||||||
static _ALWAYS_INLINE_ float atan2(float p_y, float p_x) { return ::atan2f(p_y, p_x); }
|
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_ double math_floord(double p_x) {
|
||||||
static _ALWAYS_INLINE_ float sqrt(float p_x) { return ::sqrtf(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_ double math_ceild(double p_x) {
|
||||||
static _ALWAYS_INLINE_ float fmod(float p_x, float p_y) { return ::fmodf(p_x, p_y); }
|
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_ double math_powd(double p_x, double p_y) {
|
||||||
static _ALWAYS_INLINE_ float floor(float p_x) { return ::floorf(p_x); }
|
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_ double math_logd(double p_x) {
|
||||||
static _ALWAYS_INLINE_ float ceil(float p_x) { return ::ceilf(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_ double math_expd(double p_x) {
|
||||||
static _ALWAYS_INLINE_ float pow(float p_x, float p_y) { return ::powf(p_x, p_y); }
|
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_ bool math_is_nand(double p_val) {
|
||||||
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) {
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
return _isnan(p_val);
|
return _isnan(p_val);
|
||||||
#elif defined(__GNUC__) && __GNUC__ < 6
|
#elif defined(__GNUC__) && __GNUC__ < 6
|
||||||
@ -120,9 +187,9 @@ public:
|
|||||||
#else
|
#else
|
||||||
return isnan(p_val);
|
return isnan(p_val);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static _ALWAYS_INLINE_ bool is_nan(float p_val) {
|
static _ALWAYS_INLINE_ bool math_is_nanf(float p_val) {
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
return _isnan(p_val);
|
return _isnan(p_val);
|
||||||
#elif defined(__GNUC__) && __GNUC__ < 6
|
#elif defined(__GNUC__) && __GNUC__ < 6
|
||||||
@ -143,9 +210,9 @@ public:
|
|||||||
#else
|
#else
|
||||||
return isnan(p_val);
|
return isnan(p_val);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static _ALWAYS_INLINE_ bool is_inf(double p_val) {
|
static _ALWAYS_INLINE_ bool math_is_infd(double p_val) {
|
||||||
#ifdef _MSC_VER
|
#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
|
// use an inline implementation of isinf as a workaround for problematic libstdc++ versions from gcc 5.x era
|
||||||
@ -160,9 +227,9 @@ public:
|
|||||||
#else
|
#else
|
||||||
return isinf(p_val);
|
return isinf(p_val);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static _ALWAYS_INLINE_ bool is_inf(float p_val) {
|
static _ALWAYS_INLINE_ bool math_is_inff(float p_val) {
|
||||||
#ifdef _MSC_VER
|
#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
|
// use an inline implementation of isinf as a workaround for problematic libstdc++ versions from gcc 5.x era
|
||||||
@ -176,187 +243,9 @@ public:
|
|||||||
#else
|
#else
|
||||||
return isinf(p_val);
|
return isinf(p_val);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static _ALWAYS_INLINE_ double abs(double g) { return absd(g); }
|
static _ALWAYS_INLINE_ float math_absf(float 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;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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_ 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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_ 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);
|
|
||||||
}
|
|
||||||
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; }
|
|
||||||
|
|
||||||
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_ 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));
|
|
||||||
}
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 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 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static _ALWAYS_INLINE_ bool is_zero_approx(float s) {
|
|
||||||
return abs(s) < (float)CMP_EPSILON;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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_ bool is_zero_approx(double s) {
|
|
||||||
return abs(s) < CMP_EPSILON;
|
|
||||||
}
|
|
||||||
|
|
||||||
static _ALWAYS_INLINE_ float absf(float g) {
|
|
||||||
union {
|
union {
|
||||||
float f;
|
float f;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
@ -365,9 +254,9 @@ public:
|
|||||||
u.f = g;
|
u.f = g;
|
||||||
u.i &= 2147483647u;
|
u.i &= 2147483647u;
|
||||||
return u.f;
|
return u.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static _ALWAYS_INLINE_ double absd(double g) {
|
static _ALWAYS_INLINE_ double math_absd(double g) {
|
||||||
union {
|
union {
|
||||||
double d;
|
double d;
|
||||||
uint64_t i;
|
uint64_t i;
|
||||||
@ -375,15 +264,262 @@ public:
|
|||||||
u.d = g;
|
u.d = g;
|
||||||
u.i &= (uint64_t)9223372036854775807ll;
|
u.i &= (uint64_t)9223372036854775807ll;
|
||||||
return u.d;
|
return u.d;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function should be as fast as possible and rounding mode should not matter.
|
static _ALWAYS_INLINE_ int math_absi(int g) {
|
||||||
static _ALWAYS_INLINE_ int fast_ftoi(float a) {
|
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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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_ 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;
|
||||||
|
}
|
||||||
|
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_ bool math_is_equal_approxf(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 * math_absf(a);
|
||||||
|
if (tolerance < (float)CMP_EPSILON) {
|
||||||
|
tolerance = (float)CMP_EPSILON;
|
||||||
|
}
|
||||||
|
return math_absf(a - b) < tolerance;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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;
|
||||||
|
}
|
||||||
|
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_ 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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()`.
|
// Assuming every supported compiler has `lrint()`.
|
||||||
return lrintf(a);
|
return lrintf(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static _ALWAYS_INLINE_ uint32_t halfbits_to_floatbits(uint16_t h) {
|
static _ALWAYS_INLINE_ uint32_t math_halfbits_to_floatbits(uint16_t h) {
|
||||||
uint16_t h_exp, h_sig;
|
uint16_t h_exp, h_sig;
|
||||||
uint32_t f_sgn, f_exp, f_sig;
|
uint32_t f_sgn, f_exp, f_sig;
|
||||||
|
|
||||||
@ -412,23 +548,23 @@ public:
|
|||||||
/* Just need to adjust the exponent and shift */
|
/* Just need to adjust the exponent and shift */
|
||||||
return f_sgn + (((uint32_t)(h & 0x7fffu) + 0x1c000u) << 13);
|
return f_sgn + (((uint32_t)(h & 0x7fffu) + 0x1c000u) << 13);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static _ALWAYS_INLINE_ float halfptr_to_float(const uint16_t *h) {
|
static _ALWAYS_INLINE_ float math_halfptr_to_float(const uint16_t *h) {
|
||||||
union {
|
union {
|
||||||
uint32_t u32;
|
uint32_t u32;
|
||||||
float f32;
|
float f32;
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
u.u32 = halfbits_to_floatbits(*h);
|
u.u32 = math_halfbits_to_floatbits(*h);
|
||||||
return u.f32;
|
return u.f32;
|
||||||
}
|
}
|
||||||
|
|
||||||
static _ALWAYS_INLINE_ float half_to_float(const uint16_t h) {
|
static _ALWAYS_INLINE_ float math_half_to_float(const uint16_t h) {
|
||||||
return halfptr_to_float(&h);
|
return math_halfptr_to_float(&h);
|
||||||
}
|
}
|
||||||
|
|
||||||
static _ALWAYS_INLINE_ uint16_t make_half_float(float f) {
|
static _ALWAYS_INLINE_ uint16_t math_make_half_float(float f) {
|
||||||
union {
|
union {
|
||||||
float fv;
|
float fv;
|
||||||
uint32_t ui;
|
uint32_t ui;
|
||||||
@ -473,25 +609,27 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
return hf;
|
return hf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static _ALWAYS_INLINE_ float snap_scalar(float p_offset, float p_step, float p_target) {
|
float math_stepifyf(float p_value, float p_step);
|
||||||
return p_step != 0 ? Math::stepify(p_target - p_offset, p_step) + p_offset : p_target;
|
double math_stepifyd(double p_value, double p_step);
|
||||||
}
|
|
||||||
|
|
||||||
static _ALWAYS_INLINE_ float snap_scalar_separation(float p_offset, float p_step, float p_target, float p_separation) {
|
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) {
|
if (p_step != 0) {
|
||||||
float a = Math::stepify(p_target - p_offset, p_step + p_separation) + p_offset;
|
float a = math_stepifyf(p_target - p_offset, p_step + p_separation) + p_offset;
|
||||||
float b = a;
|
float b = a;
|
||||||
if (p_target >= 0) {
|
if (p_target >= 0) {
|
||||||
b -= p_separation;
|
b -= p_separation;
|
||||||
} else {
|
} else {
|
||||||
b += p_step;
|
b += p_step;
|
||||||
}
|
}
|
||||||
return (Math::abs(p_target - a) < Math::abs(p_target - b)) ? a : b;
|
return (math_absf(p_target - a) < math_absf(p_target - b)) ? a : b;
|
||||||
}
|
}
|
||||||
return p_target;
|
return p_target;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
#endif // MATH_FUNCS_H
|
#endif // MATH_FUNCS_H
|
||||||
|
@ -32,7 +32,6 @@
|
|||||||
#define VECTOR2_H
|
#define VECTOR2_H
|
||||||
|
|
||||||
#include "core/math/math_funcs.h"
|
#include "core/math/math_funcs.h"
|
||||||
#include "core/ustring.h"
|
|
||||||
|
|
||||||
struct Vector2i;
|
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