fix16_unittests.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. #include <fix16.h>
  2. #include <stdio.h>
  3. #include <math.h>
  4. #include <stdbool.h>
  5. #include "unittests.h"
  6. const fix16_t testcases[] = {
  7. // Small numbers
  8. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
  9. -1, -2, -3, -4, -5, -6, -7, -8, -9, -10,
  10. // Integer numbers
  11. 0x10000, -0x10000, 0x20000, -0x20000, 0x30000, -0x30000,
  12. 0x40000, -0x40000, 0x50000, -0x50000, 0x60000, -0x60000,
  13. // Fractions (1/2, 1/4, 1/8)
  14. 0x8000, -0x8000, 0x4000, -0x4000, 0x2000, -0x2000,
  15. // Problematic carry
  16. 0xFFFF, -0xFFFF, 0x1FFFF, -0x1FFFF, 0x3FFFF, -0x3FFFF,
  17. // Smallest and largest values
  18. 0x7FFFFFFF, 0x80000000,
  19. // Large random numbers
  20. 831858892, 574794913, 2147272293, -469161054, -961611615,
  21. 1841960234, 1992698389, 520485404, 560523116, -2094993050,
  22. -876897543, -67813629, 2146227091, 509861939, -1073573657,
  23. // Small random numbers
  24. -14985, 30520, -83587, 41129, 42137, 58537, -2259, 84142,
  25. -28283, 90914, 19865, 33191, 81844, -66273, -63215, -44459,
  26. -11326, 84295, 47515, -39324,
  27. // Tiny random numbers
  28. -171, -359, 491, 844, 158, -413, -422, -737, -575, -330,
  29. -376, 435, -311, 116, 715, -1024, -487, 59, 724, 993
  30. };
  31. #define TESTCASES_COUNT (sizeof(testcases)/sizeof(testcases[0]))
  32. #define delta(a,b) (((a)>=(b)) ? (a)-(b) : (b)-(a))
  33. #ifdef FIXMATH_NO_ROUNDING
  34. const fix16_t max_delta = 1;
  35. #else
  36. const fix16_t max_delta = 0;
  37. #endif
  38. int main()
  39. {
  40. int status = 0;
  41. {
  42. COMMENT("Testing basic multiplication");
  43. TEST(fix16_mul(fix16_from_int(5), fix16_from_int(5)) == fix16_from_int(25));
  44. TEST(fix16_mul(fix16_from_int(-5), fix16_from_int(5)) == fix16_from_int(-25));
  45. TEST(fix16_mul(fix16_from_int(-5), fix16_from_int(-5)) == fix16_from_int(25));
  46. TEST(fix16_mul(fix16_from_int(5), fix16_from_int(-5)) == fix16_from_int(-25));
  47. }
  48. #ifndef FIXMATH_NO_ROUNDING
  49. {
  50. COMMENT("Testing multiplication rounding corner cases");
  51. TEST(fix16_mul(0, 10) == 0);
  52. TEST(fix16_mul(2, 0x8000) == 1);
  53. TEST(fix16_mul(-2, 0x8000) == -1);
  54. TEST(fix16_mul(3, 0x8000) == 2);
  55. TEST(fix16_mul(-3, 0x8000) == -2);
  56. TEST(fix16_mul(2, 0x7FFF) == 1);
  57. TEST(fix16_mul(-2, 0x7FFF) == -1);
  58. TEST(fix16_mul(2, 0x8001) == 1);
  59. TEST(fix16_mul(-2, 0x8001) == -1);
  60. }
  61. #endif
  62. {
  63. unsigned int i, j;
  64. int failures = 0;
  65. COMMENT("Running testcases for multiplication");
  66. for (i = 0; i < TESTCASES_COUNT; i++)
  67. {
  68. for (j = 0; j < TESTCASES_COUNT; j++)
  69. {
  70. fix16_t a = testcases[i];
  71. fix16_t b = testcases[j];
  72. fix16_t result = fix16_mul(a, b);
  73. double fa = fix16_to_dbl(a);
  74. double fb = fix16_to_dbl(b);
  75. fix16_t fresult = fix16_from_dbl(fa * fb);
  76. double max = fix16_to_dbl(fix16_maximum);
  77. double min = fix16_to_dbl(fix16_minimum);
  78. if (delta(fresult, result) > max_delta)
  79. {
  80. if (fa * fb > max || fa * fb < min)
  81. {
  82. #ifndef FIXMATH_NO_OVERFLOW
  83. if (result != fix16_overflow)
  84. {
  85. printf("\n%d * %d overflow not detected!\n", a, b);
  86. failures++;
  87. }
  88. #endif
  89. // Legitimate overflow
  90. continue;
  91. }
  92. printf("\n%d * %d = %d\n", a, b, result);
  93. printf("%f * %f = %d\n", fa, fb, fresult);
  94. failures++;
  95. }
  96. }
  97. }
  98. TEST(failures == 0);
  99. }
  100. {
  101. COMMENT("Testing basic division");
  102. TEST(fix16_div(fix16_from_int(15), fix16_from_int(5)) == fix16_from_int(3));
  103. TEST(fix16_div(fix16_from_int(-15), fix16_from_int(5)) == fix16_from_int(-3));
  104. TEST(fix16_div(fix16_from_int(-15), fix16_from_int(-5)) == fix16_from_int(3));
  105. TEST(fix16_div(fix16_from_int(15), fix16_from_int(-5)) == fix16_from_int(-3));
  106. }
  107. #ifndef FIXMATH_NO_ROUNDING
  108. {
  109. COMMENT("Testing division rounding corner cases");
  110. TEST(fix16_div(0, 10) == 0);
  111. TEST(fix16_div(1, fix16_from_int(2)) == 1);
  112. TEST(fix16_div(-1, fix16_from_int(2)) == -1);
  113. TEST(fix16_div(1, fix16_from_int(-2)) == -1);
  114. TEST(fix16_div(-1, fix16_from_int(-2)) == 1);
  115. TEST(fix16_div(3, fix16_from_int(2)) == 2);
  116. TEST(fix16_div(-3, fix16_from_int(2)) == -2);
  117. TEST(fix16_div(3, fix16_from_int(-2)) == -2);
  118. TEST(fix16_div(-3, fix16_from_int(-2)) == 2);
  119. TEST(fix16_div(2, 0x7FFF) == 4);
  120. TEST(fix16_div(-2, 0x7FFF) == -4);
  121. TEST(fix16_div(2, 0x8001) == 4);
  122. TEST(fix16_div(-2, 0x8001) == -4);
  123. }
  124. #endif
  125. {
  126. unsigned int i, j;
  127. int failures = 0;
  128. COMMENT("Running testcases for division");
  129. for (i = 0; i < TESTCASES_COUNT; i++)
  130. {
  131. for (j = 0; j < TESTCASES_COUNT; j++)
  132. {
  133. fix16_t a = testcases[i];
  134. fix16_t b = testcases[j];
  135. // We don't require a solution for /0 :)
  136. if (b == 0) continue;
  137. fix16_t result = fix16_div(a, b);
  138. double fa = fix16_to_dbl(a);
  139. double fb = fix16_to_dbl(b);
  140. fix16_t fresult = fix16_from_dbl(fa / fb);
  141. double max = fix16_to_dbl(fix16_maximum);
  142. double min = fix16_to_dbl(fix16_minimum);
  143. if (delta(fresult, result) > max_delta)
  144. {
  145. if (((fa / fb) > max) || ((fa / fb) < min))
  146. {
  147. #ifndef FIXMATH_NO_OVERFLOW
  148. if (result != fix16_overflow)
  149. {
  150. printf("\n%d / %d overflow not detected!\n", a, b);
  151. failures++;
  152. }
  153. #endif
  154. // Legitimate overflow
  155. continue;
  156. }
  157. printf("\n%f / %f = %f\n", fix16_to_dbl(a), fix16_to_dbl(b), fix16_to_dbl(fresult));
  158. printf("%f / %f = %f\n", fa, fb, (fa / fb));
  159. failures++;
  160. }
  161. }
  162. }
  163. TEST(failures == 0);
  164. }
  165. {
  166. unsigned int i, j;
  167. int failures = 0;
  168. COMMENT("Running testcases for addition");
  169. for (i = 0; i < TESTCASES_COUNT; i++)
  170. {
  171. for (j = 0; j < TESTCASES_COUNT; j++)
  172. {
  173. fix16_t a = testcases[i];
  174. fix16_t b = testcases[j];
  175. fix16_t result = fix16_add(a, b);
  176. double fa = fix16_to_dbl(a);
  177. double fb = fix16_to_dbl(b);
  178. fix16_t fresult = fix16_from_dbl(fa + fb);
  179. double max = fix16_to_dbl(fix16_maximum);
  180. double min = fix16_to_dbl(fix16_minimum);
  181. if (delta(fresult, result) > max_delta)
  182. {
  183. if (fa + fb > max || fa + fb < min)
  184. {
  185. #ifndef FIXMATH_NO_OVERFLOW
  186. if (result != fix16_overflow)
  187. {
  188. printf("\n%d + %d overflow not detected!\n", a, b);
  189. failures++;
  190. }
  191. #endif
  192. // Legitimate overflow
  193. continue;
  194. }
  195. printf("\n%d + %d = %d\n", a, b, result);
  196. printf("%f + %f = %d\n", fa, fb, fresult);
  197. failures++;
  198. }
  199. }
  200. }
  201. TEST(failures == 0);
  202. }
  203. {
  204. unsigned int i, j;
  205. int failures = 0;
  206. COMMENT("Running testcases for subtraction");
  207. for (i = 0; i < TESTCASES_COUNT; i++)
  208. {
  209. for (j = 0; j < TESTCASES_COUNT; j++)
  210. {
  211. fix16_t a = testcases[i];
  212. fix16_t b = testcases[j];
  213. fix16_t result = fix16_sub(a, b);
  214. double fa = fix16_to_dbl(a);
  215. double fb = fix16_to_dbl(b);
  216. fix16_t fresult = fix16_from_dbl(fa - fb);
  217. double max = fix16_to_dbl(fix16_maximum);
  218. double min = fix16_to_dbl(fix16_minimum);
  219. if (delta(fresult, result) > max_delta)
  220. {
  221. if (fa - fb > max || fa - fb < min)
  222. {
  223. #ifndef FIXMATH_NO_OVERFLOW
  224. if (result != fix16_overflow)
  225. {
  226. printf("\n%d - %d overflow not detected!\n", a, b);
  227. failures++;
  228. }
  229. #endif
  230. // Legitimate overflow
  231. continue;
  232. }
  233. printf("\n%d - %d = %d\n", a, b, result);
  234. printf("%f - %f = %d\n", fa, fb, fresult);
  235. failures++;
  236. }
  237. }
  238. }
  239. TEST(failures == 0);
  240. }
  241. {
  242. COMMENT("Testing basic square roots");
  243. TEST(fix16_sqrt(fix16_from_int(16)) == fix16_from_int(4));
  244. TEST(fix16_sqrt(fix16_from_int(100)) == fix16_from_int(10));
  245. TEST(fix16_sqrt(fix16_from_int(1)) == fix16_from_int(1));
  246. }
  247. #ifndef FIXMATH_NO_ROUNDING
  248. {
  249. COMMENT("Testing square root rounding corner cases");
  250. TEST(fix16_sqrt(214748302) == 3751499);
  251. TEST(fix16_sqrt(214748303) == 3751499);
  252. TEST(fix16_sqrt(214748359) == 3751499);
  253. TEST(fix16_sqrt(214748360) == 3751500);
  254. }
  255. #endif
  256. {
  257. unsigned int i;
  258. int failures = 0;
  259. COMMENT("Running test cases for square root");
  260. for (i = 0; i < TESTCASES_COUNT; i++)
  261. {
  262. fix16_t a = testcases[i];
  263. if (a < 0) continue;
  264. fix16_t result = fix16_sqrt(a);
  265. double fa = fix16_to_dbl(a);
  266. fix16_t fresult = fix16_from_dbl(sqrt(fa));
  267. if (delta(fresult, result) > max_delta)
  268. {
  269. printf("\nfix16_sqrt(%d) = %d\n", a, result);
  270. printf("sqrt(%f) = %d\n", fa, fresult);
  271. failures++;
  272. }
  273. }
  274. TEST(failures == 0);
  275. }
  276. if (status != 0)
  277. fprintf(stdout, "\n\nSome tests FAILED!\n");
  278. return status;
  279. }