fixed.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. /*! ========================================================================
  2. ** Extended Template and Library Test Suite
  3. ** Fixed-Point Math Test
  4. **
  5. ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
  6. ** Copyright (c) 2007 Chris Moore
  7. **
  8. ** This package is free software; you can redistribute it and/or
  9. ** modify it under the terms of the GNU General Public License as
  10. ** published by the Free Software Foundation; either version 2 of
  11. ** the License, or (at your option) any later version.
  12. **
  13. ** This package is distributed in the hope that it will be useful,
  14. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. ** General Public License for more details.
  17. **
  18. ** === N O T E S ===========================================================
  19. **
  20. ** ========================================================================= */
  21. #define ETL_FIXED_BITS 12
  22. #include <ETL/fixed>
  23. #include <stdio.h>
  24. #include <ETL/clock>
  25. #ifndef PI
  26. # define PI (3.1415926535897932384626433832795029L)
  27. #endif
  28. #define ADD_SUB_TEST 20000000
  29. #define MUL_TEST 10000000
  30. #define DIV_TEST 1048573 // at 1048573, fixed point numbers wrap around to zero
  31. using namespace etl;
  32. template <class value_type>
  33. struct speed_test {
  34. double add_sub_test(void)
  35. {
  36. value_type a = 1;
  37. value_type b = 2;
  38. value_type c = 3;
  39. int i;
  40. etl::clock MyTimer;
  41. MyTimer.reset();
  42. for (i = 0; i < ADD_SUB_TEST; i++) {
  43. a += a;
  44. a -= b;
  45. a -= c;
  46. a += a;
  47. a += a;
  48. a -= b;
  49. a -= c;
  50. a += a;
  51. a += a;
  52. a -= b;
  53. a -= c;
  54. a += a;
  55. a += a;
  56. a -= b;
  57. a -= c;
  58. a += a;
  59. a += a;
  60. a -= b;
  61. a -= c;
  62. a += a;
  63. a += a;
  64. a -= b;
  65. a -= c;
  66. a += a;
  67. a += a;
  68. a -= b;
  69. a -= c;
  70. a += a;
  71. }
  72. fprintf(stderr, "[%1d]...", int(int(a) / 1e9) + 5); // so the compiler doesn't optimize everything out
  73. return MyTimer();
  74. }
  75. double mul_test(void)
  76. {
  77. value_type a, b, c, d;
  78. a = value_type(2.25);
  79. b = value_type(2);
  80. c = value_type(4.5);
  81. d = value_type(1);
  82. const value_type one_and_a_half(static_cast<value_type>(1.5));
  83. int i;
  84. etl::clock MyTimer;
  85. MyTimer.reset();
  86. for (i = 1; i < MUL_TEST; i++) {
  87. d *= a;
  88. d *= b;
  89. d *= c;
  90. d *= 3;
  91. d *= i;
  92. b *= c;
  93. b *= d;
  94. b *= d;
  95. b *= 3;
  96. c *= d;
  97. c *= one_and_a_half;
  98. c *= a;
  99. c *= b;
  100. c *= 3;
  101. a *= c;
  102. a *= b;
  103. a *= 3;
  104. d *= a;
  105. d *= b;
  106. d *= c;
  107. d *= 3;
  108. d *= i;
  109. b *= c;
  110. b *= d;
  111. b *= d;
  112. b *= 3;
  113. c *= d;
  114. c *= one_and_a_half;
  115. c *= a;
  116. c *= b;
  117. c *= 3;
  118. a *= c;
  119. a *= b;
  120. a *= 3;
  121. d *= a;
  122. d *= b;
  123. d *= c;
  124. d *= 3;
  125. d *= i;
  126. b *= c;
  127. b *= d;
  128. b *= d;
  129. b *= 3;
  130. c *= d;
  131. c *= one_and_a_half;
  132. c *= a;
  133. c *= b;
  134. c *= 3;
  135. a *= c;
  136. a *= b;
  137. a *= 3;
  138. d *= a;
  139. d *= b;
  140. d *= c;
  141. d *= 3;
  142. d *= i;
  143. b *= c;
  144. b *= d;
  145. b *= d;
  146. b *= 3;
  147. c *= d;
  148. c *= one_and_a_half;
  149. c *= a;
  150. c *= b;
  151. c *= 3;
  152. a *= c;
  153. a *= b;
  154. a *= 3;
  155. d *= a;
  156. d *= b;
  157. d *= c;
  158. d *= 3;
  159. d *= i;
  160. b *= c;
  161. b *= d;
  162. b *= d;
  163. b *= 3;
  164. c *= d;
  165. c *= one_and_a_half;
  166. c *= a;
  167. c *= b;
  168. c *= 3;
  169. a *= c;
  170. a *= b;
  171. a *= 3;
  172. d *= a;
  173. d *= b;
  174. d *= c;
  175. d *= 3;
  176. d *= i;
  177. b *= c;
  178. b *= d;
  179. b *= d;
  180. b *= 3;
  181. c *= d;
  182. c *= one_and_a_half;
  183. c *= a;
  184. c *= b;
  185. c *= 3;
  186. a *= c;
  187. a *= b;
  188. a *= 3;
  189. d *= a;
  190. d *= b;
  191. d *= c;
  192. d *= 3;
  193. d *= i;
  194. b *= c;
  195. b *= d;
  196. b *= d;
  197. b *= 3;
  198. c *= d;
  199. c *= one_and_a_half;
  200. c *= a;
  201. c *= b;
  202. c *= 3;
  203. a *= c;
  204. a *= b;
  205. a *= 3;
  206. }
  207. fprintf(stderr, "[%1d]...", int(int(a) / 1e9) + 5); // so the compiler doesn't optimize everything out
  208. return MyTimer();
  209. }
  210. double div_test(void)
  211. {
  212. value_type a(30);
  213. value_type b(40);
  214. value_type acc(0);
  215. int i, j;
  216. etl::clock MyTimer;
  217. MyTimer.reset();
  218. for (j = 0; j < 10; j++)
  219. for (i = 1; i < DIV_TEST; i++) {
  220. a = 3 + i;
  221. b = 40 + i;
  222. b /= a;
  223. a /= (i % 20) + 1;
  224. acc += a;
  225. a = 3 + i;
  226. b = 40 + i;
  227. b /= a;
  228. a /= (i % 20) + 1;
  229. acc += a;
  230. a = 3 + i;
  231. b = 40 + i;
  232. b /= a;
  233. a /= (i % 20) + 1;
  234. acc += a;
  235. a = 3 + i;
  236. b = 40 + i;
  237. b /= a;
  238. a /= (i % 20) + 1;
  239. acc += a;
  240. a = 3 + i;
  241. b = 40 + i;
  242. b /= a;
  243. a /= (i % 20) + 1;
  244. acc += a;
  245. a = 3 + i;
  246. b = 40 + i;
  247. b /= a;
  248. a /= (i % 20) + 1;
  249. acc += a;
  250. }
  251. fprintf(stderr, "[%1d]...", int(int(acc) / 1e9) + 5); // so the compiler doesn't optimize everything out
  252. return MyTimer();
  253. }
  254. };
  255. int basic_test(void)
  256. {
  257. int ret = 0;
  258. fixed a, b, c;
  259. double d;
  260. a = -1;
  261. a = std::abs(a);
  262. if (a != fixed(1)) {
  263. fprintf(stderr, "fixed: abs() failure on line %d in "__FILE__".\n", __LINE__);
  264. ret++;
  265. }
  266. d = (double)(fixed(2.5) * fixed(3.0f) / 7) - (2.5f * 3.0f / 7.0f);
  267. fprintf(stderr, "fixed: 2.5 * 2 / 7 --- Difference: %f\n", d);
  268. if (d < 0.0) {
  269. d = -d;
  270. }
  271. if (d > 0.0005) {
  272. fprintf(stderr, "fixed: Failed test on line %d in "__FILE__".\n", __LINE__);
  273. ret++;
  274. }
  275. a = 1043;
  276. d = 1043;
  277. a /= 27;
  278. d /= 27;
  279. a += 10.42;
  280. d += 10.42;
  281. a /= 6;
  282. d /= 6;
  283. a *= PI;
  284. d *= PI;
  285. d -= (double)a;
  286. fprintf(stderr, "fixed: ( 1043 / 27 + 10.42 ) / 6 * PI --- Difference: %f\n", d);
  287. if (d < 0.0) {
  288. d = -d;
  289. }
  290. #ifdef ROUND_TO_NEAREST_INTEGER
  291. if (d > 0.0005)
  292. #else
  293. if (d > 0.0025)
  294. #endif
  295. {
  296. fprintf(stderr, "fixed: Failed test on line %d in "__FILE__".\n", __LINE__);
  297. ret++;
  298. }
  299. return ret;
  300. }
  301. int char_test(void)
  302. {
  303. int ret = 0;
  304. fixed_base<unsigned char, 8> fix;
  305. double flt;
  306. if (sizeof(fix) != sizeof(unsigned char)) {
  307. ret++;
  308. fprintf(stderr, "fixed: Size of fixed_base<unsigned char,8> is wrong!\n");
  309. }
  310. flt = 1.0;
  311. fix = 1.0;
  312. fprintf(stderr, "fixed: value=%f, data=%d, shouldbe=%f, error=%f\n", (float)fix, fix.data(), flt, (float)fix - flt);
  313. flt *= 0.7;
  314. fix *= 0.7;
  315. fprintf(stderr, "fixed: value=%f, data=%d, shouldbe=%f, error=%f\n", (float)fix, fix.data(), flt, (float)fix - flt);
  316. flt *= 0.7;
  317. fix *= 0.7;
  318. fprintf(stderr, "fixed: value=%f, data=%d, shouldbe=%f, error=%f\n", (float)fix, fix.data(), flt, (float)fix - flt);
  319. flt *= 0.7;
  320. fix *= 0.7;
  321. fprintf(stderr, "fixed: value=%f, data=%d, shouldbe=%f, error=%f\n", (float)fix, fix.data(), flt, (float)fix - flt);
  322. flt *= 0.7;
  323. fix *= 0.7;
  324. fprintf(stderr, "fixed: value=%f, data=%d, shouldbe=%f, error=%f\n", (float)fix, fix.data(), flt, (float)fix - flt);
  325. flt *= 0.7;
  326. fix *= 0.7;
  327. fprintf(stderr, "fixed: value=%f, data=%d, shouldbe=%f, error=%f\n", (float)fix, fix.data(), flt, (float)fix - flt);
  328. // fix/=0.7;
  329. // fprintf(stderr,"fixed: value=%f, data=%d, shouldbe=%f, error=%f\n",(float)fix,fix.data(),flt,(float)fix-flt);
  330. flt += 0.3;
  331. fix += 0.3;
  332. fprintf(stderr, "fixed: value=%f, data=%d, shouldbe=%f, error=%f\n", (float)fix, fix.data(), flt, (float)fix - flt);
  333. flt *= 2;
  334. fix *= 2;
  335. fprintf(stderr, "fixed: value=%f, data=%d, shouldbe=%f, error=%f\n", (float)fix, fix.data(), flt, (float)fix - flt);
  336. return ret;
  337. }
  338. int main()
  339. {
  340. int error = 0;
  341. error += basic_test();
  342. error += char_test();
  343. speed_test<float> float_test;
  344. speed_test<int> int_test;
  345. speed_test<fixed> fixed_test;
  346. {
  347. double flt, fix, inte;
  348. fprintf(stderr, "\nAddition/subtraction test...\n");
  349. fprintf(stderr, " calculating float.....");
  350. flt = float_test.add_sub_test();
  351. fprintf(stderr, " float time: %f sec\n", flt);
  352. fprintf(stderr, " calculating fixed.....");
  353. fix = fixed_test.add_sub_test();
  354. fprintf(stderr, " fixed time: %f sec\n", fix);
  355. fprintf(stderr, " calculating integer...");
  356. inte = int_test.add_sub_test();
  357. fprintf(stderr, " integer time: %f sec\n", inte);
  358. if (flt > fix) {
  359. fprintf(stderr, "Fixed point wins by %f seconds! (%f%% faster)\n", flt - fix, flt / fix * 100.0f - 100.0f);
  360. } else {
  361. fprintf(stderr, "Floating point wins by %f seconds! (%f%% faster)\n", fix - flt, fix / flt * 100.0f - 100.0f);
  362. }
  363. }
  364. {
  365. double flt, fix, inte;
  366. fprintf(stderr, "\nProduct test...\n");
  367. fprintf(stderr, " calculating float.....");
  368. flt = float_test.mul_test();
  369. fprintf(stderr, " float time: %f sec\n", flt);
  370. fprintf(stderr, " calculating fixed.....");
  371. fix = fixed_test.mul_test();
  372. fprintf(stderr, " fixed time: %f sec\n", fix);
  373. fprintf(stderr, " calculating integer...");
  374. inte = int_test.mul_test();
  375. fprintf(stderr, " integer time: %f sec\n", inte);
  376. if (flt > fix) {
  377. fprintf(stderr, "Fixed point wins by %f seconds! (%f%% faster)\n", flt - fix, flt / fix * 100.0f - 100.0f);
  378. } else {
  379. fprintf(stderr, "Floating point wins by %f seconds! (%f%% faster)\n", fix - flt, fix / flt * 100.0f - 100.0f);
  380. }
  381. }
  382. {
  383. double flt, fix, inte;
  384. fprintf(stderr, "\nDivision test...\n");
  385. fprintf(stderr, " calculating float.....");
  386. flt = float_test.div_test();
  387. fprintf(stderr, " float time: %f sec\n", flt);
  388. fprintf(stderr, " calculating fixed.....");
  389. fix = fixed_test.div_test();
  390. fprintf(stderr, " fixed time: %f sec\n", fix);
  391. fprintf(stderr, " calculating integer...");
  392. inte = int_test.div_test();
  393. fprintf(stderr, " integer time: %f sec\n", inte);
  394. if (flt > fix) {
  395. fprintf(stderr, "Fixed point wins by %f seconds! (%f%% faster)\n", flt - fix, flt / fix * 100.0f - 100.0f);
  396. } else {
  397. fprintf(stderr, "Floating point wins by %f seconds! (%f%% faster)\n", fix - flt, fix / flt * 100.0f - 100.0f);
  398. }
  399. fprintf(stderr, "\n");
  400. }
  401. return error;
  402. }