mirror of
https://github.com/Relintai/rcpp_framework.git
synced 2024-11-14 04:57:21 +01:00
Added a few number to string conversion methods form the godot engine to the string.
This commit is contained in:
parent
a19bcea0f0
commit
aaa48e390b
180
core/math.h
180
core/math.h
@ -11,79 +11,161 @@
|
||||
|
||||
class Math {
|
||||
public:
|
||||
static const uint64_t RANDOM_32BIT_MAX = 0xFFFFFFFF;
|
||||
|
||||
static const uint64_t RANDOM_32BIT_MAX = 0xFFFFFFFF;
|
||||
inline static float sin(const float x) { return ::sinf(x); }
|
||||
inline static double sin(const double x) { return ::sin(x); }
|
||||
|
||||
inline static float sin(const float x) { return ::sinf(x); }
|
||||
inline static double sin(const double x) { return ::sin(x); }
|
||||
inline static float cos(const float x) { return ::cosf(x); }
|
||||
inline static double cos(const double x) { return ::cos(x); }
|
||||
|
||||
inline static float cos(const float x) { return ::cosf(x); }
|
||||
inline static double cos(const double x) { return ::cos(x); }
|
||||
inline static float tan(const float x) { return ::tanf(x); }
|
||||
inline static double tan(const double x) { return ::tan(x); }
|
||||
|
||||
inline static float tan(const float x) { return ::tanf(x); }
|
||||
inline static double tan(const double x) { return ::tan(x); }
|
||||
inline static float asin(const float x) { return ::asinf(x); }
|
||||
inline static double asin(const double x) { return ::asin(x); }
|
||||
|
||||
inline static float asin(const float x) { return ::asinf(x); }
|
||||
inline static double asin(const double x) { return ::asin(x); }
|
||||
inline static float acos(const float x) { return ::acosf(x); }
|
||||
inline static double acos(const double x) { return ::acos(x); }
|
||||
|
||||
inline static float acos(const float x) { return ::acosf(x); }
|
||||
inline static double acos(const double x) { return ::acos(x); }
|
||||
inline static float atan(const float x) { return ::atanf(x); }
|
||||
inline static double atan(const double x) { return ::atan(x); }
|
||||
|
||||
inline static float atan(const float x) { return ::atanf(x); }
|
||||
inline static double atan(const double x) { return ::atan(x); }
|
||||
inline static float atan2(const float x, const float y) { return ::atan2f(x, y); }
|
||||
inline static double atan2(const double x, const float y) { return ::atan2(x, y); }
|
||||
|
||||
inline static float atan2(const float x, const float y) { return ::atan2f(x, y); }
|
||||
inline static double atan2(const double x, const float y) { return ::atan2(x, y); }
|
||||
inline static float sqrt(const float x) { return ::sqrtf(x); }
|
||||
inline static double sqrt(const double x) { return ::sqrt(x); }
|
||||
|
||||
inline static float sqrt(const float x) { return ::sqrtf(x); }
|
||||
inline static double sqrt(const double x) { return ::sqrt(x); }
|
||||
inline static float fmod(const float x, const float y) { return ::fmodf(x, y); }
|
||||
inline static double fmod(const double x, const float y) { return ::fmod(x, y); }
|
||||
|
||||
inline static float fmod(const float x, const float y) { return ::fmodf(x, y); }
|
||||
inline static double fmod(const double x, const float y) { return ::fmod(x, y); }
|
||||
inline static float floor(const float x) { return ::floorf(x); }
|
||||
inline static double floor(const double x) { return ::floor(x); }
|
||||
|
||||
inline static float floor(const float x) { return ::floorf(x); }
|
||||
inline static double floor(const double x) { return ::floor(x); }
|
||||
inline static float ceil(const float x) { return ::ceilf(x); }
|
||||
inline static double ceil(const double x) { return ::ceil(x); }
|
||||
|
||||
inline static float ceil(const float x) { return ::ceilf(x); }
|
||||
inline static double ceil(const double x) { return ::ceil(x); }
|
||||
inline static float pow(const float x, const float y) { return ::powf(x, y); }
|
||||
inline static double pow(const double x, const float y) { return ::pow(x, y); }
|
||||
|
||||
inline static float pow(const float x, const float y) { return ::powf(x, y); }
|
||||
inline static double pow(const double x, const float y) { return ::pow(x, y); }
|
||||
inline static float log(const float x) { return ::logf(x); }
|
||||
inline static double log(const double x) { return ::log(x); }
|
||||
|
||||
inline static float log(const float x) { return ::logf(x); }
|
||||
inline static double log(const double x) { return ::log(x); }
|
||||
static float inv_sqrt(const float x);
|
||||
static float fast_inv_sqrt(const float x);
|
||||
|
||||
static float inv_sqrt(const float x);
|
||||
static float fast_inv_sqrt(const float x);
|
||||
inline static float absf(const float x) { return x > 0 ? x : -x; }
|
||||
inline static double absd(const double x) { return x > 0 ? x : -x; }
|
||||
inline static int absi(const int x) { return x > 0 ? x : -x; }
|
||||
|
||||
inline static float abs(const float x) { return x > 0 ? x : -x; }
|
||||
inline static double abs(const double x) { return x > 0 ? x : -x; }
|
||||
inline static int abs(const int x) { return x > 0 ? x : -x; }
|
||||
inline static float deg2rad(const float x) { return x * MATH_PI / 180.0; }
|
||||
inline static double deg2rad(const double x) { return x * MATH_PI / 180.0; }
|
||||
inline static int deg2rad(const int x) { return x * MATH_PI / 180.0; }
|
||||
|
||||
inline static float deg2rad(const float x) { return x * MATH_PI / 180.0; }
|
||||
inline static double deg2rad(const double x) { return x * MATH_PI / 180.0; }
|
||||
inline static int deg2rad(const int x) { return x * MATH_PI / 180.0; }
|
||||
inline static float rad2deg(const float x) { return x * 180.0 / MATH_PI; }
|
||||
inline static double rad2deg(const double x) { return x * 180.0 / MATH_PI; }
|
||||
inline static int rad2deg(const int x) { return x * 180.0 / MATH_PI; }
|
||||
|
||||
inline static float rad2deg(const float x) { return x * 180.0 / MATH_PI; }
|
||||
inline static double rad2deg(const double x) { return x * 180.0 / MATH_PI; }
|
||||
inline static int rad2deg(const int x) { return x * 180.0 / MATH_PI; }
|
||||
static float is_equal_approx(const float a, const float b);
|
||||
static float is_zero_approx(const float a);
|
||||
|
||||
static float is_equal_approx(const float a, const float b);
|
||||
static float is_zero_approx(const float a);
|
||||
static void seed(const unsigned int s);
|
||||
static void randomize();
|
||||
|
||||
static void seed(const unsigned int s);
|
||||
static void randomize();
|
||||
static int rand();
|
||||
static float randf();
|
||||
static double randd();
|
||||
|
||||
static int rand();
|
||||
static float randf();
|
||||
static double randd();
|
||||
static int rand(const int m);
|
||||
|
||||
static int rand(const int m);
|
||||
static int rand(const int from, const int to);
|
||||
static float rand(const float from, const float to);
|
||||
static float rand(const double from, const double to);
|
||||
|
||||
static int rand(const int from, const int to);
|
||||
static float rand(const float from, const float to);
|
||||
static float rand(const double from, const double to);
|
||||
//Taken from the Godot Engine (MIT License)
|
||||
//Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.
|
||||
//Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).
|
||||
static bool is_nan(double p_val) {
|
||||
#ifdef _MSC_VER
|
||||
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);
|
||||
#else
|
||||
return isnan(p_val);
|
||||
#endif
|
||||
}
|
||||
|
||||
//Taken from the Godot Engine (MIT License)
|
||||
//Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.
|
||||
//Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).
|
||||
static bool is_nan(float p_val) {
|
||||
#ifdef _MSC_VER
|
||||
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);
|
||||
#else
|
||||
return isnan(p_val);
|
||||
#endif
|
||||
}
|
||||
|
||||
//Taken from the Godot Engine (MIT License)
|
||||
//Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.
|
||||
//Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).
|
||||
static bool is_inf(double p_val) {
|
||||
#ifdef _MSC_VER
|
||||
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);
|
||||
#else
|
||||
return isinf(p_val);
|
||||
#endif
|
||||
}
|
||||
|
||||
//Taken from the Godot Engine (MIT License)
|
||||
//Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.
|
||||
//Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).
|
||||
static bool is_inf(float p_val) {
|
||||
#ifdef _MSC_VER
|
||||
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;
|
||||
#else
|
||||
return isinf(p_val);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
320
core/string.cpp
320
core/string.cpp
@ -4,6 +4,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include "core/math.h"
|
||||
|
||||
static const int MAX_DECIMALS = 32;
|
||||
|
||||
void String::push_back(const char element) {
|
||||
ensure_capacity(_size + 1);
|
||||
@ -565,6 +568,323 @@ void String::print() const {
|
||||
::printf("%s\n", c_str());
|
||||
}
|
||||
|
||||
//Taken from the Godot Engine (MIT License)
|
||||
//Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.
|
||||
//Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).
|
||||
String String::num(double p_num, int p_decimals) {
|
||||
if (Math::is_nan(p_num)) {
|
||||
return "nan";
|
||||
}
|
||||
|
||||
if (Math::is_inf(p_num)) {
|
||||
if (signbit(p_num)) {
|
||||
return "-inf";
|
||||
} else {
|
||||
return "inf";
|
||||
}
|
||||
}
|
||||
|
||||
if (p_decimals < 0) {
|
||||
p_decimals = 14;
|
||||
const double abs_num = Math::absd(p_num);
|
||||
if (abs_num > 10) {
|
||||
// We want to align the digits to the above sane default, so we only
|
||||
// need to subtract log10 for numbers with a positive power of ten.
|
||||
p_decimals -= (int)floor(log10(abs_num));
|
||||
}
|
||||
}
|
||||
if (p_decimals > MAX_DECIMALS) {
|
||||
p_decimals = MAX_DECIMALS;
|
||||
}
|
||||
|
||||
char fmt[7];
|
||||
fmt[0] = '%';
|
||||
fmt[1] = '.';
|
||||
|
||||
if (p_decimals < 0) {
|
||||
fmt[1] = 'l';
|
||||
fmt[2] = 'f';
|
||||
fmt[3] = 0;
|
||||
} else if (p_decimals < 10) {
|
||||
fmt[2] = '0' + p_decimals;
|
||||
fmt[3] = 'l';
|
||||
fmt[4] = 'f';
|
||||
fmt[5] = 0;
|
||||
} else {
|
||||
fmt[2] = '0' + (p_decimals / 10);
|
||||
fmt[3] = '0' + (p_decimals % 10);
|
||||
fmt[4] = 'l';
|
||||
fmt[5] = 'f';
|
||||
fmt[6] = 0;
|
||||
}
|
||||
char buf[256];
|
||||
|
||||
#if defined(__GNUC__) || defined(_MSC_VER)
|
||||
snprintf(buf, 256, fmt, p_num);
|
||||
#else
|
||||
sprintf(buf, fmt, p_num);
|
||||
#endif
|
||||
|
||||
buf[255] = 0;
|
||||
//destroy trailing zeroes
|
||||
{
|
||||
bool period = false;
|
||||
int z = 0;
|
||||
while (buf[z]) {
|
||||
if (buf[z] == '.') {
|
||||
period = true;
|
||||
}
|
||||
z++;
|
||||
}
|
||||
|
||||
if (period) {
|
||||
z--;
|
||||
while (z > 0) {
|
||||
if (buf[z] == '0') {
|
||||
buf[z] = 0;
|
||||
} else if (buf[z] == '.') {
|
||||
buf[z] = 0;
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
z--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
//Taken from the Godot Engine (MIT License)
|
||||
//Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.
|
||||
//Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).
|
||||
String String::num_int64(int64_t p_num, int base, bool capitalize_hex) {
|
||||
bool sign = p_num < 0;
|
||||
|
||||
int64_t n = p_num;
|
||||
|
||||
int chars = 0;
|
||||
do {
|
||||
n /= base;
|
||||
chars++;
|
||||
} while (n);
|
||||
|
||||
if (sign) {
|
||||
chars++;
|
||||
}
|
||||
|
||||
String s;
|
||||
s.resize(chars + 1);
|
||||
char *c = s.dataw();
|
||||
c[chars] = 0;
|
||||
n = p_num;
|
||||
do {
|
||||
int mod = Math::absi(n % base);
|
||||
if (mod >= 10) {
|
||||
char a = (capitalize_hex ? 'A' : 'a');
|
||||
c[--chars] = a + (mod - 10);
|
||||
} else {
|
||||
c[--chars] = '0' + mod;
|
||||
}
|
||||
|
||||
n /= base;
|
||||
} while (n);
|
||||
|
||||
if (sign) {
|
||||
c[0] = '-';
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//Taken from the Godot Engine (MIT License)
|
||||
//Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.
|
||||
//Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).
|
||||
String String::num_uint64(uint64_t p_num, int base, bool capitalize_hex) {
|
||||
uint64_t n = p_num;
|
||||
|
||||
int chars = 0;
|
||||
do {
|
||||
n /= base;
|
||||
chars++;
|
||||
} while (n);
|
||||
|
||||
String s;
|
||||
s.resize(chars + 1);
|
||||
char *c = s.dataw();
|
||||
c[chars] = 0;
|
||||
n = p_num;
|
||||
do {
|
||||
int mod = n % base;
|
||||
if (mod >= 10) {
|
||||
char a = (capitalize_hex ? 'A' : 'a');
|
||||
c[--chars] = a + (mod - 10);
|
||||
} else {
|
||||
c[--chars] = '0' + mod;
|
||||
}
|
||||
|
||||
n /= base;
|
||||
} while (n);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//Taken from the Godot Engine (MIT License)
|
||||
//Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.
|
||||
//Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).
|
||||
String String::num_real(double p_num, bool p_trailing) {
|
||||
if (Math::is_nan(p_num)) {
|
||||
return "nan";
|
||||
}
|
||||
|
||||
if (Math::is_inf(p_num)) {
|
||||
if (signbit(p_num)) {
|
||||
return "-inf";
|
||||
} else {
|
||||
return "inf";
|
||||
}
|
||||
}
|
||||
|
||||
String s;
|
||||
String sd;
|
||||
|
||||
// Integer part.
|
||||
|
||||
bool neg = p_num < 0;
|
||||
p_num = Math::absd(p_num);
|
||||
int64_t intn = (int64_t)p_num;
|
||||
|
||||
// Decimal part.
|
||||
|
||||
if (intn != p_num) {
|
||||
double dec = p_num - (double)intn;
|
||||
|
||||
int digit = 0;
|
||||
|
||||
#ifdef REAL_T_IS_DOUBLE
|
||||
int decimals = 14;
|
||||
double tolerance = 1e-14;
|
||||
#else
|
||||
int decimals = 6;
|
||||
double tolerance = 1e-6;
|
||||
#endif
|
||||
// We want to align the digits to the above sane default, so we only
|
||||
// need to subtract log10 for numbers with a positive power of ten.
|
||||
if (p_num > 10) {
|
||||
decimals -= (int)floor(log10(p_num));
|
||||
}
|
||||
|
||||
if (decimals > MAX_DECIMALS) {
|
||||
decimals = MAX_DECIMALS;
|
||||
}
|
||||
|
||||
// In case the value ends up ending in "99999", we want to add a
|
||||
// tiny bit to the value we're checking when deciding when to stop,
|
||||
// so we multiply by slightly above 1 (1 + 1e-7 or 1e-15).
|
||||
double check_multiplier = 1 + tolerance / 10;
|
||||
|
||||
int64_t dec_int = 0;
|
||||
int64_t dec_max = 0;
|
||||
|
||||
while (true) {
|
||||
dec *= 10.0;
|
||||
dec_int = dec_int * 10 + (int64_t)dec % 10;
|
||||
dec_max = dec_max * 10 + 9;
|
||||
digit++;
|
||||
|
||||
if ((dec - (double)(int64_t)(dec * check_multiplier)) < tolerance) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (digit == decimals) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dec *= 10;
|
||||
int last = (int64_t)dec % 10;
|
||||
|
||||
if (last > 5) {
|
||||
if (dec_int == dec_max) {
|
||||
dec_int = 0;
|
||||
intn++;
|
||||
} else {
|
||||
dec_int++;
|
||||
}
|
||||
}
|
||||
|
||||
String decimal;
|
||||
for (int i = 0; i < digit; i++) {
|
||||
char num[2] = { 0, 0 };
|
||||
num[0] = '0' + dec_int % 10;
|
||||
decimal = num + decimal;
|
||||
dec_int /= 10;
|
||||
}
|
||||
sd = '.' + decimal;
|
||||
} else if (p_trailing) {
|
||||
sd = ".0";
|
||||
} else {
|
||||
sd = "";
|
||||
}
|
||||
|
||||
if (intn == 0) {
|
||||
s = "0";
|
||||
} else {
|
||||
while (intn) {
|
||||
char32_t num = '0' + (intn % 10);
|
||||
intn /= 10;
|
||||
s = num + s;
|
||||
}
|
||||
}
|
||||
|
||||
s = s + sd;
|
||||
if (neg) {
|
||||
s = "-" + s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
//Taken from the Godot Engine (MIT License)
|
||||
//Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.
|
||||
//Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).
|
||||
String String::num_scientific(double p_num) {
|
||||
if (Math::is_nan(p_num)) {
|
||||
return "nan";
|
||||
}
|
||||
|
||||
if (Math::is_inf(p_num)) {
|
||||
if (signbit(p_num)) {
|
||||
return "-inf";
|
||||
} else {
|
||||
return "inf";
|
||||
}
|
||||
}
|
||||
|
||||
char buf[256];
|
||||
|
||||
#if defined(__GNUC__) || defined(_MSC_VER)
|
||||
|
||||
#if defined(__MINGW32__) && defined(_TWO_DIGIT_EXPONENT) && !defined(_UCRT)
|
||||
// MinGW requires _set_output_format() to conform to C99 output for printf
|
||||
unsigned int old_exponent_format = _set_output_format(_TWO_DIGIT_EXPONENT);
|
||||
#endif
|
||||
snprintf(buf, 256, "%lg", p_num);
|
||||
|
||||
#if defined(__MINGW32__) && defined(_TWO_DIGIT_EXPONENT) && !defined(_UCRT)
|
||||
_set_output_format(old_exponent_format);
|
||||
#endif
|
||||
|
||||
#else
|
||||
sprintf(buf, "%.16lg", p_num);
|
||||
#endif
|
||||
|
||||
buf[255] = 0;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *String::c_str() {
|
||||
return _data;
|
||||
}
|
||||
|
@ -69,8 +69,15 @@ public:
|
||||
std::string to_string() const;
|
||||
void print() const;
|
||||
|
||||
//todo
|
||||
static String num(const int num) { return "1"; }
|
||||
//Taken from the Godot Engine (MIT License)
|
||||
//Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.
|
||||
//Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).
|
||||
static String num(double p_num, int p_decimals = -1);
|
||||
static String num_scientific(double p_num);
|
||||
static String num_real(double p_num, bool p_trailing = true);
|
||||
static String num_int64(int64_t p_num, int base = 10, bool capitalize_hex = false);
|
||||
static String num_uint64(uint64_t p_num, int base = 10, bool capitalize_hex = false);
|
||||
static String chr(char32_t p_char);
|
||||
|
||||
char *c_str();
|
||||
const char *c_str() const;
|
||||
|
Loading…
Reference in New Issue
Block a user