339 lines
9.3 KiB

  1. //
  2. // Lol Engine — Unit tests
  3. //
  4. // Copyright © 2010—2014 Sam Hocevar <sam@hocevar.net>
  5. //
  6. // This program is free software. It comes without any warranty, to
  7. // the extent permitted by applicable law. You can redistribute it
  8. // and/or modify it under the terms of the Do What the Fuck You Want
  9. // to Public License, Version 2, as published by the WTFPL Task Force.
  10. // See http://www.wtfpl.net/ for more details.
  11. //
  12. #include <lol/engine-internal.h>
  13. #include <lolunit.h>
  14. namespace lol
  15. {
  16. lolunit_declare_fixture(PolynomialTest)
  17. {
  18. lolunit_declare_test(Declaration)
  19. {
  20. polynomial<float> p;
  21. polynomial<real> q;
  22. }
  23. lolunit_declare_test(Init)
  24. {
  25. polynomial<float> p { };
  26. lolunit_assert_equal(p[0], 0.f);
  27. lolunit_assert_equal(p[1], 0.f);
  28. lolunit_assert_equal(p[2], 0.f);
  29. lolunit_assert_equal(p.degree(), -1);
  30. polynomial<float> q { 1.f };
  31. lolunit_assert_equal(q[0], 1.f);
  32. lolunit_assert_equal(q[1], 0.f);
  33. lolunit_assert_equal(q[2], 0.f);
  34. lolunit_assert_equal(q.degree(), 0);
  35. polynomial<float> r { 1.f, 2.f };
  36. lolunit_assert_equal(r[0], 1.f);
  37. lolunit_assert_equal(r[1], 2.f);
  38. lolunit_assert_equal(r[2], 0.f);
  39. lolunit_assert_equal(r.degree(), 1);
  40. polynomial<float> s { 0.f };
  41. lolunit_assert_equal(s[0], 0.f);
  42. lolunit_assert_equal(s[1], 0.f);
  43. lolunit_assert_equal(s[2], 0.f);
  44. lolunit_assert_equal(s.degree(), -1);
  45. }
  46. lolunit_declare_test(Derive)
  47. {
  48. polynomial<float> p {};
  49. p = p.derive();
  50. lolunit_assert_equal(p.degree(), -1);
  51. polynomial<float> q { 1.f };
  52. q = q.derive();
  53. lolunit_assert_equal(q.degree(), -1);
  54. polynomial<float> r { 1.f, 2.f };
  55. r = r.derive();
  56. lolunit_assert_equal(r.degree(), 0);
  57. lolunit_assert_equal(r[0], 2.f);
  58. polynomial<float> s { 1.f, 2.f, 3.f, 4.f };
  59. s = s.derive();
  60. lolunit_assert_equal(s.degree(), 2);
  61. lolunit_assert_equal(s[0], 2.f);
  62. lolunit_assert_equal(s[1], 6.f);
  63. lolunit_assert_equal(s[2], 12.f);
  64. }
  65. lolunit_declare_test(Eval)
  66. {
  67. /* Special null polynomial */
  68. polynomial<float> p;
  69. float a = p.eval(42.f);
  70. lolunit_assert_equal(a, 0.f);
  71. }
  72. lolunit_declare_test(Eval0)
  73. {
  74. /* Constant polynomial p(x) = 1 */
  75. polynomial<float> p { 1.f };
  76. float a = p.eval(42.f);
  77. lolunit_assert_equal(a, 1.f);
  78. }
  79. lolunit_declare_test(Eval1)
  80. {
  81. /* p(x) = 1 + 2x */
  82. polynomial<float> p { 1.f, 2.f };
  83. float a = p.eval(0.f);
  84. lolunit_assert_equal(a, 1.f);
  85. float b = p.eval(1.f);
  86. lolunit_assert_equal(b, 3.f);
  87. float c = p.eval(2.f);
  88. lolunit_assert_equal(c, 5.f);
  89. }
  90. lolunit_declare_test(Eval2)
  91. {
  92. /* p(x) = 1 + 2x + 3x² */
  93. polynomial<float> p { 1.f, 2.f, 3.f };
  94. float a = p.eval(0.f);
  95. lolunit_assert_equal(a, 1.f);
  96. float b = p.eval(1.f);
  97. lolunit_assert_equal(b, 6.f);
  98. float c = p.eval(2.f);
  99. lolunit_assert_equal(c, 17.f);
  100. }
  101. lolunit_declare_test(UnaryPlusMinus)
  102. {
  103. /* p(x) = 1 + 2x + 3x² */
  104. polynomial<float> p { 1.f, 2.f, 3.f };
  105. polynomial<float> q = +p;
  106. polynomial<float> r = -p;
  107. lolunit_assert_equal(q[0], 1.f);
  108. lolunit_assert_equal(q[1], 2.f);
  109. lolunit_assert_equal(q[2], 3.f);
  110. lolunit_assert_equal(r[0], -1.f);
  111. lolunit_assert_equal(r[1], -2.f);
  112. lolunit_assert_equal(r[2], -3.f);
  113. }
  114. lolunit_declare_test(Addition)
  115. {
  116. /* p(x) = 1 + 2x + 3x² */
  117. /* q(x) = 4 + 5x */
  118. polynomial<float> p { 1.f, 2.f, 3.f };
  119. polynomial<float> q { 4.f, 5.f };
  120. /* r(x) = 5 + 7x + 3x² */
  121. polynomial<float> r = p + q;
  122. lolunit_assert_equal(r.degree(), 2);
  123. lolunit_assert_equal(r[0], 5.f);
  124. lolunit_assert_equal(r[1], 7.f);
  125. lolunit_assert_equal(r[2], 3.f);
  126. }
  127. lolunit_declare_test(Subtraction)
  128. {
  129. /* p(x) = 1 + 2x + 3x² */
  130. /* q(x) = 4 + 5x */
  131. polynomial<float> p { 1.f, 2.f, 3.f };
  132. polynomial<float> q { 4.f, 5.f };
  133. /* r(x) = -3 + -3x + 3x² */
  134. polynomial<float> r = p - q;
  135. lolunit_assert_equal(r.degree(), 2);
  136. lolunit_assert_equal(r[0], -3.f);
  137. lolunit_assert_equal(r[1], -3.f);
  138. lolunit_assert_equal(r[2], 3.f);
  139. }
  140. lolunit_declare_test(Multiplication)
  141. {
  142. /* p(x) = 1 + 2x + 3x² */
  143. /* q(x) = 4 + 5x */
  144. polynomial<float> p { 1.f, 2.f, 3.f };
  145. polynomial<float> q { 4.f, 5.f };
  146. /* r(x) = 4 + 13x + 22x² + 15x³ */
  147. polynomial<float> r = p * q;
  148. lolunit_assert_equal(r.degree(), 3);
  149. lolunit_assert_equal(r[0], 4.f);
  150. lolunit_assert_equal(r[1], 13.f);
  151. lolunit_assert_equal(r[2], 22.f);
  152. lolunit_assert_equal(r[3], 15.f);
  153. }
  154. lolunit_declare_test(Division)
  155. {
  156. /* p(x) = -4 - 2x² + x³ */
  157. /* q(x) = -3 + x */
  158. polynomial<float> p { -4.f, 0.f, -2.f, 1.f };
  159. polynomial<float> q { -3.f, 1.f };
  160. /* p(x) = r(x) q(x) + s(x)
  161. * r(x) = 3 + x + x²
  162. * s(x) = 5 */
  163. auto r = p / q;
  164. lolunit_assert_equal(r.m1.degree(), 2);
  165. lolunit_assert_doubles_equal(r.m1[0], 3.f, 1e-5f);
  166. lolunit_assert_doubles_equal(r.m1[1], 1.f, 1e-5f);
  167. lolunit_assert_doubles_equal(r.m1[2], 1.f, 1e-5f);
  168. lolunit_assert_equal(r.m2.degree(), 0);
  169. lolunit_assert_doubles_equal(r.m2[0], 5.f, 1e-5f);
  170. }
  171. lolunit_declare_test(Composition1)
  172. {
  173. /* p(x) = 1 + x² */
  174. polynomial<float> p({ 1, 0, 1 });
  175. /* q(x) = (p o p)(x) = 2 + 2x² + x⁴ */
  176. polynomial<float> q = p.eval(p);
  177. lolunit_assert_equal(q.degree(), 4);
  178. lolunit_assert_equal(q[0], 2.f);
  179. lolunit_assert_equal(q[1], 0.f);
  180. lolunit_assert_equal(q[2], 2.f);
  181. lolunit_assert_equal(q[3], 0.f);
  182. lolunit_assert_equal(q[4], 1.f);
  183. }
  184. lolunit_declare_test(Composition2)
  185. {
  186. /* p(x) = 1 + x */
  187. polynomial<float> p({ 1, 1 });
  188. /* q(x) = 1 + x + x² */
  189. polynomial<float> q({ 1, 1, 1 });
  190. /* r(x) = (q o p)(x) = 3 + 3x + x² */
  191. polynomial<float> r = q.eval(p);
  192. lolunit_assert_equal(r.degree(), 2);
  193. lolunit_assert_equal(r[0], 3.f);
  194. lolunit_assert_equal(r[1], 3.f);
  195. lolunit_assert_equal(r[2], 1.f);
  196. }
  197. lolunit_declare_test(RootsDegree0)
  198. {
  199. /* p(x) = 42 */
  200. polynomial<float> p { 42.f };
  201. auto roots = p.roots();
  202. lolunit_assert_equal(roots.count(), 0);
  203. }
  204. lolunit_declare_test(RootsDegree1)
  205. {
  206. /* p(x) = -6 + 2x */
  207. polynomial<float> p { -6.f, 2.f };
  208. auto roots = p.roots();
  209. lolunit_assert_equal(roots.count(), 1);
  210. lolunit_assert_equal(roots[0], 3.f);
  211. }
  212. lolunit_declare_test(RootsDegree2)
  213. {
  214. /* p(x) = 81 - 18x + x² */
  215. polynomial<float> p { 81.f, -18.f, 1.f };
  216. auto roots1 = p.roots();
  217. lolunit_assert_equal(roots1.count(), 1);
  218. lolunit_assert_equal(roots1[0], 9.f);
  219. /* p(x) = 42 - 20x + 2x² */
  220. polynomial<float> q { 42.f, -20.f, 2.f };
  221. auto roots2 = q.roots();
  222. lolunit_assert_equal(roots2.count(), 2);
  223. lolunit_assert_equal(roots2[0], 3.f);
  224. lolunit_assert_equal(roots2[1], 7.f);
  225. }
  226. #ifdef ENABLE_3SOLVE
  227. lolunit_declare_test(RootsDegree3TripleSolution)
  228. {
  229. polynomial<float> p { 1.f, 3.f, 3.f, 1.f };
  230. auto roots1 = p.roots();
  231. lolunit_assert_equal(roots1.count(), 3);
  232. }
  233. lolunit_declare_test(RootsDegree3DoubleSolution)
  234. {
  235. polynomial<float> p { 2.f, 5.f, 4.f, 1.f };
  236. auto roots1 = p.roots();
  237. lolunit_assert_equal(roots1.count(), 3);
  238. }
  239. lolunit_declare_test(RootsDegree3SingleSolutions)
  240. {
  241. polynomial<float> p { 6.f, 11.f, 6.f, 1.f };
  242. auto roots1 = p.roots();
  243. lolunit_assert_equal(roots1.count(), 3);
  244. }
  245. #endif
  246. lolunit_declare_test(Chebyshev)
  247. {
  248. polynomial<float> t0 = polynomial<float>::chebyshev(0);
  249. polynomial<float> t1 = polynomial<float>::chebyshev(1);
  250. polynomial<float> t2 = polynomial<float>::chebyshev(2);
  251. polynomial<float> t3 = polynomial<float>::chebyshev(3);
  252. polynomial<float> t4 = polynomial<float>::chebyshev(4);
  253. /* Taken from the sequence at http://oeis.org/A028297 */
  254. lolunit_assert_equal(t0.degree(), 0);
  255. lolunit_assert_equal(t0[0], 1.f);
  256. lolunit_assert_equal(t1.degree(), 1);
  257. lolunit_assert_equal(t1[0], 0.f);
  258. lolunit_assert_equal(t1[1], 1.f);
  259. lolunit_assert_equal(t2.degree(), 2);
  260. lolunit_assert_equal(t2[0], -1.f);
  261. lolunit_assert_equal(t2[1], 0.f);
  262. lolunit_assert_equal(t2[2], 2.f);
  263. lolunit_assert_equal(t3.degree(), 3);
  264. lolunit_assert_equal(t3[0], 0.f);
  265. lolunit_assert_equal(t3[1], -3.f);
  266. lolunit_assert_equal(t3[2], 0.f);
  267. lolunit_assert_equal(t3[3], 4.f);
  268. lolunit_assert_equal(t4.degree(), 4);
  269. lolunit_assert_equal(t4[0], 1.f);
  270. lolunit_assert_equal(t4[1], 0.f);
  271. lolunit_assert_equal(t4[2], -8.f);
  272. lolunit_assert_equal(t4[3], 0.f);
  273. lolunit_assert_equal(t4[4], 8.f);
  274. }
  275. };
  276. } /* namespace lol */