You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

321 line
8.8 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://sam.zoy.org/projects/COPYING.WTFPL for more details.
  9. //
  10. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #include <cppunit/extensions/HelperMacros.h>
  14. #include <cppunit/TestCaller.h>
  15. #include <cppunit/TestCase.h>
  16. #include <cppunit/TestSuite.h>
  17. #include "core.h"
  18. namespace lol
  19. {
  20. class HalfTest : public CppUnit::TestCase
  21. {
  22. CPPUNIT_TEST_SUITE(HalfTest);
  23. CPPUNIT_TEST(test_half_makebits);
  24. CPPUNIT_TEST(test_half_makeslow);
  25. CPPUNIT_TEST(test_half_makefast);
  26. CPPUNIT_TEST(test_half_isnan);
  27. CPPUNIT_TEST(test_half_isinf);
  28. CPPUNIT_TEST(test_half_isfinite);
  29. CPPUNIT_TEST(test_half_isnormal);
  30. CPPUNIT_TEST(test_half_classify);
  31. CPPUNIT_TEST(test_half_to_float);
  32. CPPUNIT_TEST(test_half_to_int);
  33. CPPUNIT_TEST(test_float_op_half);
  34. CPPUNIT_TEST(test_half_op_float);
  35. CPPUNIT_TEST_SUITE_END();
  36. public:
  37. HalfTest() : CppUnit::TestCase("Matrix Test") {}
  38. void setUp()
  39. {
  40. }
  41. void tearDown() {}
  42. void test_half_makebits()
  43. {
  44. for (unsigned int i = 0; i < 0x10000; i++)
  45. {
  46. half a = half::makebits(i);
  47. uint16_t b = i;
  48. CPPUNIT_ASSERT_EQUAL(a.bits, b);
  49. }
  50. }
  51. void test_half_makeslow()
  52. {
  53. for (size_t i = 0; i < sizeof(pairs) / sizeof(*pairs); i++)
  54. {
  55. half a = half::makeslow(pairs[i].f);
  56. uint16_t b = pairs[i].x;
  57. CPPUNIT_ASSERT_EQUAL(a.bits, b);
  58. }
  59. }
  60. void test_half_makefast()
  61. {
  62. for (size_t i = 0; i < sizeof(pairs) / sizeof(*pairs); i++)
  63. {
  64. half a = half::makefast(pairs[i].f);
  65. uint16_t b = pairs[i].x;
  66. CPPUNIT_ASSERT_EQUAL(a.bits, b);
  67. }
  68. }
  69. void test_half_isnan()
  70. {
  71. CPPUNIT_ASSERT(half::makebits(0x7c01).isnan());
  72. CPPUNIT_ASSERT(half::makebits(0xfc01).isnan());
  73. CPPUNIT_ASSERT(half::makebits(0x7e00).isnan());
  74. CPPUNIT_ASSERT(half::makebits(0xfe00).isnan());
  75. CPPUNIT_ASSERT(!half::makebits(0x7c00).isnan());
  76. CPPUNIT_ASSERT(!half::makebits(0xfc00).isnan());
  77. CPPUNIT_ASSERT(!half(0.0f).isnan());
  78. CPPUNIT_ASSERT(!half(-0.0f).isnan());
  79. CPPUNIT_ASSERT(!half(2.0f).isnan());
  80. CPPUNIT_ASSERT(!half(-2.0f).isnan());
  81. }
  82. void test_half_isinf()
  83. {
  84. CPPUNIT_ASSERT(half(65536.0f).isinf());
  85. CPPUNIT_ASSERT(half(-65536.0f).isinf());
  86. CPPUNIT_ASSERT(!half(0.0f).isinf());
  87. CPPUNIT_ASSERT(!half(-0.0f).isinf());
  88. CPPUNIT_ASSERT(!half(65535.0f).isinf());
  89. CPPUNIT_ASSERT(!half(-65535.0f).isinf());
  90. CPPUNIT_ASSERT(half::makebits(0x7c00).isinf());
  91. CPPUNIT_ASSERT(half::makebits(0xfc00).isinf());
  92. CPPUNIT_ASSERT(!half::makebits(0x7e00).isinf());
  93. CPPUNIT_ASSERT(!half::makebits(0xfe00).isinf());
  94. }
  95. void test_half_isfinite()
  96. {
  97. CPPUNIT_ASSERT(half(0.0f).isfinite());
  98. CPPUNIT_ASSERT(half(-0.0f).isfinite());
  99. CPPUNIT_ASSERT(half(65535.0f).isfinite());
  100. CPPUNIT_ASSERT(half(-65535.0f).isfinite());
  101. CPPUNIT_ASSERT(!half(65536.0f).isfinite());
  102. CPPUNIT_ASSERT(!half(-65536.0f).isfinite());
  103. CPPUNIT_ASSERT(!half::makebits(0x7c00).isfinite());
  104. CPPUNIT_ASSERT(!half::makebits(0xfc00).isfinite());
  105. CPPUNIT_ASSERT(!half::makebits(0x7e00).isfinite());
  106. CPPUNIT_ASSERT(!half::makebits(0xfe00).isfinite());
  107. }
  108. void test_half_isnormal()
  109. {
  110. CPPUNIT_ASSERT(half(0.0f).isnormal());
  111. CPPUNIT_ASSERT(half(-0.0f).isnormal());
  112. CPPUNIT_ASSERT(half(65535.0f).isnormal());
  113. CPPUNIT_ASSERT(half(-65535.0f).isnormal());
  114. CPPUNIT_ASSERT(!half(65536.0f).isnormal());
  115. CPPUNIT_ASSERT(!half(-65536.0f).isnormal());
  116. CPPUNIT_ASSERT(!half::makebits(0x7c00).isnormal());
  117. CPPUNIT_ASSERT(!half::makebits(0xfc00).isnormal());
  118. CPPUNIT_ASSERT(!half::makebits(0x7e00).isnormal());
  119. CPPUNIT_ASSERT(!half::makebits(0xfe00).isnormal());
  120. }
  121. void test_half_classify()
  122. {
  123. for (uint32_t i = 0; i < 0x10000; i++)
  124. {
  125. half h = half::makebits(i);
  126. if (h.isnan())
  127. {
  128. CPPUNIT_ASSERT(!h.isinf());
  129. CPPUNIT_ASSERT(!h.isnormal());
  130. CPPUNIT_ASSERT(!h.isfinite());
  131. }
  132. else if (h.isinf())
  133. {
  134. CPPUNIT_ASSERT(!h.isnormal());
  135. CPPUNIT_ASSERT(!h.isfinite());
  136. }
  137. else
  138. {
  139. CPPUNIT_ASSERT(h.isfinite());
  140. }
  141. }
  142. }
  143. void test_half_to_float()
  144. {
  145. for (size_t i = 0; i < sizeof(pairs) / sizeof(*pairs); i++)
  146. {
  147. float a = (float)half::makebits(pairs[i].x);
  148. float b = pairs[i].f;
  149. CPPUNIT_ASSERT_EQUAL(a, b);
  150. }
  151. for (uint32_t i = 0; i < 0x10000; i++)
  152. {
  153. half h = half::makebits(i);
  154. float f = (float)h;
  155. half g = (half)f;
  156. if (h.isnan())
  157. {
  158. CPPUNIT_ASSERT(isnan(f));
  159. CPPUNIT_ASSERT(g.isnan());
  160. }
  161. else
  162. {
  163. CPPUNIT_ASSERT(!isnan(f));
  164. CPPUNIT_ASSERT_EQUAL(g.bits, h.bits);
  165. }
  166. }
  167. }
  168. void test_half_to_int()
  169. {
  170. CPPUNIT_ASSERT_EQUAL((int)(half)(0.0f), 0);
  171. CPPUNIT_ASSERT_EQUAL((int)(half)(-0.0f), 0);
  172. CPPUNIT_ASSERT_EQUAL((int)(half)(0.9f), 0);
  173. CPPUNIT_ASSERT_EQUAL((int)(half)(-0.9f), 0);
  174. CPPUNIT_ASSERT_EQUAL((int)(half)(1.0f), 1);
  175. CPPUNIT_ASSERT_EQUAL((int)(half)(-1.0f), -1);
  176. CPPUNIT_ASSERT_EQUAL((int)(half)(1.9f), 1);
  177. CPPUNIT_ASSERT_EQUAL((int)(half)(-1.9f), -1);
  178. CPPUNIT_ASSERT_EQUAL((int)(half)(65504.0f), 65504);
  179. CPPUNIT_ASSERT_EQUAL((int)(half)(-65504.0f), -65504);
  180. }
  181. void test_float_op_half()
  182. {
  183. half zero = 0;
  184. half one = 1;
  185. half two = 2;
  186. float a = zero + one;
  187. CPPUNIT_ASSERT_EQUAL(1.0f, a);
  188. a += zero;
  189. CPPUNIT_ASSERT_EQUAL(1.0f, a);
  190. a -= zero;
  191. CPPUNIT_ASSERT_EQUAL(1.0f, a);
  192. a *= one;
  193. CPPUNIT_ASSERT_EQUAL(1.0f, a);
  194. a /= one;
  195. CPPUNIT_ASSERT_EQUAL(1.0f, a);
  196. float b = one + zero;
  197. CPPUNIT_ASSERT_EQUAL(1.0f, b);
  198. b += one;
  199. CPPUNIT_ASSERT_EQUAL(2.0f, b);
  200. b *= two;
  201. CPPUNIT_ASSERT_EQUAL(4.0f, b);
  202. b -= two;
  203. CPPUNIT_ASSERT_EQUAL(2.0f, b);
  204. b /= two;
  205. CPPUNIT_ASSERT_EQUAL(1.0f, b);
  206. float c = one - zero;
  207. CPPUNIT_ASSERT_EQUAL(1.0f, c);
  208. float d = two - one;
  209. CPPUNIT_ASSERT_EQUAL(1.0f, d);
  210. float e = two + (-one);
  211. CPPUNIT_ASSERT_EQUAL(1.0f, e);
  212. float f = (two * two) / (one + one);
  213. CPPUNIT_ASSERT_EQUAL(2.0f, f);
  214. }
  215. void test_half_op_float()
  216. {
  217. half zero = 0;
  218. half one = 1;
  219. half two = 2;
  220. half four = 4;
  221. half a = one + 0.0f;
  222. CPPUNIT_ASSERT_EQUAL(one.bits, a.bits);
  223. a += 0.0f;
  224. CPPUNIT_ASSERT_EQUAL(one.bits, a.bits);
  225. a -= 0.0f;
  226. CPPUNIT_ASSERT_EQUAL(one.bits, a.bits);
  227. a *= 1.0f;
  228. CPPUNIT_ASSERT_EQUAL(one.bits, a.bits);
  229. a /= 1.0f;
  230. CPPUNIT_ASSERT_EQUAL(one.bits, a.bits);
  231. half b = one + 0.0f;
  232. CPPUNIT_ASSERT_EQUAL(one.bits, b.bits);
  233. b += 1.0f;
  234. CPPUNIT_ASSERT_EQUAL(two.bits, b.bits);
  235. b *= 2.0f;
  236. CPPUNIT_ASSERT_EQUAL(four.bits, b.bits);
  237. b -= 2.0f;
  238. CPPUNIT_ASSERT_EQUAL(two.bits, b.bits);
  239. b /= 2.0f;
  240. CPPUNIT_ASSERT_EQUAL(one.bits, b.bits);
  241. half c = 1.0f - zero;
  242. CPPUNIT_ASSERT_EQUAL(one.bits, c.bits);
  243. half d = 2.0f - one;
  244. CPPUNIT_ASSERT_EQUAL(one.bits, d.bits);
  245. half e = 2.0f + (-one);
  246. CPPUNIT_ASSERT_EQUAL(one.bits, e.bits);
  247. half f = (2.0f * two) / (1.0f + one);
  248. CPPUNIT_ASSERT_EQUAL(two.bits, f.bits);
  249. }
  250. private:
  251. struct TestPair { float f; uint16_t x; };
  252. static TestPair const pairs[11];
  253. };
  254. HalfTest::TestPair const HalfTest::pairs[] =
  255. {
  256. /* All these values have exact half representations */
  257. { 0.0f, 0x0000 },
  258. { -0.0f, 0x8000 }, /* negative zero */
  259. { 1.0f, 0x3c00 },
  260. { -1.0f, 0xbc00 },
  261. { 2.0f, 0x4000 },
  262. { 0.5f, 0x3800 },
  263. { 0.125f, 0x3000 },
  264. { 15.9375f, 0x4bf8 },
  265. { 0x1.fp-10, 0x17c0 },
  266. { 0x1.fp-14, 0x07c0 }, /* denormal */
  267. { 0x1.fp-15, 0x03e0 }, /* denormal */
  268. };
  269. CPPUNIT_TEST_SUITE_REGISTRATION(HalfTest);
  270. } /* namespace lol */