test_math_funcs.h 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. /**************************************************************************/
  2. /* test_math_funcs.h */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #pragma once
  31. #include "tests/test_macros.h"
  32. namespace TestMath {
  33. TEST_CASE("[Math] C++ macros") {
  34. CHECK(MIN(-2, 2) == -2);
  35. CHECK(MIN(600, 2) == 2);
  36. CHECK(MAX(-2, 2) == 2);
  37. CHECK(MAX(600, 2) == 600);
  38. CHECK(CLAMP(600, -2, 2) == 2);
  39. CHECK(CLAMP(620, 600, 650) == 620);
  40. // `max` is lower than `min`.
  41. CHECK(CLAMP(620, 600, 50) == 50);
  42. CHECK(Math::abs(-5) == 5);
  43. CHECK(Math::abs(0) == 0);
  44. CHECK(Math::abs(5) == 5);
  45. CHECK(SIGN(-5) == -1.0);
  46. CHECK(SIGN(0) == 0.0);
  47. CHECK(SIGN(5) == 1.0);
  48. // Check that SIGN(Math::NaN) returns 0.0.
  49. CHECK(SIGN(Math::NaN) == 0.0);
  50. }
  51. TEST_CASE("[Math] Power of two functions") {
  52. CHECK(next_power_of_2((uint32_t)0) == 0);
  53. CHECK(next_power_of_2((uint32_t)1) == 1);
  54. CHECK(next_power_of_2((uint32_t)16) == 16);
  55. CHECK(next_power_of_2((uint32_t)17) == 32);
  56. CHECK(next_power_of_2((uint32_t)65535) == 65536);
  57. CHECK(previous_power_of_2((uint32_t)0) == 0);
  58. CHECK(previous_power_of_2((uint32_t)1) == 1);
  59. CHECK(previous_power_of_2((uint32_t)16) == 16);
  60. CHECK(previous_power_of_2((uint32_t)17) == 16);
  61. CHECK(previous_power_of_2((uint32_t)65535) == 32768);
  62. CHECK(closest_power_of_2((uint32_t)0) == 0);
  63. CHECK(closest_power_of_2((uint32_t)1) == 1);
  64. CHECK(closest_power_of_2((uint32_t)16) == 16);
  65. CHECK(closest_power_of_2((uint32_t)17) == 16);
  66. CHECK(closest_power_of_2((uint32_t)65535) == 65536);
  67. CHECK(get_shift_from_power_of_2((uint32_t)0) == -1);
  68. CHECK(get_shift_from_power_of_2((uint32_t)1) == 0);
  69. CHECK(get_shift_from_power_of_2((uint32_t)16) == 4);
  70. CHECK(get_shift_from_power_of_2((uint32_t)17) == -1);
  71. CHECK(get_shift_from_power_of_2((uint32_t)65535) == -1);
  72. CHECK(nearest_shift((uint32_t)0) == 0);
  73. CHECK(nearest_shift((uint32_t)1) == 1);
  74. CHECK(nearest_shift((uint32_t)16) == 5);
  75. CHECK(nearest_shift((uint32_t)17) == 5);
  76. CHECK(nearest_shift((uint32_t)65535) == 16);
  77. }
  78. TEST_CASE_TEMPLATE("[Math] abs", T, int, float, double) {
  79. CHECK(Math::abs((T)-1) == (T)1);
  80. CHECK(Math::abs((T)0) == (T)0);
  81. CHECK(Math::abs((T)1) == (T)1);
  82. CHECK(Math::abs((T)0.1) == (T)0.1);
  83. }
  84. TEST_CASE_TEMPLATE("[Math] round/floor/ceil", T, float, double) {
  85. CHECK(Math::round((T)1.5) == (T)2.0);
  86. CHECK(Math::round((T)1.6) == (T)2.0);
  87. CHECK(Math::round((T)-1.5) == (T)-2.0);
  88. CHECK(Math::round((T)-1.1) == (T)-1.0);
  89. CHECK(Math::floor((T)1.5) == (T)1.0);
  90. CHECK(Math::floor((T)-1.5) == (T)-2.0);
  91. CHECK(Math::ceil((T)1.5) == (T)2.0);
  92. CHECK(Math::ceil((T)-1.9) == (T)-1.0);
  93. }
  94. TEST_CASE_TEMPLATE("[Math] integer division round up unsigned", T, uint32_t, uint64_t) {
  95. CHECK(Math::division_round_up((T)0, (T)64) == 0);
  96. CHECK(Math::division_round_up((T)1, (T)64) == 1);
  97. CHECK(Math::division_round_up((T)63, (T)64) == 1);
  98. CHECK(Math::division_round_up((T)64, (T)64) == 1);
  99. CHECK(Math::division_round_up((T)65, (T)64) == 2);
  100. CHECK(Math::division_round_up((T)65, (T)1) == 65);
  101. }
  102. TEST_CASE_TEMPLATE("[Math] integer division round up signed", T, int32_t, int64_t) {
  103. CHECK(Math::division_round_up((T)0, (T)64) == 0);
  104. CHECK(Math::division_round_up((T)1, (T)64) == 1);
  105. CHECK(Math::division_round_up((T)63, (T)64) == 1);
  106. CHECK(Math::division_round_up((T)64, (T)64) == 1);
  107. CHECK(Math::division_round_up((T)65, (T)64) == 2);
  108. CHECK(Math::division_round_up((T)65, (T)1) == 65);
  109. CHECK(Math::division_round_up((T)-1, (T)64) == 0);
  110. CHECK(Math::division_round_up((T)-1, (T)-1) == 1);
  111. CHECK(Math::division_round_up((T)-1, (T)1) == -1);
  112. CHECK(Math::division_round_up((T)-1, (T)-2) == 1);
  113. CHECK(Math::division_round_up((T)-4, (T)-2) == 2);
  114. }
  115. TEST_CASE_TEMPLATE("[Math] sin/cos/tan", T, float, double) {
  116. CHECK(Math::sin((T)-0.1) == doctest::Approx((T)-0.0998334166));
  117. CHECK(Math::sin((T)0.1) == doctest::Approx((T)0.0998334166));
  118. CHECK(Math::sin((T)0.5) == doctest::Approx((T)0.4794255386));
  119. CHECK(Math::sin((T)1.0) == doctest::Approx((T)0.8414709848));
  120. CHECK(Math::sin((T)1.5) == doctest::Approx((T)0.9974949866));
  121. CHECK(Math::sin((T)450.0) == doctest::Approx((T)-0.683283725));
  122. CHECK(Math::cos((T)-0.1) == doctest::Approx((T)0.99500416530));
  123. CHECK(Math::cos((T)0.1) == doctest::Approx((T)0.9950041653));
  124. CHECK(Math::cos((T)0.5) == doctest::Approx((T)0.8775825619));
  125. CHECK(Math::cos((T)1.0) == doctest::Approx((T)0.5403023059));
  126. CHECK(Math::cos((T)1.5) == doctest::Approx((T)0.0707372017));
  127. CHECK(Math::cos((T)450.0) == doctest::Approx((T)-0.7301529642));
  128. CHECK(Math::tan((T)-0.1) == doctest::Approx((T)-0.1003346721));
  129. CHECK(Math::tan((T)0.1) == doctest::Approx((T)0.1003346721));
  130. CHECK(Math::tan((T)0.5) == doctest::Approx((T)0.5463024898));
  131. CHECK(Math::tan((T)1.0) == doctest::Approx((T)1.5574077247));
  132. CHECK(Math::tan((T)1.5) == doctest::Approx((T)14.1014199472));
  133. CHECK(Math::tan((T)450.0) == doctest::Approx((T)0.9358090134));
  134. }
  135. TEST_CASE_TEMPLATE("[Math] sinh/cosh/tanh", T, float, double) {
  136. CHECK(Math::sinh((T)-0.1) == doctest::Approx((T)-0.10016675));
  137. CHECK(Math::sinh((T)0.1) == doctest::Approx((T)0.10016675));
  138. CHECK(Math::sinh((T)0.5) == doctest::Approx((T)0.5210953055));
  139. CHECK(Math::sinh((T)1.0) == doctest::Approx((T)1.1752011936));
  140. CHECK(Math::sinh((T)1.5) == doctest::Approx((T)2.1292794551));
  141. CHECK(Math::cosh((T)-0.1) == doctest::Approx((T)1.0050041681));
  142. CHECK(Math::cosh((T)0.1) == doctest::Approx((T)1.0050041681));
  143. CHECK(Math::cosh((T)0.5) == doctest::Approx((T)1.1276259652));
  144. CHECK(Math::cosh((T)1.0) == doctest::Approx((T)1.5430806348));
  145. CHECK(Math::cosh((T)1.5) == doctest::Approx((T)2.3524096152));
  146. CHECK(Math::tanh((T)-0.1) == doctest::Approx((T)-0.0996679946));
  147. CHECK(Math::tanh((T)0.1) == doctest::Approx((T)0.0996679946));
  148. CHECK(Math::tanh((T)0.5) == doctest::Approx((T)0.4621171573));
  149. CHECK(Math::tanh((T)1.0) == doctest::Approx((T)0.761594156));
  150. CHECK(Math::tanh((T)1.5) == doctest::Approx((T)0.9051482536));
  151. CHECK(Math::tanh((T)450.0) == doctest::Approx((T)1.0));
  152. }
  153. TEST_CASE_TEMPLATE("[Math] asin/acos/atan", T, float, double) {
  154. CHECK(Math::asin((T)-0.1) == doctest::Approx((T)-0.1001674212));
  155. CHECK(Math::asin((T)0.1) == doctest::Approx((T)0.1001674212));
  156. CHECK(Math::asin((T)0.5) == doctest::Approx((T)0.5235987756));
  157. CHECK(Math::asin((T)1.0) == doctest::Approx((T)1.5707963268));
  158. CHECK(Math::asin((T)2.0) == doctest::Approx((T)1.5707963268));
  159. CHECK(Math::asin((T)-2.0) == doctest::Approx((T)-1.5707963268));
  160. CHECK(Math::acos((T)-0.1) == doctest::Approx((T)1.670963748));
  161. CHECK(Math::acos((T)0.1) == doctest::Approx((T)1.4706289056));
  162. CHECK(Math::acos((T)0.5) == doctest::Approx((T)1.0471975512));
  163. CHECK(Math::acos((T)1.0) == doctest::Approx((T)0.0));
  164. CHECK(Math::acos((T)2.0) == doctest::Approx((T)0.0));
  165. CHECK(Math::acos((T)-2.0) == doctest::Approx((T)Math::PI));
  166. CHECK(Math::atan((T)-0.1) == doctest::Approx((T)-0.0996686525));
  167. CHECK(Math::atan((T)0.1) == doctest::Approx((T)0.0996686525));
  168. CHECK(Math::atan((T)0.5) == doctest::Approx((T)0.463647609));
  169. CHECK(Math::atan((T)1.0) == doctest::Approx((T)0.7853981634));
  170. CHECK(Math::atan((T)1.5) == doctest::Approx((T)0.9827937232));
  171. CHECK(Math::atan((T)450.0) == doctest::Approx((T)1.5685741082));
  172. }
  173. TEST_CASE_TEMPLATE("[Math] asinh/acosh/atanh", T, float, double) {
  174. CHECK(Math::asinh((T)-2.0) == doctest::Approx((T)-1.4436354751));
  175. CHECK(Math::asinh((T)-0.1) == doctest::Approx((T)-0.0998340788));
  176. CHECK(Math::asinh((T)0.1) == doctest::Approx((T)0.0998340788));
  177. CHECK(Math::asinh((T)0.5) == doctest::Approx((T)0.4812118250));
  178. CHECK(Math::asinh((T)1.0) == doctest::Approx((T)0.8813735870));
  179. CHECK(Math::asinh((T)2.0) == doctest::Approx((T)1.4436354751));
  180. CHECK(Math::acosh((T)-2.0) == doctest::Approx((T)0.0));
  181. CHECK(Math::acosh((T)-0.1) == doctest::Approx((T)0.0));
  182. CHECK(Math::acosh((T)0.1) == doctest::Approx((T)0.0));
  183. CHECK(Math::acosh((T)0.5) == doctest::Approx((T)0.0));
  184. CHECK(Math::acosh((T)1.0) == doctest::Approx((T)0.0));
  185. CHECK(Math::acosh((T)2.0) == doctest::Approx((T)1.3169578969));
  186. CHECK(Math::acosh((T)450.0) == doctest::Approx((T)6.8023935287));
  187. CHECK(Math::is_inf(Math::atanh((T)-2.0)));
  188. CHECK(Math::atanh((T)-2.0) < (T)0.0);
  189. CHECK(Math::is_inf(Math::atanh((T)-1.0)));
  190. CHECK(Math::atanh((T)-1.0) < (T)0.0);
  191. CHECK(Math::atanh((T)-0.1) == doctest::Approx((T)-0.1003353477));
  192. CHECK(Math::atanh((T)0.1) == doctest::Approx((T)0.1003353477));
  193. CHECK(Math::atanh((T)0.5) == doctest::Approx((T)0.5493061443));
  194. CHECK(Math::is_inf(Math::atanh((T)1.0)));
  195. CHECK(Math::atanh((T)1.0) > (T)0.0);
  196. CHECK(Math::is_inf(Math::atanh((T)1.5)));
  197. CHECK(Math::atanh((T)1.5) > (T)0.0);
  198. CHECK(Math::is_inf(Math::atanh((T)450.0)));
  199. CHECK(Math::atanh((T)450.0) > (T)0.0);
  200. }
  201. TEST_CASE_TEMPLATE("[Math] sinc/sincn/atan2", T, float, double) {
  202. CHECK(Math::sinc((T)-0.1) == doctest::Approx((T)0.9983341665));
  203. CHECK(Math::sinc((T)0.1) == doctest::Approx((T)0.9983341665));
  204. CHECK(Math::sinc((T)0.5) == doctest::Approx((T)0.9588510772));
  205. CHECK(Math::sinc((T)1.0) == doctest::Approx((T)0.8414709848));
  206. CHECK(Math::sinc((T)1.5) == doctest::Approx((T)0.6649966577));
  207. CHECK(Math::sinc((T)450.0) == doctest::Approx((T)-0.0015184083));
  208. CHECK(Math::sincn((T)-0.1) == doctest::Approx((T)0.9836316431));
  209. CHECK(Math::sincn((T)0.1) == doctest::Approx((T)0.9836316431));
  210. CHECK(Math::sincn((T)0.5) == doctest::Approx((T)0.6366197724));
  211. CHECK(Math::sincn((T)1.0) == doctest::Approx((T)0.0));
  212. CHECK(Math::sincn((T)1.5) == doctest::Approx((T)-0.2122065908));
  213. CHECK(Math::sincn((T)450.0) == doctest::Approx((T)0.0));
  214. CHECK(Math::atan2((T)-0.1, (T)0.5) == doctest::Approx((T)-0.1973955598));
  215. CHECK(Math::atan2((T)0.1, (T)-0.5) == doctest::Approx((T)2.9441970937));
  216. CHECK(Math::atan2((T)0.5, (T)1.5) == doctest::Approx((T)0.3217505544));
  217. CHECK(Math::atan2((T)1.0, (T)2.5) == doctest::Approx((T)0.3805063771));
  218. CHECK(Math::atan2((T)1.5, (T)1.0) == doctest::Approx((T)0.9827937232));
  219. CHECK(Math::atan2((T)450.0, (T)1.0) == doctest::Approx((T)1.5685741082));
  220. }
  221. TEST_CASE_TEMPLATE("[Math] pow/log/log2/exp/sqrt", T, float, double) {
  222. CHECK(Math::pow((T)-0.1, (T)2.0) == doctest::Approx((T)0.01));
  223. CHECK(Math::pow((T)0.1, (T)2.5) == doctest::Approx((T)0.0031622777));
  224. CHECK(Math::pow((T)0.5, (T)0.5) == doctest::Approx((T)0.7071067812));
  225. CHECK(Math::pow((T)1.0, (T)1.0) == doctest::Approx((T)1.0));
  226. CHECK(Math::pow((T)1.5, (T)-1.0) == doctest::Approx((T)0.6666666667));
  227. CHECK(Math::pow((T)450.0, (T)-2.0) == doctest::Approx((T)0.0000049383));
  228. CHECK(Math::pow((T)450.0, (T)0.0) == doctest::Approx((T)1.0));
  229. CHECK(Math::is_nan(Math::log((T)-0.1)));
  230. CHECK(Math::log((T)0.1) == doctest::Approx((T)-2.302585093));
  231. CHECK(Math::log((T)0.5) == doctest::Approx((T)-0.6931471806));
  232. CHECK(Math::log((T)1.0) == doctest::Approx((T)0.0));
  233. CHECK(Math::log((T)1.5) == doctest::Approx((T)0.4054651081));
  234. CHECK(Math::log((T)450.0) == doctest::Approx((T)6.1092475828));
  235. CHECK(Math::is_nan(Math::log2((T)-0.1)));
  236. CHECK(Math::log2((T)0.1) == doctest::Approx((T)-3.3219280949));
  237. CHECK(Math::log2((T)0.5) == doctest::Approx((T)-1.0));
  238. CHECK(Math::log2((T)1.0) == doctest::Approx((T)0.0));
  239. CHECK(Math::log2((T)1.5) == doctest::Approx((T)0.5849625007));
  240. CHECK(Math::log2((T)450.0) == doctest::Approx((T)8.8137811912));
  241. CHECK(Math::exp((T)-0.1) == doctest::Approx((T)0.904837418));
  242. CHECK(Math::exp((T)0.1) == doctest::Approx((T)1.1051709181));
  243. CHECK(Math::exp((T)0.5) == doctest::Approx((T)1.6487212707));
  244. CHECK(Math::exp((T)1.0) == doctest::Approx((T)2.7182818285));
  245. CHECK(Math::exp((T)1.5) == doctest::Approx((T)4.4816890703));
  246. CHECK(Math::is_nan(Math::sqrt((T)-0.1)));
  247. CHECK(Math::sqrt((T)0.1) == doctest::Approx((T)0.316228));
  248. CHECK(Math::sqrt((T)0.5) == doctest::Approx((T)0.707107));
  249. CHECK(Math::sqrt((T)1.0) == doctest::Approx((T)1.0));
  250. CHECK(Math::sqrt((T)1.5) == doctest::Approx((T)1.224745));
  251. }
  252. TEST_CASE_TEMPLATE("[Math] is_nan/is_inf", T, float, double) {
  253. CHECK(!Math::is_nan((T)0.0));
  254. CHECK(Math::is_nan((T)Math::NaN));
  255. CHECK(!Math::is_inf((T)0.0));
  256. CHECK(Math::is_inf((T)Math::INF));
  257. }
  258. TEST_CASE_TEMPLATE("[Math] linear_to_db", T, float, double) {
  259. CHECK(Math::linear_to_db((T)1.0) == doctest::Approx((T)0.0));
  260. CHECK(Math::linear_to_db((T)20.0) == doctest::Approx((T)26.0206));
  261. CHECK(Math::is_inf(Math::linear_to_db((T)0.0)));
  262. CHECK(Math::is_nan(Math::linear_to_db((T)-20.0)));
  263. }
  264. TEST_CASE_TEMPLATE("[Math] db_to_linear", T, float, double) {
  265. CHECK(Math::db_to_linear((T)0.0) == doctest::Approx((T)1.0));
  266. CHECK(Math::db_to_linear((T)1.0) == doctest::Approx((T)1.122018));
  267. CHECK(Math::db_to_linear((T)20.0) == doctest::Approx((T)10.0));
  268. CHECK(Math::db_to_linear((T)-20.0) == doctest::Approx((T)0.1));
  269. }
  270. TEST_CASE_TEMPLATE("[Math] step_decimals", T, float, double) {
  271. CHECK(Math::step_decimals((T)-0.5) == 1);
  272. CHECK(Math::step_decimals((T)0) == 0);
  273. CHECK(Math::step_decimals((T)1) == 0);
  274. CHECK(Math::step_decimals((T)0.1) == 1);
  275. CHECK(Math::step_decimals((T)0.01) == 2);
  276. CHECK(Math::step_decimals((T)0.001) == 3);
  277. CHECK(Math::step_decimals((T)0.0001) == 4);
  278. CHECK(Math::step_decimals((T)0.00001) == 5);
  279. CHECK(Math::step_decimals((T)0.000001) == 6);
  280. CHECK(Math::step_decimals((T)0.0000001) == 7);
  281. CHECK(Math::step_decimals((T)0.00000001) == 8);
  282. CHECK(Math::step_decimals((T)0.000000001) == 9);
  283. // Too many decimals to handle.
  284. CHECK(Math::step_decimals((T)0.0000000001) == 0);
  285. }
  286. TEST_CASE_TEMPLATE("[Math] range_step_decimals", T, float, double) {
  287. CHECK(Math::range_step_decimals((T)0.000000001) == 9);
  288. // Too many decimals to handle.
  289. CHECK(Math::range_step_decimals((T)0.0000000001) == 0);
  290. // Should be treated as a step of 0 for use by the editor.
  291. CHECK(Math::range_step_decimals((T)0.0) == 16);
  292. CHECK(Math::range_step_decimals((T)-0.5) == 16);
  293. }
  294. TEST_CASE_TEMPLATE("[Math] lerp", T, float, double) {
  295. CHECK(Math::lerp((T)2.0, (T)5.0, (T)-0.1) == doctest::Approx((T)1.7));
  296. CHECK(Math::lerp((T)2.0, (T)5.0, (T)0.0) == doctest::Approx((T)2.0));
  297. CHECK(Math::lerp((T)2.0, (T)5.0, (T)0.1) == doctest::Approx((T)2.3));
  298. CHECK(Math::lerp((T)2.0, (T)5.0, (T)1.0) == doctest::Approx((T)5.0));
  299. CHECK(Math::lerp((T)2.0, (T)5.0, (T)2.0) == doctest::Approx((T)8.0));
  300. CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)-0.1) == doctest::Approx((T)-1.7));
  301. CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)0.0) == doctest::Approx((T)-2.0));
  302. CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)0.1) == doctest::Approx((T)-2.3));
  303. CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)1.0) == doctest::Approx((T)-5.0));
  304. CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)2.0) == doctest::Approx((T)-8.0));
  305. }
  306. TEST_CASE_TEMPLATE("[Math] inverse_lerp", T, float, double) {
  307. CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)1.7) == doctest::Approx((T)-0.1));
  308. CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)2.0) == doctest::Approx((T)0.0));
  309. CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)2.3) == doctest::Approx((T)0.1));
  310. CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)5.0) == doctest::Approx((T)1.0));
  311. CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)8.0) == doctest::Approx((T)2.0));
  312. CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-1.7) == doctest::Approx((T)-0.1));
  313. CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-2.0) == doctest::Approx((T)0.0));
  314. CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-2.3) == doctest::Approx((T)0.1));
  315. CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-5.0) == doctest::Approx((T)1.0));
  316. CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-8.0) == doctest::Approx((T)2.0));
  317. }
  318. TEST_CASE_TEMPLATE("[Math] remap", T, float, double) {
  319. CHECK(Math::remap((T)50.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)-500.0));
  320. CHECK(Math::remap((T)100.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)0.0));
  321. CHECK(Math::remap((T)200.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1000.0));
  322. CHECK(Math::remap((T)250.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1500.0));
  323. CHECK(Math::remap((T)-50.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)-500.0));
  324. CHECK(Math::remap((T)-100.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)0.0));
  325. CHECK(Math::remap((T)-200.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1000.0));
  326. CHECK(Math::remap((T)-250.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1500.0));
  327. CHECK(Math::remap((T)-50.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)500.0));
  328. CHECK(Math::remap((T)-100.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)0.0));
  329. CHECK(Math::remap((T)-200.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)-1000.0));
  330. CHECK(Math::remap((T)-250.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)-1500.0));
  331. // Note: undefined behavior can happen when `p_istart == p_istop`. We don't bother testing this as it will
  332. // vary between hardware and compilers properly implementing IEEE 754.
  333. }
  334. TEST_CASE_TEMPLATE("[Math] angle_difference", T, float, double) {
  335. // Loops around, should return 0.0.
  336. CHECK(Math::angle_difference((T)0.0, (T)Math::TAU) == doctest::Approx((T)0.0));
  337. CHECK(Math::angle_difference((T)Math::PI, (T)-Math::PI) == doctest::Approx((T)0.0));
  338. CHECK(Math::angle_difference((T)0.0, (T)Math::TAU * (T)4.0) == doctest::Approx((T)0.0));
  339. // Rotation is clockwise, so it should return -PI.
  340. CHECK(Math::angle_difference((T)0.0, (T)Math::PI) == doctest::Approx((T)-Math::PI));
  341. CHECK(Math::angle_difference((T)0.0, (T)-Math::PI) == doctest::Approx((T)Math::PI));
  342. CHECK(Math::angle_difference((T)Math::PI, (T)0.0) == doctest::Approx((T)Math::PI));
  343. CHECK(Math::angle_difference((T)-Math::PI, (T)0.0) == doctest::Approx((T)-Math::PI));
  344. CHECK(Math::angle_difference((T)0.0, (T)3.0) == doctest::Approx((T)3.0));
  345. CHECK(Math::angle_difference((T)1.0, (T)-2.0) == doctest::Approx((T)-3.0));
  346. CHECK(Math::angle_difference((T)-1.0, (T)2.0) == doctest::Approx((T)3.0));
  347. CHECK(Math::angle_difference((T)-2.0, (T)-4.5) == doctest::Approx((T)-2.5));
  348. CHECK(Math::angle_difference((T)100.0, (T)102.5) == doctest::Approx((T)2.5));
  349. }
  350. TEST_CASE_TEMPLATE("[Math] lerp_angle", T, float, double) {
  351. // Counter-clockwise rotation.
  352. CHECK(Math::lerp_angle((T)0.24 * Math::TAU, 0.75 * Math::TAU, 0.5) == doctest::Approx((T)-0.005 * Math::TAU));
  353. // Counter-clockwise rotation.
  354. CHECK(Math::lerp_angle((T)0.25 * Math::TAU, 0.75 * Math::TAU, 0.5) == doctest::Approx((T)0.0));
  355. // Clockwise rotation.
  356. CHECK(Math::lerp_angle((T)0.26 * Math::TAU, 0.75 * Math::TAU, 0.5) == doctest::Approx((T)0.505 * Math::TAU));
  357. CHECK(Math::lerp_angle((T)-0.25 * Math::TAU, 1.25 * Math::TAU, 0.5) == doctest::Approx((T)-0.5 * Math::TAU));
  358. CHECK(Math::lerp_angle((T)0.72 * Math::TAU, 1.44 * Math::TAU, 0.96) == doctest::Approx((T)0.4512 * Math::TAU));
  359. CHECK(Math::lerp_angle((T)0.72 * Math::TAU, 1.44 * Math::TAU, 1.04) == doctest::Approx((T)0.4288 * Math::TAU));
  360. // Initial and final angles are effectively identical, so the value returned
  361. // should always be the same regardless of the `weight` parameter.
  362. CHECK(Math::lerp_angle((T)-4 * Math::TAU, 4 * Math::TAU, -1.0) == doctest::Approx((T)-4.0 * Math::TAU));
  363. CHECK(Math::lerp_angle((T)-4 * Math::TAU, 4 * Math::TAU, 0.0) == doctest::Approx((T)-4.0 * Math::TAU));
  364. CHECK(Math::lerp_angle((T)-4 * Math::TAU, 4 * Math::TAU, 0.5) == doctest::Approx((T)-4.0 * Math::TAU));
  365. CHECK(Math::lerp_angle((T)-4 * Math::TAU, 4 * Math::TAU, 1.0) == doctest::Approx((T)-4.0 * Math::TAU));
  366. CHECK(Math::lerp_angle((T)-4 * Math::TAU, 4 * Math::TAU, 500.0) == doctest::Approx((T)-4.0 * Math::TAU));
  367. }
  368. TEST_CASE_TEMPLATE("[Math] move_toward", T, float, double) {
  369. CHECK(Math::move_toward(2.0, 5.0, -1.0) == doctest::Approx((T)1.0));
  370. CHECK(Math::move_toward(2.0, 5.0, 2.5) == doctest::Approx((T)4.5));
  371. CHECK(Math::move_toward(2.0, 5.0, 4.0) == doctest::Approx((T)5.0));
  372. CHECK(Math::move_toward(-2.0, -5.0, -1.0) == doctest::Approx((T)-1.0));
  373. CHECK(Math::move_toward(-2.0, -5.0, 2.5) == doctest::Approx((T)-4.5));
  374. CHECK(Math::move_toward(-2.0, -5.0, 4.0) == doctest::Approx((T)-5.0));
  375. }
  376. TEST_CASE_TEMPLATE("[Math] rotate_toward", T, float, double) {
  377. // Rotate toward.
  378. CHECK(Math::rotate_toward((T)0.0, (T)Math::PI * (T)0.75, (T)1.5) == doctest::Approx((T)1.5));
  379. CHECK(Math::rotate_toward((T)-2.0, (T)1.0, (T)2.5) == doctest::Approx((T)0.5));
  380. CHECK(Math::rotate_toward((T)-2.0, (T)Math::PI, (T)Math::PI) == doctest::Approx((T)-Math::PI));
  381. CHECK(Math::rotate_toward((T)1.0, (T)Math::PI, (T)20.0) == doctest::Approx((T)Math::PI));
  382. // Rotate away.
  383. CHECK(Math::rotate_toward((T)0.0, (T)0.0, (T)-1.5) == doctest::Approx((T)-1.5));
  384. CHECK(Math::rotate_toward((T)0.0, (T)0.0, (T)-Math::PI) == doctest::Approx((T)-Math::PI));
  385. CHECK(Math::rotate_toward((T)3.0, (T)Math::PI, (T)-Math::PI) == doctest::Approx((T)0.0));
  386. CHECK(Math::rotate_toward((T)2.0, (T)Math::PI, (T)-1.5) == doctest::Approx((T)0.5));
  387. CHECK(Math::rotate_toward((T)1.0, (T)2.0, (T)-0.5) == doctest::Approx((T)0.5));
  388. CHECK(Math::rotate_toward((T)2.5, (T)2.0, (T)-0.5) == doctest::Approx((T)3.0));
  389. CHECK(Math::rotate_toward((T)-1.0, (T)1.0, (T)-1.0) == doctest::Approx((T)-2.0));
  390. }
  391. TEST_CASE_TEMPLATE("[Math] smoothstep", T, float, double) {
  392. CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)-5.0) == doctest::Approx((T)0.0));
  393. CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)0.5) == doctest::Approx((T)0.15625));
  394. CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)1.0) == doctest::Approx((T)0.5));
  395. CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)2.0) == doctest::Approx((T)1.0));
  396. }
  397. TEST_CASE("[Math] ease") {
  398. CHECK(Math::ease(0.1, 1.0) == doctest::Approx(0.1));
  399. CHECK(Math::ease(0.1, 2.0) == doctest::Approx(0.01));
  400. CHECK(Math::ease(0.1, 0.5) == doctest::Approx(0.19));
  401. CHECK(Math::ease(0.1, 0.0) == doctest::Approx(0));
  402. CHECK(Math::ease(0.1, -0.5) == doctest::Approx(0.2236067977));
  403. CHECK(Math::ease(0.1, -1.0) == doctest::Approx(0.1));
  404. CHECK(Math::ease(0.1, -2.0) == doctest::Approx(0.02));
  405. CHECK(Math::ease(-1.0, 1.0) == doctest::Approx(0));
  406. CHECK(Math::ease(-1.0, 2.0) == doctest::Approx(0));
  407. CHECK(Math::ease(-1.0, 0.5) == doctest::Approx(0));
  408. CHECK(Math::ease(-1.0, 0.0) == doctest::Approx(0));
  409. CHECK(Math::ease(-1.0, -0.5) == doctest::Approx(0));
  410. CHECK(Math::ease(-1.0, -1.0) == doctest::Approx(0));
  411. CHECK(Math::ease(-1.0, -2.0) == doctest::Approx(0));
  412. }
  413. TEST_CASE("[Math] snapped") {
  414. CHECK(Math::snapped(0.5, 0.04) == doctest::Approx(0.52));
  415. CHECK(Math::snapped(-0.5, 0.04) == doctest::Approx(-0.48));
  416. CHECK(Math::snapped(0.0, 0.04) == doctest::Approx(0));
  417. CHECK(Math::snapped(128'000.025, 0.04) == doctest::Approx(128'000.04));
  418. CHECK(Math::snapped(0.5, 400) == doctest::Approx(0));
  419. CHECK(Math::snapped(-0.5, 400) == doctest::Approx(0));
  420. CHECK(Math::snapped(0.0, 400) == doctest::Approx(0));
  421. CHECK(Math::snapped(128'000.025, 400) == doctest::Approx(128'000.0));
  422. CHECK(Math::snapped(0.5, 0.0) == doctest::Approx(0.5));
  423. CHECK(Math::snapped(-0.5, 0.0) == doctest::Approx(-0.5));
  424. CHECK(Math::snapped(0.0, 0.0) == doctest::Approx(0.0));
  425. CHECK(Math::snapped(128'000.025, 0.0) == doctest::Approx(128'000.0));
  426. CHECK(Math::snapped(0.5, -1.0) == doctest::Approx(0));
  427. CHECK(Math::snapped(-0.5, -1.0) == doctest::Approx(-1.0));
  428. CHECK(Math::snapped(0.0, -1.0) == doctest::Approx(0));
  429. CHECK(Math::snapped(128'000.025, -1.0) == doctest::Approx(128'000.0));
  430. }
  431. TEST_CASE("[Math] larger_prime") {
  432. CHECK(Math::larger_prime(0) == 5);
  433. CHECK(Math::larger_prime(1) == 5);
  434. CHECK(Math::larger_prime(2) == 5);
  435. CHECK(Math::larger_prime(5) == 13);
  436. CHECK(Math::larger_prime(500) == 769);
  437. CHECK(Math::larger_prime(1'000'000) == 1'572'869);
  438. CHECK(Math::larger_prime(1'000'000'000) == 1'610'612'741);
  439. // The next prime is larger than `INT32_MAX` and is not present in the built-in prime table.
  440. ERR_PRINT_OFF;
  441. CHECK(Math::larger_prime(2'000'000'000) == 0);
  442. ERR_PRINT_ON;
  443. }
  444. TEST_CASE_TEMPLATE("[Math] fmod", T, float, double) {
  445. CHECK(Math::fmod((T)-2.0, (T)0.3) == doctest::Approx((T)-0.2));
  446. CHECK(Math::fmod((T)0.0, (T)0.3) == doctest::Approx((T)0.0));
  447. CHECK(Math::fmod((T)2.0, (T)0.3) == doctest::Approx((T)0.2));
  448. CHECK(Math::fmod((T)-2.0, (T)-0.3) == doctest::Approx((T)-0.2));
  449. CHECK(Math::fmod((T)0.0, (T)-0.3) == doctest::Approx((T)0.0));
  450. CHECK(Math::fmod((T)2.0, (T)-0.3) == doctest::Approx((T)0.2));
  451. }
  452. TEST_CASE_TEMPLATE("[Math] fposmod", T, float, double) {
  453. CHECK(Math::fposmod((T)-2.0, (T)0.3) == doctest::Approx((T)0.1));
  454. CHECK(Math::fposmod((T)0.0, (T)0.3) == doctest::Approx((T)0.0));
  455. CHECK(Math::fposmod((T)2.0, (T)0.3) == doctest::Approx((T)0.2));
  456. CHECK(Math::fposmod((T)-2.0, (T)-0.3) == doctest::Approx((T)-0.2));
  457. CHECK(Math::fposmod((T)0.0, (T)-0.3) == doctest::Approx((T)0.0));
  458. CHECK(Math::fposmod((T)2.0, (T)-0.3) == doctest::Approx((T)-0.1));
  459. }
  460. TEST_CASE_TEMPLATE("[Math] fposmodp", T, float, double) {
  461. CHECK(Math::fposmodp((T)-2.0, (T)0.3) == doctest::Approx((T)0.1));
  462. CHECK(Math::fposmodp((T)0.0, (T)0.3) == doctest::Approx((T)0.0));
  463. CHECK(Math::fposmodp((T)2.0, (T)0.3) == doctest::Approx((T)0.2));
  464. CHECK(Math::fposmodp((T)-2.0, (T)-0.3) == doctest::Approx((T)-0.5));
  465. CHECK(Math::fposmodp((T)0.0, (T)-0.3) == doctest::Approx((T)0.0));
  466. CHECK(Math::fposmodp((T)2.0, (T)-0.3) == doctest::Approx((T)0.2));
  467. }
  468. TEST_CASE("[Math] posmod") {
  469. CHECK(Math::posmod(-20, 3) == 1);
  470. CHECK(Math::posmod(0, 3) == 0);
  471. CHECK(Math::posmod(20, 3) == 2);
  472. CHECK(Math::posmod(-20, -3) == -2);
  473. CHECK(Math::posmod(0, -3) == 0);
  474. CHECK(Math::posmod(20, -3) == -1);
  475. }
  476. TEST_CASE("[Math] wrapi") {
  477. CHECK(Math::wrapi(-30, -20, 160) == 150);
  478. CHECK(Math::wrapi(30, -20, 160) == 30);
  479. CHECK(Math::wrapi(300, -20, 160) == 120);
  480. CHECK(Math::wrapi(300'000'000'000, -20, 160) == 120);
  481. }
  482. TEST_CASE_TEMPLATE("[Math] wrapf", T, float, double) {
  483. CHECK(Math::wrapf((T)-30.0, (T)-20.0, (T)160.0) == doctest::Approx((T)150.0));
  484. CHECK(Math::wrapf((T)30.0, (T)-2.0, (T)160.0) == doctest::Approx((T)30.0));
  485. CHECK(Math::wrapf((T)300.0, (T)-20.0, (T)160.0) == doctest::Approx((T)120.0));
  486. CHECK(Math::wrapf(300'000'000'000.0, -20.0, 160.0) == doctest::Approx((T)120.0));
  487. // float's precision is too low for 300'000'000'000.0, so we reduce it by a factor of 1000.
  488. CHECK(Math::wrapf((float)15'000'000.0, (float)-20.0, (float)160.0) == doctest::Approx((T)60.0));
  489. }
  490. TEST_CASE_TEMPLATE("[Math] fract", T, float, double) {
  491. CHECK(Math::fract((T)1.0) == doctest::Approx((T)0.0));
  492. CHECK(Math::fract((T)77.8) == doctest::Approx((T)0.8));
  493. CHECK(Math::fract((T)-10.1) == doctest::Approx((T)0.9));
  494. }
  495. TEST_CASE_TEMPLATE("[Math] pingpong", T, float, double) {
  496. CHECK(Math::pingpong((T)0.0, (T)0.0) == doctest::Approx((T)0.0));
  497. CHECK(Math::pingpong((T)1.0, (T)1.0) == doctest::Approx((T)1.0));
  498. CHECK(Math::pingpong((T)0.5, (T)2.0) == doctest::Approx((T)0.5));
  499. CHECK(Math::pingpong((T)3.5, (T)2.0) == doctest::Approx((T)0.5));
  500. CHECK(Math::pingpong((T)11.5, (T)2.0) == doctest::Approx((T)0.5));
  501. CHECK(Math::pingpong((T)-2.5, (T)2.0) == doctest::Approx((T)1.5));
  502. }
  503. TEST_CASE_TEMPLATE("[Math] deg_to_rad/rad_to_deg", T, float, double) {
  504. CHECK(Math::deg_to_rad((T)180.0) == doctest::Approx((T)Math::PI));
  505. CHECK(Math::deg_to_rad((T)-27.0) == doctest::Approx((T)-0.471239));
  506. CHECK(Math::rad_to_deg((T)Math::PI) == doctest::Approx((T)180.0));
  507. CHECK(Math::rad_to_deg((T)-1.5) == doctest::Approx((T)-85.94366927));
  508. }
  509. TEST_CASE_TEMPLATE("[Math] cubic_interpolate", T, float, double) {
  510. CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.0) == doctest::Approx((T)0.2));
  511. CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.25) == doctest::Approx((T)0.33125));
  512. CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.5) == doctest::Approx((T)0.5));
  513. CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.75) == doctest::Approx((T)0.66875));
  514. CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)1.0) == doctest::Approx((T)0.8));
  515. CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)-50.0) == doctest::Approx((T)-6662732.3));
  516. CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)-5.0) == doctest::Approx((T)-9356.3));
  517. CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)0.0) == doctest::Approx((T)20.2));
  518. CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)1.0) == doctest::Approx((T)30.1));
  519. CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)4.0) == doctest::Approx((T)1853.2));
  520. }
  521. TEST_CASE_TEMPLATE("[Math] cubic_interpolate_angle", T, float, double) {
  522. CHECK(Math::cubic_interpolate_angle((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.0) == doctest::Approx((T)Math::PI * (1.0 / 6.0)));
  523. CHECK(Math::cubic_interpolate_angle((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.25) == doctest::Approx((T)0.973566));
  524. CHECK(Math::cubic_interpolate_angle((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.5) == doctest::Approx((T)Math::PI / 2.0));
  525. CHECK(Math::cubic_interpolate_angle((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.75) == doctest::Approx((T)2.16803));
  526. CHECK(Math::cubic_interpolate_angle((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)1.0) == doctest::Approx((T)Math::PI * (5.0 / 6.0)));
  527. }
  528. TEST_CASE_TEMPLATE("[Math] cubic_interpolate_in_time", T, float, double) {
  529. CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.0));
  530. CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.25, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.1625));
  531. CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.5, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.4));
  532. CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.75, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.6375));
  533. CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)1.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.8));
  534. }
  535. TEST_CASE_TEMPLATE("[Math] cubic_interpolate_angle_in_time", T, float, double) {
  536. CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.0));
  537. CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.25, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.494964));
  538. CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.5, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)1.27627));
  539. CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.75, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)2.07394));
  540. CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)1.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)Math::PI * (5.0 / 6.0)));
  541. }
  542. TEST_CASE_TEMPLATE("[Math] bezier_interpolate", T, float, double) {
  543. CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.0) == doctest::Approx((T)0.0));
  544. CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.25) == doctest::Approx((T)0.2125));
  545. CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.5) == doctest::Approx((T)0.5));
  546. CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.75) == doctest::Approx((T)0.7875));
  547. CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)1.0) == doctest::Approx((T)1.0));
  548. }
  549. } // namespace TestMath