fast_atof.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. // Copyright (C) 2008-2012 Colin MacDonald
  2. // No rights reserved: this software is in the public domain.
  3. #include "testUtils.h"
  4. using namespace irr;
  5. using namespace core;
  6. //! This was an older Irrlicht implementation, tested against for reference.
  7. static inline u32 old_strtol10(const char* in, const char** out=0)
  8. {
  9. u32 value = 0;
  10. while ( ( *in >= '0') && ( *in <= '9' ))
  11. {
  12. value = ( value * 10 ) + ( *in - '0' );
  13. ++in;
  14. }
  15. if (out)
  16. *out = in;
  17. return value;
  18. }
  19. //! This was an older Irrlicht implementation, tested against for reference.
  20. static inline const char* old_fast_atof_move( const char* c, float& out)
  21. {
  22. bool inv = false;
  23. const char *t;
  24. float f;
  25. if (*c=='-')
  26. {
  27. ++c;
  28. inv = true;
  29. }
  30. //f = (float)strtol(c, &t, 10);
  31. f = (float) old_strtol10 ( c, &c );
  32. if (*c == '.')
  33. {
  34. ++c;
  35. //float pl = (float)strtol(c, &t, 10);
  36. float pl = (float) old_strtol10 ( c, &t );
  37. pl *= fast_atof_table[t-c];
  38. f += pl;
  39. c = t;
  40. if (*c == 'e')
  41. {
  42. ++c;
  43. //float exp = (float)strtol(c, &t, 10);
  44. bool einv = (*c=='-');
  45. if (einv)
  46. ++c;
  47. float exp = (float)old_strtol10(c, &c);
  48. if (einv)
  49. exp *= -1.0f;
  50. f *= (float)pow(10.0f, exp);
  51. }
  52. }
  53. if (inv)
  54. f *= -1.0f;
  55. out = f;
  56. return c;
  57. }
  58. //! This was an older Irrlicht implementation, tested against for reference.
  59. static inline float old_fast_atof(const char* c)
  60. {
  61. float ret;
  62. old_fast_atof_move(c, ret);
  63. return ret;
  64. }
  65. static bool testCalculation_atof(const char * valueString)
  66. {
  67. const f32 newFastValue = fast_atof(valueString);
  68. const f32 oldFastValue = old_fast_atof(valueString);
  69. const f32 atofValue = (f32)atof(valueString);
  70. logTestString("\n String '%s'\n New fast %.40f\n Old fast %.40f\n atof %.40f\n",
  71. valueString, newFastValue, oldFastValue, atofValue);
  72. const f32 diffNew = fabs(newFastValue - atofValue) ;
  73. const f32 diffOld = fabs(newFastValue - atofValue) ;
  74. bool accurate = diffNew <= diffOld || equalsByUlp(diffNew, diffOld, 1);
  75. if(!accurate)
  76. logTestString("*** ERROR - less accurate than old method ***\n\n");
  77. return accurate;
  78. }
  79. static bool testCalculation_strtol(const char * valueString)
  80. {
  81. const s32 newFastValue = strtol10(valueString);
  82. const s32 oldFastValue = old_strtol10(valueString);
  83. const s32 strtolValue = (s32)clamp(strtol(valueString, 0, 10), (long int)INT_MIN, (long int)INT_MAX);
  84. logTestString("\n String '%s'\n New fast %d\n Old fast %d\n strtol %d\n",
  85. valueString, newFastValue, oldFastValue, strtolValue);
  86. bool accurate = (newFastValue == strtolValue) || (oldFastValue != strtolValue);
  87. if (!accurate)
  88. logTestString("*** ERROR - wrong calculation in new method ***\n\n");
  89. return accurate;
  90. }
  91. //! Test both the accuracy and speed of Irrlicht's fast_atof() implementation.
  92. bool test_fast_atof(void)
  93. {
  94. bool accurate = true;
  95. accurate &= testCalculation_atof("340282346638528859811704183484516925440.000000");
  96. accurate &= testCalculation_atof("3.402823466e+38F");
  97. accurate &= testCalculation_atof("3402823466e+29F");
  98. accurate &= testCalculation_atof("-340282346638528859811704183484516925440.000000");
  99. accurate &= testCalculation_atof("-3.402823466e+38F");
  100. accurate &= testCalculation_atof("-3402823466e+29F");
  101. accurate &= testCalculation_atof("34028234663852885981170418348451692544.000000");
  102. accurate &= testCalculation_atof("3.402823466e+37F");
  103. accurate &= testCalculation_atof("3402823466e+28F");
  104. accurate &= testCalculation_atof("-34028234663852885981170418348451692544.000000");
  105. accurate &= testCalculation_atof("-3.402823466e+37F");
  106. accurate &= testCalculation_atof("-3402823466e+28F");
  107. accurate &= testCalculation_atof(".00234567");
  108. accurate &= testCalculation_atof("-.00234567");
  109. accurate &= testCalculation_atof("0.00234567");
  110. accurate &= testCalculation_atof("-0.00234567");
  111. accurate &= testCalculation_atof("1.175494351e-38F");
  112. accurate &= testCalculation_atof("1175494351e-47F");
  113. accurate &= testCalculation_atof("1.175494351e-37F");
  114. accurate &= testCalculation_atof("1.175494351e-36F");
  115. accurate &= testCalculation_atof("-1.175494351e-36F");
  116. accurate &= testCalculation_atof("123456.789");
  117. accurate &= testCalculation_atof("-123456.789");
  118. accurate &= testCalculation_atof("0000123456.789");
  119. accurate &= testCalculation_atof("-0000123456.789");
  120. accurate &= testCalculation_atof("-0.0690462109446526");
  121. if (!accurate)
  122. {
  123. logTestString("Calculation is not accurate, so the speed is irrelevant\n");
  124. return false;
  125. }
  126. #ifndef _DEBUG // it's only faster in release
  127. IrrlichtDevice* device = createDevice(video::EDT_NULL);
  128. if (!device)
  129. return false;
  130. ITimer* timer = device->getTimer();
  131. const int ITERATIONS = 100000;
  132. int i;
  133. f32 value;
  134. u32 then = timer->getRealTime();
  135. for(i = 0; i < ITERATIONS; ++i)
  136. value = (f32)atof("-340282346638528859811704183484516925440.000000");
  137. const u32 atofTime = timer->getRealTime() - then;
  138. then += atofTime;
  139. for(i = 0; i < ITERATIONS; ++i)
  140. value = fast_atof("-340282346638528859811704183484516925440.000000");
  141. const u32 fastAtofTime = timer->getRealTime() - then;
  142. then += fastAtofTime;
  143. for(i = 0; i < ITERATIONS; ++i)
  144. value = old_fast_atof("-340282346638528859811704183484516925440.000000");
  145. const u32 oldFastAtofTime = timer->getRealTime() - then;
  146. logTestString("Speed test\n atof time = %d\n fast_atof Time = %d\nold fast_atof time = %d\n",
  147. atofTime, fastAtofTime, oldFastAtofTime);
  148. device->closeDevice();
  149. device->run();
  150. device->drop();
  151. if(fastAtofTime > (1.2f*atofTime))
  152. {
  153. logTestString("The fast method is slower than atof()\n");
  154. return false;
  155. }
  156. #endif // #ifndef _DEBUG
  157. return true;
  158. }
  159. //! Test both the accuracy and speed of Irrlicht's strtol10() implementation.
  160. bool test_strtol(void)
  161. {
  162. bool accurate = true;
  163. accurate &= testCalculation_strtol("340282346638528859811704183484516925440");
  164. accurate &= testCalculation_strtol("3402823466");
  165. accurate &= testCalculation_strtol("3402823466e+29F");
  166. accurate &= testCalculation_strtol("-340282346638528859811704183484516925440");
  167. accurate &= testCalculation_strtol("-3402823466");
  168. accurate &= testCalculation_strtol("-3402823466e+29F");
  169. accurate &= testCalculation_strtol("402823466385288598117");
  170. accurate &= testCalculation_strtol("402823466");
  171. accurate &= testCalculation_strtol("402823466e+28F");
  172. accurate &= testCalculation_strtol("402823466385288598117");
  173. accurate &= testCalculation_strtol("-402823466");
  174. accurate &= testCalculation_strtol("-402823466e+28F");
  175. accurate &= testCalculation_strtol(".00234567");
  176. accurate &= testCalculation_strtol("-234567");
  177. accurate &= testCalculation_strtol("234567");
  178. accurate &= testCalculation_strtol("-234567");
  179. accurate &= testCalculation_strtol("1175494351");
  180. accurate &= testCalculation_strtol("11754943512");
  181. accurate &= testCalculation_strtol("11754943513");
  182. accurate &= testCalculation_strtol("11754943514");
  183. accurate &= testCalculation_strtol("-1175494351");
  184. accurate &= testCalculation_strtol("123456789");
  185. accurate &= testCalculation_strtol("-123456789");
  186. accurate &= testCalculation_strtol("123456.789");
  187. accurate &= testCalculation_strtol("-123456.789");
  188. accurate &= testCalculation_strtol("-109446526");
  189. if(!accurate)
  190. {
  191. logTestString("Calculation is not accurate, so the speed is irrelevant\n");
  192. return false;
  193. }
  194. #ifndef _DEBUG // it's only faster in release
  195. IrrlichtDevice* device = createDevice(video::EDT_NULL);
  196. if (!device)
  197. return false;
  198. ITimer* timer = device->getTimer();
  199. const int ITERATIONS = 1000000;
  200. int i;
  201. s32 value;
  202. u32 then = timer->getRealTime();
  203. for(i = 0; i < ITERATIONS; ++i)
  204. value = strtol("-3402823466", 0, 10);
  205. const u32 strtolTime = timer->getRealTime() - then;
  206. then += strtolTime;
  207. for(i = 0; i < ITERATIONS; ++i)
  208. value = strtol10("-3402823466");
  209. const u32 strtol10Time = timer->getRealTime() - then;
  210. then += strtol10Time;
  211. for(i = 0; i < ITERATIONS; ++i)
  212. value = old_strtol10("-3402823466");
  213. const u32 oldstrtol10Time = timer->getRealTime() - then;
  214. logTestString("Speed test\n strtol time = %d\n strtol10 time = %d\nold strtol10 time = %d\n",
  215. strtolTime, strtol10Time, oldstrtol10Time);
  216. device->closeDevice();
  217. device->run();
  218. device->drop();
  219. if (strtol10Time > (1.2f*strtolTime))
  220. {
  221. logTestString("The fast method is slower than strtol()\n");
  222. return false;
  223. }
  224. #endif // #ifndef _DEBUG
  225. return true;
  226. }
  227. bool fast_atof(void)
  228. {
  229. bool ok = true;
  230. ok &= test_fast_atof() ;
  231. ok &= test_strtol();
  232. return ok;
  233. }