Get rid of gmio_floatXX_t typedefs
This commit is contained in:
parent
8a5f626663
commit
0c15f9f325
@ -152,13 +152,6 @@ enum gmio_bool_value
|
||||
typedef int_or_bool gmio_bool_t;
|
||||
#endif /* GMIO_HAVE_STDBOOL_H */
|
||||
|
||||
/* Float types */
|
||||
/*! Typedef for 32bit real type (float) */
|
||||
typedef float gmio_float32_t;
|
||||
|
||||
/*! Typedef for 64bit real type (double) */
|
||||
typedef double gmio_float64_t;
|
||||
|
||||
/* GMIO_UNUSED */
|
||||
/*! Tells the compiler that a parameter is not used in the body of a function */
|
||||
#define GMIO_UNUSED(x) (void)x;
|
||||
|
@ -20,38 +20,38 @@
|
||||
|
||||
union gmio_uint_float_32
|
||||
{
|
||||
uint32_t as_uint32;
|
||||
gmio_float32_t as_float32;
|
||||
uint32_t as_uint32;
|
||||
float as_float32;
|
||||
};
|
||||
|
||||
union gmio_int_float_32
|
||||
{
|
||||
int32_t as_int32;
|
||||
gmio_float32_t as_float32;
|
||||
int32_t as_int32;
|
||||
float as_float32;
|
||||
};
|
||||
|
||||
GMIO_INLINE gmio_float32_t gmio_convert_ufloat32(uint32_t val)
|
||||
GMIO_INLINE float gmio_convert_ufloat32(uint32_t val)
|
||||
{
|
||||
union gmio_uint_float_32 conv;
|
||||
conv.as_uint32 = val;
|
||||
return conv.as_float32;
|
||||
}
|
||||
|
||||
GMIO_INLINE uint32_t gmio_convert_uint32(gmio_float32_t val)
|
||||
GMIO_INLINE uint32_t gmio_convert_uint32(float val)
|
||||
{
|
||||
union gmio_uint_float_32 conv;
|
||||
conv.as_float32 = val;
|
||||
return conv.as_uint32;
|
||||
}
|
||||
|
||||
GMIO_INLINE gmio_float32_t gmio_convert_sfloat32(int32_t val)
|
||||
GMIO_INLINE float gmio_convert_sfloat32(int32_t val)
|
||||
{
|
||||
union gmio_int_float_32 conv;
|
||||
conv.as_int32 = val;
|
||||
return conv.as_float32;
|
||||
}
|
||||
|
||||
GMIO_INLINE int32_t gmio_convert_int32(gmio_float32_t val)
|
||||
GMIO_INLINE int32_t gmio_convert_int32(float val)
|
||||
{
|
||||
union gmio_int_float_32 conv;
|
||||
conv.as_float32 = val;
|
||||
|
@ -25,6 +25,231 @@ GMIO_INLINE gmio_bool_t is_local_decimal_point(char in)
|
||||
return in == '.';
|
||||
}
|
||||
|
||||
/* #define ASSIMP_FAST_ATOF */
|
||||
#define IRRLICH_FAST_ATOF
|
||||
|
||||
#if defined(ASSIMP_FAST_ATOF)
|
||||
|
||||
static const double fast_atof_table[16] = { // we write [16] here instead of [] to work around a swig bug
|
||||
0.0,
|
||||
0.1,
|
||||
0.01,
|
||||
0.001,
|
||||
0.0001,
|
||||
0.00001,
|
||||
0.000001,
|
||||
0.0000001,
|
||||
0.00000001,
|
||||
0.000000001,
|
||||
0.0000000001,
|
||||
0.00000000001,
|
||||
0.000000000001,
|
||||
0.0000000000001,
|
||||
0.00000000000001,
|
||||
0.000000000000001
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------
|
||||
* Special version of the function, providing higher accuracy and safety
|
||||
* It is mainly used by fast_atof to prevent ugly and unwanted integer overflows.
|
||||
* ------------------------------------------------------------------------------------ */
|
||||
GMIO_INLINE uint64_t strtoul10_64( const char* in, const char** out, unsigned int* max_inout)
|
||||
{
|
||||
unsigned int cur = 0;
|
||||
uint64_t value = 0;
|
||||
const gmio_bool_t running = GMIO_TRUE;
|
||||
|
||||
if ( !gmio_ascii_isdigit(*in) )
|
||||
return value;
|
||||
/* throw std::invalid_argument(std::string("The string \"") + in + "\" cannot be converted into a value."); */
|
||||
|
||||
while ( running )
|
||||
{
|
||||
const uint64_t new_value = ( value * 10 ) + ( *in - '0' );
|
||||
|
||||
if ( !gmio_ascii_isdigit(*in) )
|
||||
break;
|
||||
|
||||
if (new_value < value) /* numeric overflow, we rely on you */
|
||||
return value;
|
||||
/* throw std::overflow_error(std::string("Converting the string \"") + in + "\" into a value resulted in overflow."); */
|
||||
|
||||
value = new_value;
|
||||
|
||||
++in;
|
||||
++cur;
|
||||
|
||||
if (max_inout && *max_inout == cur) {
|
||||
|
||||
if (out) { /* skip to end */
|
||||
while (gmio_ascii_isdigit(*in))
|
||||
++in;
|
||||
*out = in;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
if (out)
|
||||
*out = in;
|
||||
|
||||
if (max_inout)
|
||||
*max_inout = cur;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------
|
||||
* signed variant of strtoul10_64
|
||||
* ------------------------------------------------------------------------------------*/
|
||||
GMIO_INLINE int64_t strtol10_64(const char* in, const char** out, unsigned int* max_inout)
|
||||
{
|
||||
const gmio_bool_t inv = (*in == '-');
|
||||
int64_t value;
|
||||
if (inv || *in == '+')
|
||||
++in;
|
||||
|
||||
value = strtoul10_64(in, out, max_inout);
|
||||
if (inv) {
|
||||
value = -value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/* Number of relevant decimals for floating-point parsing. */
|
||||
#define AI_FAST_ATOF_RELAVANT_DECIMALS 15
|
||||
|
||||
/* ------------------------------------------------------------------------------------
|
||||
* Provides a fast function for converting a string into a float,
|
||||
* about 6 times faster than atof in win32.
|
||||
* If you find any bugs, please send them to me, niko (at) irrlicht3d.org.
|
||||
* ------------------------------------------------------------------------------------*/
|
||||
GMIO_INLINE const char* fast_atoreal_move(const char* c, double* out, gmio_bool_t check_comma)
|
||||
{
|
||||
double f = 0;
|
||||
const gmio_bool_t inv = (*c == '-');
|
||||
|
||||
if (inv || *c == '+') {
|
||||
++c;
|
||||
}
|
||||
|
||||
if ((c[0] == 'N' || c[0] == 'n') && gmio_ascii_strincmp(c, "nan", 3) == 0)
|
||||
{
|
||||
/* TODO: write NAN */
|
||||
/* out = std::numeric_limits<Real>::quiet_NaN(); */
|
||||
c += 3;
|
||||
return c;
|
||||
}
|
||||
|
||||
if ((c[0] == 'I' || c[0] == 'i') && gmio_ascii_strincmp(c, "inf", 3) == 0)
|
||||
{
|
||||
/* TODO: write INF */
|
||||
/* out = std::numeric_limits<Real>::infinity(); */
|
||||
if (inv) {
|
||||
*out = -(*out);
|
||||
}
|
||||
c += 3;
|
||||
if ((c[0] == 'I' || c[0] == 'i') && gmio_ascii_strincmp(c, "inity", 5) == 0)
|
||||
{
|
||||
c += 5;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
if (!gmio_ascii_isdigit(c[0]) &&
|
||||
!((c[0] == '.' || (check_comma && c[0] == ',')) && gmio_ascii_isdigit(c[1])))
|
||||
{
|
||||
return c;
|
||||
/*throw std::invalid_argument("Cannot parse string "
|
||||
"as real number: does not start with digit "
|
||||
"or decimal point followed by digit.");*/
|
||||
}
|
||||
|
||||
if (*c != '.' && (!check_comma || c[0] != ','))
|
||||
{
|
||||
f = (double)strtoul10_64(c, &c, NULL);
|
||||
}
|
||||
|
||||
if ((*c == '.' || (check_comma && c[0] == ',')) && gmio_ascii_isdigit(c[1]))
|
||||
{
|
||||
unsigned int diff = AI_FAST_ATOF_RELAVANT_DECIMALS;
|
||||
double pl;
|
||||
++c;
|
||||
|
||||
/* NOTE: The original implementation is highly inaccurate here. The precision of a single
|
||||
* IEEE 754 float is not high enough, everything behind the 6th digit tends to be more
|
||||
* inaccurate than it would need to be. Casting to double seems to solve the problem.
|
||||
* strtol_64 is used to prevent integer overflow.
|
||||
*
|
||||
* Another fix: this tends to become 0 for long numbers if we don't limit the maximum
|
||||
* number of digits to be read. AI_FAST_ATOF_RELAVANT_DECIMALS can be a value between
|
||||
* 1 and 15. */
|
||||
pl = (double)strtoul10_64(c, &c, &diff);
|
||||
|
||||
pl *= fast_atof_table[diff];
|
||||
f += pl;
|
||||
}
|
||||
/* For backwards compatibility: eat trailing dots, but not trailing commas. */
|
||||
else if (*c == '.') {
|
||||
++c;
|
||||
}
|
||||
|
||||
/* A major 'E' must be allowed. Necessary for proper reading of some DXF files.
|
||||
* Thanks to Zhao Lei to point out that this if() must be outside the if (*c == '.' ..) */
|
||||
if (*c == 'e' || *c == 'E') {
|
||||
const gmio_bool_t einv = (*(c+1)=='-');
|
||||
double exp;
|
||||
|
||||
++c;
|
||||
if (einv || *c=='+') {
|
||||
++c;
|
||||
}
|
||||
|
||||
/* The reason float constants are used here is that we've seen cases where compilers
|
||||
* would perform such casts on compile-time constants at runtime, which would be
|
||||
* bad considering how frequently fast_atoreal_move<float> is called in Assimp. */
|
||||
exp = (double)strtoul10_64(c, &c, NULL);
|
||||
if (einv) {
|
||||
exp = -exp;
|
||||
}
|
||||
f *= pow(10.0, exp);
|
||||
}
|
||||
|
||||
if (inv) {
|
||||
f = -f;
|
||||
}
|
||||
*out = f;
|
||||
return c;
|
||||
}
|
||||
|
||||
GMIO_INLINE float fast_atof(const char* c)
|
||||
{
|
||||
double ret;
|
||||
fast_atoreal_move(c, &ret, GMIO_TRUE);
|
||||
return (float)ret;
|
||||
}
|
||||
|
||||
GMIO_INLINE double fast_atod(const char* c)
|
||||
{
|
||||
double ret;
|
||||
fast_atoreal_move(c, &ret, GMIO_TRUE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GMIO_INLINE float fast_strtof(const char* str, const char** out)
|
||||
{
|
||||
double ret;
|
||||
if (out)
|
||||
*out = fast_atoreal_move(str, &ret, GMIO_TRUE);
|
||||
else
|
||||
fast_atoreal_move(str, &ret, GMIO_TRUE);
|
||||
return (float)ret;
|
||||
}
|
||||
|
||||
|
||||
#elif defined(IRRLICH_FAST_ATOF)
|
||||
|
||||
/* we write [17] here instead of [] to work around a swig bug */
|
||||
static const float fast_atof_table[17] = {
|
||||
0.f,
|
||||
@ -184,5 +409,6 @@ GMIO_INLINE float fast_atof(const char* str)
|
||||
fast_atof_move(str, &ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GMIO_INTERNAL_FAST_ATOF_H */
|
||||
|
@ -15,8 +15,7 @@
|
||||
|
||||
#include "numeric_utils.h"
|
||||
|
||||
gmio_bool_t gmio_float32_ulp_equals(
|
||||
gmio_float32_t a, gmio_float32_t b, uint32_t max_ulp_diff)
|
||||
gmio_bool_t gmio_float32_ulp_equals(float a, float b, uint32_t max_ulp_diff)
|
||||
{
|
||||
const int32_t ia = gmio_convert_int32(a);
|
||||
const int32_t ib = gmio_convert_int32(b);
|
||||
|
@ -28,17 +28,16 @@
|
||||
* See:
|
||||
* http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
|
||||
*/
|
||||
gmio_bool_t gmio_float32_ulp_equals(
|
||||
gmio_float32_t a, gmio_float32_t b, uint32_t max_ulp_diff);
|
||||
gmio_bool_t gmio_float32_ulp_equals(float a, float b, uint32_t max_ulp_diff);
|
||||
|
||||
/*! Count of ULP between \p a and \p b */
|
||||
GMIO_INLINE uint32_t gmio_float32_ulp_diff(gmio_float32_t a, gmio_float32_t b);
|
||||
GMIO_INLINE uint32_t gmio_float32_ulp_diff(float a, float b);
|
||||
|
||||
/*! Portable sign-extraction for int32 */
|
||||
GMIO_INLINE int gmio_int32_sign(int32_t v);
|
||||
|
||||
/*! Portable sign-extraction for float32 */
|
||||
GMIO_INLINE int gmio_float32_sign(gmio_float32_t v);
|
||||
GMIO_INLINE int gmio_float32_sign(float v);
|
||||
|
||||
|
||||
|
||||
@ -46,7 +45,7 @@ GMIO_INLINE int gmio_float32_sign(gmio_float32_t v);
|
||||
* Implementation
|
||||
*/
|
||||
|
||||
uint32_t gmio_float32_ulp_diff(gmio_float32_t a, gmio_float32_t b)
|
||||
uint32_t gmio_float32_ulp_diff(float a, float b)
|
||||
{
|
||||
const uint32_t ua = gmio_convert_uint32(a);
|
||||
const uint32_t ub = gmio_convert_uint32(b);
|
||||
@ -58,7 +57,7 @@ int gmio_int32_sign(int32_t v)
|
||||
return (v & 0x80000000) != 0 ? -1 : 1;
|
||||
}
|
||||
|
||||
int gmio_float32_sign(gmio_float32_t v)
|
||||
int gmio_float32_sign(float v)
|
||||
{
|
||||
return gmio_int32_sign(gmio_convert_int32(v));
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ gmio_bool_t gmio_stringstream_checked_next_chars(
|
||||
#endif
|
||||
|
||||
/*! Parses float from stringstream \p sstream */
|
||||
GMIO_INLINE gmio_float32_t gmio_stringstream_parse_float32(
|
||||
GMIO_INLINE float gmio_stringstream_parse_float32(
|
||||
struct gmio_stringstream* sstream);
|
||||
|
||||
/*! Converts C string \p str to float
|
||||
@ -110,13 +110,13 @@ GMIO_INLINE gmio_float32_t gmio_stringstream_parse_float32(
|
||||
*
|
||||
* TODO: move to another header
|
||||
*/
|
||||
GMIO_INLINE int gmio_get_float32(const char* str, gmio_float32_t* value_ptr);
|
||||
GMIO_INLINE int gmio_get_float32(const char* str, float* value_ptr);
|
||||
|
||||
/*! Converts C string \p str to float
|
||||
*
|
||||
* TODO: move to another header
|
||||
*/
|
||||
GMIO_INLINE gmio_float32_t gmio_to_float32(const char* str);
|
||||
GMIO_INLINE float gmio_to_float32(const char* str);
|
||||
|
||||
|
||||
|
||||
@ -191,7 +191,7 @@ void gmio_stringstream_copy_ascii_spaces(
|
||||
}
|
||||
}
|
||||
|
||||
int gmio_get_float32(const char* str, gmio_float32_t* value_ptr)
|
||||
int gmio_get_float32(const char* str, float* value_ptr)
|
||||
{
|
||||
#if defined(GMIO_STRINGSTREAM_USE_FAST_ATOF)
|
||||
const char* end_ptr = NULL;
|
||||
@ -201,23 +201,23 @@ int gmio_get_float32(const char* str, gmio_float32_t* value_ptr)
|
||||
*value_ptr = strtof(str, &end_ptr);
|
||||
#else
|
||||
char* end_ptr = NULL;
|
||||
*value_ptr = (gmio_float32_t)strtod(str, &end_ptr);
|
||||
*value_ptr = (float)strtod(str, &end_ptr);
|
||||
#endif
|
||||
return (end_ptr == str || errno == ERANGE) ? -1 : 0;
|
||||
}
|
||||
|
||||
gmio_float32_t gmio_to_float32(const char* str)
|
||||
float gmio_to_float32(const char* str)
|
||||
{
|
||||
#if defined(GMIO_STRINGSTREAM_USE_FAST_ATOF)
|
||||
return fast_atof(str);
|
||||
#elif defined(GMIO_HAVE_STRTOF_FUNC) /* Requires C99 */
|
||||
return strtof(str, NULL);
|
||||
#else
|
||||
return (gmio_float32_t)strtod(str, NULL);
|
||||
return (float)strtod(str, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
gmio_float32_t gmio_stringstream_parse_float32(struct gmio_stringstream* sstream)
|
||||
float gmio_stringstream_parse_float32(struct gmio_stringstream* sstream)
|
||||
{
|
||||
#if defined(GMIO_STRINGSTREAM_USE_FAST_ATOF)
|
||||
return gmio_stringstream_fast_atof(sstream);
|
||||
@ -225,7 +225,7 @@ gmio_float32_t gmio_stringstream_parse_float32(struct gmio_stringstream* sstream
|
||||
char strbuff_ptr[64];
|
||||
struct gmio_string strbuff = { &strbuff_ptr[0], 0, sizeof(strbuff_ptr) };
|
||||
gmio_stringstream_eat_word(sstream, &strbuff);
|
||||
return (gmio_float32_t)atof(strbuff_ptr);
|
||||
return (float)atof(strbuff_ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
enum gmio_stl_constants
|
||||
{
|
||||
/*! Compact size of a gmio_stl_coords object */
|
||||
GMIO_STL_COORDS_RAWSIZE = (3 * sizeof(gmio_float32_t)),
|
||||
GMIO_STL_COORDS_RAWSIZE = (3 * sizeof(float)),
|
||||
|
||||
/*! Compact size of a gmio_stl_triangle object, STL ascii format */
|
||||
GMIO_STLA_TRIANGLE_RAWSIZE = (4 * GMIO_STL_COORDS_RAWSIZE),
|
||||
|
@ -31,11 +31,11 @@
|
||||
|
||||
enum { GMIO_FIXED_BUFFER_SIZE = 1024 };
|
||||
|
||||
GMIO_INLINE gmio_float32_t gmio_sqrlen(const struct gmio_stl_coords* c)
|
||||
GMIO_INLINE float gmio_sqrlen(const struct gmio_stl_coords* c)
|
||||
{
|
||||
const gmio_float32_t cx = c->x;
|
||||
const gmio_float32_t cy = c->y;
|
||||
const gmio_float32_t cz = c->z;
|
||||
const float cx = c->x;
|
||||
const float cy = c->y;
|
||||
const float cz = c->z;
|
||||
return cx*cx + cy*cy + cz*cz;
|
||||
}
|
||||
|
||||
|
@ -29,9 +29,9 @@
|
||||
* STL needs (single-float) */
|
||||
struct gmio_stl_coords
|
||||
{
|
||||
gmio_float32_t x;
|
||||
gmio_float32_t y;
|
||||
gmio_float32_t z;
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
|
||||
/*! STL mesh triangle defined three geometric vertices and an
|
||||
|
@ -86,11 +86,11 @@ static void gmio_test_atof_fprintf_err(
|
||||
|
||||
static gmio_bool_t gmio_test_calculation_atof(const char* val_str)
|
||||
{
|
||||
const gmio_float32_t std_val = (gmio_float32_t)strtod(val_str, NULL);
|
||||
const float std_val = (float)strtod(val_str, NULL);
|
||||
int accurate_count = 0;
|
||||
|
||||
{ /* Test fast_atof() */
|
||||
const gmio_float32_t fast_val = fast_atof(val_str);
|
||||
const float fast_val = fast_atof(val_str);
|
||||
if (gmio_float32_ulp_equals(fast_val, std_val, 1))
|
||||
++accurate_count;
|
||||
else
|
||||
@ -105,7 +105,7 @@ static gmio_bool_t gmio_test_calculation_atof(const char* val_str)
|
||||
gmio_stringstream(
|
||||
gmio_istream_buffer(&ibuff),
|
||||
gmio_string(iobuff, 0, sizeof(iobuff)));
|
||||
const gmio_float32_t fast_val = gmio_stringstream_fast_atof(&sstream);
|
||||
const float fast_val = gmio_stringstream_fast_atof(&sstream);
|
||||
if (gmio_float32_ulp_equals(fast_val, std_val, 1)) {
|
||||
++accurate_count;
|
||||
}
|
||||
|
@ -59,8 +59,8 @@ const char* test_platform__global_h()
|
||||
UTEST_ASSERT(sizeof(uint64_t) == 8);
|
||||
#endif
|
||||
|
||||
UTEST_ASSERT(sizeof(gmio_float32_t) == 4);
|
||||
UTEST_ASSERT(sizeof(gmio_float64_t) == 8);
|
||||
UTEST_ASSERT(sizeof(float) == 4);
|
||||
UTEST_ASSERT(sizeof(double) == 8);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user