vrshoot
diff libs/assimp/fast_atof.h @ 0:b2f14e535253
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 01 Feb 2014 19:58:19 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/assimp/fast_atof.h Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,336 @@ 1.4 +// Copyright (C) 2002-2007 Nikolaus Gebhardt 1.5 +// This file is part of the "Irrlicht Engine" and the "irrXML" project. 1.6 +// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h 1.7 + 1.8 +// ------------------------------------------------------------------------------------ 1.9 +// Original description: (Schrompf) 1.10 +// Adapted to the ASSIMP library because the builtin atof indeed takes AGES to parse a 1.11 +// float inside a large string. Before parsing, it does a strlen on the given point. 1.12 +// Changes: 1.13 +// 22nd October 08 (Aramis_acg): Added temporary cast to double, added strtoul10_64 1.14 +// to ensure long numbers are handled correctly 1.15 +// ------------------------------------------------------------------------------------ 1.16 + 1.17 + 1.18 +#ifndef __FAST_A_TO_F_H_INCLUDED__ 1.19 +#define __FAST_A_TO_F_H_INCLUDED__ 1.20 + 1.21 +#include <math.h> 1.22 + 1.23 +namespace Assimp 1.24 +{ 1.25 + 1.26 +const float fast_atof_table[16] = { // we write [16] here instead of [] to work around a swig bug 1.27 + 0.f, 1.28 + 0.1f, 1.29 + 0.01f, 1.30 + 0.001f, 1.31 + 0.0001f, 1.32 + 0.00001f, 1.33 + 0.000001f, 1.34 + 0.0000001f, 1.35 + 0.00000001f, 1.36 + 0.000000001f, 1.37 + 0.0000000001f, 1.38 + 0.00000000001f, 1.39 + 0.000000000001f, 1.40 + 0.0000000000001f, 1.41 + 0.00000000000001f, 1.42 + 0.000000000000001f 1.43 +}; 1.44 + 1.45 + 1.46 +// ------------------------------------------------------------------------------------ 1.47 +// Convert a string in decimal format to a number 1.48 +// ------------------------------------------------------------------------------------ 1.49 +inline unsigned int strtoul10( const char* in, const char** out=0) 1.50 +{ 1.51 + unsigned int value = 0; 1.52 + 1.53 + bool running = true; 1.54 + while ( running ) 1.55 + { 1.56 + if ( *in < '0' || *in > '9' ) 1.57 + break; 1.58 + 1.59 + value = ( value * 10 ) + ( *in - '0' ); 1.60 + ++in; 1.61 + } 1.62 + if (out)*out = in; 1.63 + return value; 1.64 +} 1.65 + 1.66 +// ------------------------------------------------------------------------------------ 1.67 +// Convert a string in octal format to a number 1.68 +// ------------------------------------------------------------------------------------ 1.69 +inline unsigned int strtoul8( const char* in, const char** out=0) 1.70 +{ 1.71 + unsigned int value = 0; 1.72 + 1.73 + bool running = true; 1.74 + while ( running ) 1.75 + { 1.76 + if ( *in < '0' || *in > '7' ) 1.77 + break; 1.78 + 1.79 + value = ( value << 3 ) + ( *in - '0' ); 1.80 + ++in; 1.81 + } 1.82 + if (out)*out = in; 1.83 + return value; 1.84 +} 1.85 + 1.86 +// ------------------------------------------------------------------------------------ 1.87 +// Convert a string in hex format to a number 1.88 +// ------------------------------------------------------------------------------------ 1.89 +inline unsigned int strtoul16( const char* in, const char** out=0) 1.90 +{ 1.91 + unsigned int value = 0; 1.92 + 1.93 + bool running = true; 1.94 + while ( running ) 1.95 + { 1.96 + if ( *in >= '0' && *in <= '9' ) 1.97 + { 1.98 + value = ( value << 4u ) + ( *in - '0' ); 1.99 + } 1.100 + else if (*in >= 'A' && *in <= 'F') 1.101 + { 1.102 + value = ( value << 4u ) + ( *in - 'A' ) + 10; 1.103 + } 1.104 + else if (*in >= 'a' && *in <= 'f') 1.105 + { 1.106 + value = ( value << 4u ) + ( *in - 'a' ) + 10; 1.107 + } 1.108 + else break; 1.109 + ++in; 1.110 + } 1.111 + if (out)*out = in; 1.112 + return value; 1.113 +} 1.114 + 1.115 +// ------------------------------------------------------------------------------------ 1.116 +// Convert just one hex digit 1.117 +// Return value is UINT_MAX if the input character is not a hex digit. 1.118 +// ------------------------------------------------------------------------------------ 1.119 +inline unsigned int HexDigitToDecimal(char in) 1.120 +{ 1.121 + unsigned int out = UINT_MAX; 1.122 + if (in >= '0' && in <= '9') 1.123 + out = in - '0'; 1.124 + 1.125 + else if (in >= 'a' && in <= 'f') 1.126 + out = 10u + in - 'a'; 1.127 + 1.128 + else if (in >= 'A' && in <= 'F') 1.129 + out = 10u + in - 'A'; 1.130 + 1.131 + // return value is UINT_MAX if the input is not a hex digit 1.132 + return out; 1.133 +} 1.134 + 1.135 +// ------------------------------------------------------------------------------------ 1.136 +// Convert a hex-encoded octet (2 characters, i.e. df or 1a). 1.137 +// ------------------------------------------------------------------------------------ 1.138 +inline uint8_t HexOctetToDecimal(const char* in) 1.139 +{ 1.140 + return ((uint8_t)HexDigitToDecimal(in[0])<<4)+(uint8_t)HexDigitToDecimal(in[1]); 1.141 +} 1.142 + 1.143 + 1.144 +// ------------------------------------------------------------------------------------ 1.145 +// signed variant of strtoul10 1.146 +// ------------------------------------------------------------------------------------ 1.147 +inline int strtol10( const char* in, const char** out=0) 1.148 +{ 1.149 + bool inv = (*in=='-'); 1.150 + if (inv || *in=='+') 1.151 + ++in; 1.152 + 1.153 + int value = strtoul10(in,out); 1.154 + if (inv) { 1.155 + value = -value; 1.156 + } 1.157 + return value; 1.158 +} 1.159 + 1.160 +// ------------------------------------------------------------------------------------ 1.161 +// Parse a C++-like integer literal - hex and oct prefixes. 1.162 +// 0xNNNN - hex 1.163 +// 0NNN - oct 1.164 +// NNN - dec 1.165 +// ------------------------------------------------------------------------------------ 1.166 +inline unsigned int strtoul_cppstyle( const char* in, const char** out=0) 1.167 +{ 1.168 + if ('0' == in[0]) 1.169 + { 1.170 + return 'x' == in[1] ? strtoul16(in+2,out) : strtoul8(in+1,out); 1.171 + } 1.172 + return strtoul10(in, out); 1.173 +} 1.174 + 1.175 +// ------------------------------------------------------------------------------------ 1.176 +// Special version of the function, providing higher accuracy and safety 1.177 +// It is mainly used by fast_atof to prevent ugly and unwanted integer overflows. 1.178 +// ------------------------------------------------------------------------------------ 1.179 +inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_inout=0) 1.180 +{ 1.181 + unsigned int cur = 0; 1.182 + uint64_t value = 0; 1.183 + 1.184 + bool running = true; 1.185 + while ( running ) 1.186 + { 1.187 + if ( *in < '0' || *in > '9' ) 1.188 + break; 1.189 + 1.190 + const uint64_t new_value = ( value * 10 ) + ( *in - '0' ); 1.191 + 1.192 + if (new_value < value) /* numeric overflow, we rely on you */ 1.193 + return value; 1.194 + 1.195 + value = new_value; 1.196 + 1.197 + ++in; 1.198 + ++cur; 1.199 + 1.200 + if (max_inout && *max_inout == cur) { 1.201 + 1.202 + if (out) { /* skip to end */ 1.203 + while (*in >= '0' && *in <= '9') 1.204 + ++in; 1.205 + *out = in; 1.206 + } 1.207 + 1.208 + return value; 1.209 + } 1.210 + } 1.211 + if (out) 1.212 + *out = in; 1.213 + 1.214 + if (max_inout) 1.215 + *max_inout = cur; 1.216 + 1.217 + return value; 1.218 +} 1.219 + 1.220 +// Number of relevant decimals for floating-point parsing. 1.221 +#define AI_FAST_ATOF_RELAVANT_DECIMALS 15 1.222 + 1.223 +// ------------------------------------------------------------------------------------ 1.224 +//! Provides a fast function for converting a string into a float, 1.225 +//! about 6 times faster than atof in win32. 1.226 +// If you find any bugs, please send them to me, niko (at) irrlicht3d.org. 1.227 +// ------------------------------------------------------------------------------------ 1.228 +template <typename Real> 1.229 +inline const char* fast_atoreal_move( const char* c, Real& out) 1.230 +{ 1.231 + Real f; 1.232 + 1.233 + bool inv = (*c=='-'); 1.234 + if (inv || *c=='+') { 1.235 + ++c; 1.236 + } 1.237 + 1.238 + f = static_cast<Real>( strtoul10_64 ( c, &c) ); 1.239 + if (*c == '.' || (c[0] == ',' && c[1] >= '0' && c[1] <= '9')) // allow for commas, too 1.240 + { 1.241 + ++c; 1.242 + 1.243 + // NOTE: The original implementation is highly inaccurate here. The precision of a single 1.244 + // IEEE 754 float is not high enough, everything behind the 6th digit tends to be more 1.245 + // inaccurate than it would need to be. Casting to double seems to solve the problem. 1.246 + // strtol_64 is used to prevent integer overflow. 1.247 + 1.248 + // Another fix: this tends to become 0 for long numbers if we don't limit the maximum 1.249 + // number of digits to be read. AI_FAST_ATOF_RELAVANT_DECIMALS can be a value between 1.250 + // 1 and 15. 1.251 + unsigned int diff = AI_FAST_ATOF_RELAVANT_DECIMALS; 1.252 + double pl = static_cast<double>( strtoul10_64 ( c, &c, &diff )); 1.253 + 1.254 + pl *= fast_atof_table[diff]; 1.255 + f += static_cast<Real>( pl ); 1.256 + } 1.257 + 1.258 + // A major 'E' must be allowed. Necessary for proper reading of some DXF files. 1.259 + // Thanks to Zhao Lei to point out that this if() must be outside the if (*c == '.' ..) 1.260 + if (*c == 'e' || *c == 'E') { 1.261 + 1.262 + ++c; 1.263 + const bool einv = (*c=='-'); 1.264 + if (einv || *c=='+') { 1.265 + ++c; 1.266 + } 1.267 + 1.268 + // The reason float constants are used here is that we've seen cases where compilers 1.269 + // would perform such casts on compile-time constants at runtime, which would be 1.270 + // bad considering how frequently fast_atoreal_move<float> is called in Assimp. 1.271 + Real exp = static_cast<Real>( strtoul10_64(c, &c) ); 1.272 + if (einv) { 1.273 + exp = -exp; 1.274 + } 1.275 + f *= pow(static_cast<Real>(10.0f), exp); 1.276 + } 1.277 + 1.278 + if (inv) { 1.279 + f = -f; 1.280 + } 1.281 + out = f; 1.282 + return c; 1.283 +} 1.284 + 1.285 +// ------------------------------------------------------------------------------------ 1.286 +// The same but more human. 1.287 +inline float fast_atof(const char* c) 1.288 +{ 1.289 + float ret; 1.290 + fast_atoreal_move<float>(c, ret); 1.291 + return ret; 1.292 +} 1.293 + 1.294 + 1.295 +inline float fast_atof( const char* c, const char** cout) 1.296 +{ 1.297 + float ret; 1.298 + *cout = fast_atoreal_move<float>(c, ret); 1.299 + 1.300 + return ret; 1.301 +} 1.302 + 1.303 +inline float fast_atof( const char** inout) 1.304 +{ 1.305 + float ret; 1.306 + *inout = fast_atoreal_move<float>(*inout, ret); 1.307 + 1.308 + return ret; 1.309 +} 1.310 + 1.311 + 1.312 +inline double fast_atod(const char* c) 1.313 +{ 1.314 + double ret; 1.315 + fast_atoreal_move<double>(c, ret); 1.316 + return ret; 1.317 +} 1.318 + 1.319 + 1.320 +inline double fast_atod( const char* c, const char** cout) 1.321 +{ 1.322 + double ret; 1.323 + *cout = fast_atoreal_move<double>(c, ret); 1.324 + 1.325 + return ret; 1.326 +} 1.327 + 1.328 +inline double fast_atod( const char** inout) 1.329 +{ 1.330 + double ret; 1.331 + *inout = fast_atoreal_move<double>(*inout, ret); 1.332 + 1.333 + return ret; 1.334 +} 1.335 + 1.336 +} // end of namespace Assimp 1.337 + 1.338 +#endif 1.339 +