gtx_fast_trigonometry.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. #include <glm/ext/scalar_ulp.hpp>
  2. #define GLM_ENABLE_EXPERIMENTAL
  3. #include <glm/gtc/type_precision.hpp>
  4. #include <glm/gtx/fast_trigonometry.hpp>
  5. #include <glm/gtx/integer.hpp>
  6. #include <glm/gtx/common.hpp>
  7. #include <glm/gtc/constants.hpp>
  8. #include <glm/gtc/vec1.hpp>
  9. #include <glm/trigonometric.hpp>
  10. #include <cmath>
  11. #include <ctime>
  12. #include <cstdio>
  13. #include <vector>
  14. namespace fastCos
  15. {
  16. static int perf(bool NextFloat)
  17. {
  18. const float begin = -glm::pi<float>();
  19. const float end = glm::pi<float>();
  20. float result = 0.f;
  21. const std::clock_t timestamp1 = std::clock();
  22. for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i + 0.1f)
  23. result = glm::fastCos(i);
  24. const std::clock_t timestamp2 = std::clock();
  25. for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i + 0.1f)
  26. result = glm::cos(i);
  27. const std::clock_t timestamp3 = std::clock();
  28. const std::clock_t time_fast = timestamp2 - timestamp1;
  29. const std::clock_t time_default = timestamp3 - timestamp2;
  30. std::printf("fastCos Time %d clocks\n", static_cast<int>(time_fast));
  31. std::printf("cos Time %d clocks\n", static_cast<int>(time_default));
  32. (void) result; // Silence set but not used warning
  33. return time_fast <= time_default ? 0 : 1;
  34. }
  35. }//namespace fastCos
  36. namespace fastSin
  37. {
  38. /*
  39. float sin(float x) {
  40. float temp;
  41. temp = (x + M_PI) / ((2 * M_PI) - M_PI);
  42. return limited_sin((x + M_PI) - ((2 * M_PI) - M_PI) * temp));
  43. }
  44. */
  45. static int perf(bool NextFloat)
  46. {
  47. const float begin = -glm::pi<float>();
  48. const float end = glm::pi<float>();
  49. float result = 0.f;
  50. const std::clock_t timestamp1 = std::clock();
  51. for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i + 0.1f)
  52. result = glm::fastSin(i);
  53. const std::clock_t timestamp2 = std::clock();
  54. for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i + 0.1f)
  55. result = glm::sin(i);
  56. const std::clock_t timestamp3 = std::clock();
  57. const std::clock_t time_fast = timestamp2 - timestamp1;
  58. const std::clock_t time_default = timestamp3 - timestamp2;
  59. std::printf("fastSin Time %d clocks\n", static_cast<int>(time_fast));
  60. std::printf("sin Time %d clocks\n", static_cast<int>(time_default));
  61. (void) result; // Silence set but not used warning
  62. return time_fast <= time_default ? 0 : 1;
  63. }
  64. }//namespace fastSin
  65. namespace fastTan
  66. {
  67. static int perf(bool NextFloat)
  68. {
  69. const float begin = -glm::pi<float>();
  70. const float end = glm::pi<float>();
  71. float result = 0.f;
  72. const std::clock_t timestamp1 = std::clock();
  73. for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i + 0.1f)
  74. result = glm::fastTan(i);
  75. const std::clock_t timestamp2 = std::clock();
  76. for (float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i + 0.1f)
  77. result = glm::tan(i);
  78. const std::clock_t timestamp3 = std::clock();
  79. const std::clock_t time_fast = timestamp2 - timestamp1;
  80. const std::clock_t time_default = timestamp3 - timestamp2;
  81. std::printf("fastTan Time %d clocks\n", static_cast<int>(time_fast));
  82. std::printf("tan Time %d clocks\n", static_cast<int>(time_default));
  83. (void) result; // Silence set but not used warning
  84. return time_fast <= time_default ? 0 : 1;
  85. }
  86. }//namespace fastTan
  87. namespace fastAcos
  88. {
  89. static int perf(bool NextFloat)
  90. {
  91. const float begin = -glm::pi<float>();
  92. const float end = glm::pi<float>();
  93. float result = 0.f;
  94. const std::clock_t timestamp1 = std::clock();
  95. for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i + 0.1f)
  96. result = glm::fastAcos(i);
  97. const std::clock_t timestamp2 = std::clock();
  98. for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i + 0.1f)
  99. result = glm::acos(i);
  100. const std::clock_t timestamp3 = std::clock();
  101. const std::clock_t time_fast = timestamp2 - timestamp1;
  102. const std::clock_t time_default = timestamp3 - timestamp2;
  103. std::printf("fastAcos Time %d clocks\n", static_cast<int>(time_fast));
  104. std::printf("acos Time %d clocks\n", static_cast<int>(time_default));
  105. (void) result; // Silence set but not used warning
  106. return time_fast <= time_default ? 0 : 1;
  107. }
  108. }//namespace fastAcos
  109. namespace fastAsin
  110. {
  111. static int perf(bool NextFloat)
  112. {
  113. const float begin = -glm::pi<float>();
  114. const float end = glm::pi<float>();
  115. float result = 0.f;
  116. const std::clock_t timestamp1 = std::clock();
  117. for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i + 0.1f)
  118. result = glm::fastAsin(i);
  119. const std::clock_t timestamp2 = std::clock();
  120. for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i + 0.1f)
  121. result = glm::asin(i);
  122. const std::clock_t timestamp3 = std::clock();
  123. const std::clock_t time_fast = timestamp2 - timestamp1;
  124. const std::clock_t time_default = timestamp3 - timestamp2;
  125. std::printf("fastAsin Time %d clocks\n", static_cast<int>(time_fast));
  126. std::printf("asin Time %d clocks\n", static_cast<int>(time_default));
  127. (void) result; // Silence set but not used warning
  128. return time_fast <= time_default ? 0 : 1;
  129. }
  130. }//namespace fastAsin
  131. namespace fastAtan
  132. {
  133. static int perf(bool NextFloat)
  134. {
  135. const float begin = -glm::pi<float>();
  136. const float end = glm::pi<float>();
  137. float result = 0.f;
  138. const std::clock_t timestamp1 = std::clock();
  139. for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i + 0.1f)
  140. result = glm::fastAtan(i);
  141. const std::clock_t timestamp2 = std::clock();
  142. for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i + 0.1f)
  143. result = glm::atan(i);
  144. const std::clock_t timestamp3 = std::clock();
  145. const std::clock_t time_fast = timestamp2 - timestamp1;
  146. const std::clock_t time_default = timestamp3 - timestamp2;
  147. std::printf("fastAtan Time %d clocks\n", static_cast<int>(time_fast));
  148. std::printf("atan Time %d clocks\n", static_cast<int>(time_default));
  149. (void) result; // Silence set but not used warning
  150. return time_fast <= time_default ? 0 : 1;
  151. }
  152. }//namespace fastAtan
  153. namespace taylorCos
  154. {
  155. using glm::qualifier;
  156. using glm::length_t;
  157. # if (GLM_COMPILER & GLM_COMPILER_CLANG)
  158. # pragma clang diagnostic push
  159. # pragma clang diagnostic ignored "-Wglobal-constructors"
  160. # endif
  161. glm::vec4 const AngleShift(0.0f, glm::half_pi<float>(), glm::pi<float>(), glm::three_over_two_pi<float>());
  162. # if (GLM_COMPILER & GLM_COMPILER_CLANG)
  163. # pragma clang diagnostic pop
  164. # endif
  165. template<length_t L, typename T, qualifier Q>
  166. static GLM_FUNC_QUALIFIER glm::vec<L, T, Q> taylorSeriesNewCos(glm::vec<L, T, Q> const& x)
  167. {
  168. glm::vec<L, T, Q> const Powed2(x * x);
  169. glm::vec<L, T, Q> const Powed4(Powed2 * Powed2);
  170. glm::vec<L, T, Q> const Powed6(Powed4 * Powed2);
  171. glm::vec<L, T, Q> const Powed8(Powed4 * Powed4);
  172. return static_cast<T>(1)
  173. - Powed2 * static_cast<T>(0.5)
  174. + Powed4 * static_cast<T>(0.04166666666666666666666666666667)
  175. - Powed6 * static_cast<T>(0.00138888888888888888888888888889)
  176. + Powed8 * static_cast<T>(2.4801587301587301587301587301587e-5);
  177. }
  178. /*
  179. template<length_t L, typename T, qualifier Q>
  180. static GLM_FUNC_QUALIFIER glm::vec<L, T, Q> taylorSeriesNewCos6(glm::vec<L, T, Q> const& x)
  181. {
  182. glm::vec<L, T, Q> const Powed2(x * x);
  183. glm::vec<L, T, Q> const Powed4(Powed2 * Powed2);
  184. glm::vec<L, T, Q> const Powed6(Powed4 * Powed2);
  185. return static_cast<T>(1)
  186. - Powed2 * static_cast<T>(0.5)
  187. + Powed4 * static_cast<T>(0.04166666666666666666666666666667)
  188. - Powed6 * static_cast<T>(0.00138888888888888888888888888889);
  189. }
  190. */
  191. /*
  192. template<glm::length_t L, qualifier Q>
  193. static GLM_FUNC_QUALIFIER glm::vec<L, float, Q> fastAbs(glm::vec<L, float, Q> x)
  194. {
  195. int* Pointer = reinterpret_cast<int*>(&x[0]);
  196. Pointer[0] &= 0x7fffffff;
  197. Pointer[1] &= 0x7fffffff;
  198. Pointer[2] &= 0x7fffffff;
  199. Pointer[3] &= 0x7fffffff;
  200. return x;
  201. }
  202. template<glm::length_t L, typename T, qualifier Q>
  203. static GLM_FUNC_QUALIFIER glm::vec<L, T, Q> fastCosNew(glm::vec<L, T, Q> const& x)
  204. {
  205. glm::vec<L, T, Q> const Angle0_PI(fastAbs(fmod(x + glm::pi<T>(), glm::two_pi<T>()) - glm::pi<T>()));
  206. return taylorSeriesNewCos6(x);
  207. // vec<L, bool, Q> const FirstQuarterPi(lessThanEqual(Angle0_PI, vec<L, T, Q>(glm::half_pi<T>())));
  208. // vec<L, T, Q> const RevertAngle(mix(vec<L, T, Q>(glm::pi<T>()), vec<L, T, Q>(0), FirstQuarterPi));
  209. // vec<L, T, Q> const ReturnSign(mix(vec<L, T, Q>(-1), vec<L, T, Q>(1), FirstQuarterPi));
  210. // vec<L, T, Q> const SectionAngle(RevertAngle - Angle0_PI);
  211. // return ReturnSign * taylorSeriesNewCos(SectionAngle);
  212. }
  213. */
  214. /*
  215. static int perf_fastCosNew(float Begin, float End, std::size_t Samples)
  216. {
  217. std::vector<glm::vec4> Results;
  218. Results.resize(Samples);
  219. float const Steps = (End - Begin) / static_cast<float>(Samples);
  220. std::clock_t const TimeStampBegin = std::clock();
  221. for(std::size_t i = 0; i < Samples; ++i)
  222. Results[i] = fastCosNew(AngleShift + glm::vec4(Begin + Steps * static_cast<float>(i)));
  223. std::clock_t const TimeStampEnd = std::clock();
  224. std::printf("fastCosNew %d clocks\n", static_cast<int>(TimeStampEnd - TimeStampBegin));
  225. int Error = 0;
  226. for(std::size_t i = 0; i < Samples; ++i)
  227. Error += Results[i].x >= -1.0f && Results[i].x <= 1.0f ? 0 : 1;
  228. return Error;
  229. }
  230. */
  231. template<length_t L, typename T, qualifier Q>
  232. static GLM_FUNC_QUALIFIER glm::vec<L, T, Q> deterministic_fmod(glm::vec<L, T, Q> const& x, T y)
  233. {
  234. return x - y * trunc(x / y);
  235. }
  236. template<length_t L, typename T, qualifier Q>
  237. static GLM_FUNC_QUALIFIER glm::vec<L, T, Q> fastCosDeterminisctic(glm::vec<L, T, Q> const& x)
  238. {
  239. glm::vec<L, T, Q> const Angle0_PI(abs(deterministic_fmod(x + glm::pi<T>(), glm::two_pi<T>()) - glm::pi<T>()));
  240. glm::vec<L, bool, Q> const FirstQuarterPi(lessThanEqual(Angle0_PI, glm::vec<L, T, Q>(glm::half_pi<T>())));
  241. glm::vec<L, T, Q> const RevertAngle(mix(glm::vec<L, T, Q>(glm::pi<T>()), glm::vec<L, T, Q>(0), FirstQuarterPi));
  242. glm::vec<L, T, Q> const ReturnSign(mix(glm::vec<L, T, Q>(-1), glm::vec<L, T, Q>(1), FirstQuarterPi));
  243. glm::vec<L, T, Q> const SectionAngle(RevertAngle - Angle0_PI);
  244. return ReturnSign * taylorSeriesNewCos(SectionAngle);
  245. }
  246. static int perf_fastCosDeterminisctic(float Begin, float End, std::size_t Samples)
  247. {
  248. std::vector<glm::vec4> Results;
  249. Results.resize(Samples);
  250. float const Steps = (End - Begin) / static_cast<float>(Samples);
  251. std::clock_t const TimeStampBegin = std::clock();
  252. for(std::size_t i = 0; i < Samples; ++i)
  253. Results[i] = taylorCos::fastCosDeterminisctic(AngleShift + glm::vec4(Begin + Steps * static_cast<float>(i)));
  254. std::clock_t const TimeStampEnd = std::clock();
  255. std::printf("fastCosDeterminisctic %d clocks\n", static_cast<int>(TimeStampEnd - TimeStampBegin));
  256. int Error = 0;
  257. for(std::size_t i = 0; i < Samples; ++i)
  258. Error += Results[i].x >= -1.0f && Results[i].x <= 1.0f ? 0 : 1;
  259. return Error;
  260. }
  261. template<length_t L, typename T, qualifier Q>
  262. static GLM_FUNC_QUALIFIER glm::vec<L, T, Q> taylorSeriesRefCos(glm::vec<L, T, Q> const& x)
  263. {
  264. return static_cast<T>(1)
  265. - (x * x) / glm::factorial(static_cast<T>(2))
  266. + (x * x * x * x) / glm::factorial(static_cast<T>(4))
  267. - (x * x * x * x * x * x) / glm::factorial(static_cast<T>(6))
  268. + (x * x * x * x * x * x * x * x) / glm::factorial(static_cast<T>(8));
  269. }
  270. template<length_t L, typename T, qualifier Q>
  271. static GLM_FUNC_QUALIFIER glm::vec<L, T, Q> fastRefCos(glm::vec<L, T, Q> const& x)
  272. {
  273. glm::vec<L, T, Q> const Angle0_PI(glm::abs(fmod(x + glm::pi<T>(), glm::two_pi<T>()) - glm::pi<T>()));
  274. // return taylorSeriesRefCos(Angle0_PI);
  275. glm::vec<L, bool, Q> const FirstQuarterPi(lessThanEqual(Angle0_PI, glm::vec<L, T, Q>(glm::half_pi<T>())));
  276. glm::vec<L, T, Q> const RevertAngle(mix(glm::vec<L, T, Q>(glm::pi<T>()), glm::vec<L, T, Q>(0), FirstQuarterPi));
  277. glm::vec<L, T, Q> const ReturnSign(mix(glm::vec<L, T, Q>(-1), glm::vec<L, T, Q>(1), FirstQuarterPi));
  278. glm::vec<L, T, Q> const SectionAngle(RevertAngle - Angle0_PI);
  279. return ReturnSign * taylorSeriesRefCos(SectionAngle);
  280. }
  281. static int perf_fastCosRef(float Begin, float End, std::size_t Samples)
  282. {
  283. std::vector<glm::vec4> Results;
  284. Results.resize(Samples);
  285. float const Steps = (End - Begin) / static_cast<float>(Samples);
  286. std::clock_t const TimeStampBegin = std::clock();
  287. for(std::size_t i = 0; i < Samples; ++i)
  288. Results[i] = taylorCos::fastRefCos(AngleShift + glm::vec4(Begin + Steps * static_cast<float>(i)));
  289. std::clock_t const TimeStampEnd = std::clock();
  290. std::printf("fastCosRef %d clocks\n", static_cast<int>(TimeStampEnd - TimeStampBegin));
  291. int Error = 0;
  292. for(std::size_t i = 0; i < Samples; ++i)
  293. Error += Results[i].x >= -1.0f && Results[i].x <= 1.0f ? 0 : 1;
  294. return Error;
  295. }
  296. static int perf_fastCosOld(float Begin, float End, std::size_t Samples)
  297. {
  298. std::vector<glm::vec4> Results;
  299. Results.resize(Samples);
  300. float const Steps = (End - Begin) / static_cast<float>(Samples);
  301. std::clock_t const TimeStampBegin = std::clock();
  302. for(std::size_t i = 0; i < Samples; ++i)
  303. Results[i] = glm::fastCos(AngleShift + glm::vec4(Begin + Steps * static_cast<float>(i)));
  304. std::clock_t const TimeStampEnd = std::clock();
  305. std::printf("fastCosOld %d clocks\n", static_cast<int>(TimeStampEnd - TimeStampBegin));
  306. int Error = 0;
  307. for(std::size_t i = 0; i < Samples; ++i)
  308. Error += Results[i].x >= -1.0f && Results[i].x <= 1.0f ? 0 : 1;
  309. return Error;
  310. }
  311. static int perf_cos(float Begin, float End, std::size_t Samples)
  312. {
  313. std::vector<glm::vec4> Results;
  314. Results.resize(Samples);
  315. float const Steps = (End - Begin) / static_cast<float>(Samples);
  316. std::clock_t const TimeStampBegin = std::clock();
  317. for(std::size_t i = 0; i < Samples; ++i)
  318. Results[i] = glm::cos(AngleShift + glm::vec4(Begin + Steps * static_cast<float>(i)));
  319. std::clock_t const TimeStampEnd = std::clock();
  320. std::printf("cos %d clocks\n", static_cast<int>(TimeStampEnd - TimeStampBegin));
  321. int Error = 0;
  322. for(std::size_t i = 0; i < Samples; ++i)
  323. Error += Results[i].x >= -1.0f && Results[i].x <= 1.0f ? 0 : 1;
  324. return Error;
  325. }
  326. static int perf(std::size_t const Samples)
  327. {
  328. int Error = 0;
  329. float const Begin = -glm::pi<float>();
  330. float const End = glm::pi<float>();
  331. Error += perf_cos(Begin, End, Samples);
  332. Error += perf_fastCosOld(Begin, End, Samples);
  333. Error += perf_fastCosRef(Begin, End, Samples);
  334. //Error += perf_fastCosNew(Begin, End, Samples);
  335. Error += perf_fastCosDeterminisctic(Begin, End, Samples);
  336. return Error;
  337. }
  338. static int test()
  339. {
  340. int Error = 0;
  341. //for(float Angle = -4.0f * glm::pi<float>(); Angle < 4.0f * glm::pi<float>(); Angle += 0.1f)
  342. //for(float Angle = -720.0f; Angle < 720.0f; Angle += 0.1f)
  343. for(float Angle = 0.0f; Angle < 180.0f; Angle += 0.1f)
  344. {
  345. float const modAngle = std::fmod(glm::abs(Angle), 360.f);
  346. assert(modAngle >= 0.0f && modAngle <= 360.f);
  347. float const radAngle = glm::radians(modAngle);
  348. float const Cos0 = std::cos(radAngle);
  349. float const Cos1 = taylorCos::fastRefCos(glm::fvec1(radAngle)).x;
  350. Error += glm::abs(Cos1 - Cos0) < 0.1f ? 0 : 1;
  351. //float const Cos2 = taylorCos::fastCosNew(glm::fvec1(radAngle)).x;
  352. //Error += glm::abs(Cos2 - Cos0) < 0.1f ? 0 : 1;
  353. assert(!Error);
  354. }
  355. return Error;
  356. }
  357. }//namespace taylorCos
  358. namespace taylor2
  359. {
  360. # if (GLM_COMPILER & GLM_COMPILER_CLANG)
  361. # pragma clang diagnostic push
  362. # pragma clang diagnostic ignored "-Wglobal-constructors"
  363. # endif
  364. glm::vec4 const AngleShift(0.0f, glm::pi<float>() * 0.5f, glm::pi<float>() * 1.0f, glm::pi<float>() * 1.5f);
  365. # if (GLM_COMPILER & GLM_COMPILER_CLANG)
  366. # pragma clang diagnostic pop
  367. # endif
  368. static float taylorCosA(float x)
  369. {
  370. return 1.f
  371. - (x * x) * (1.f / 2.f)
  372. + (x * x * x * x) * (1.f / 24.f)
  373. - (x * x * x * x * x * x) * (1.f / 720.f)
  374. + (x * x * x * x * x * x * x * x) * (1.f / 40320.f);
  375. }
  376. static float taylorCosB(float x)
  377. {
  378. return 1.f
  379. - (x * x) * (1.f / 2.f)
  380. + (x * x * x * x) * (1.f / 24.f)
  381. - (x * x * x * x * x * x) * (1.f / 720.f)
  382. + (x * x * x * x * x * x * x * x) * (1.f / 40320.f);
  383. }
  384. static float taylorCosC(float x)
  385. {
  386. return 1.f
  387. - (x * x) * (1.f / 2.f)
  388. + ((x * x) * (x * x)) * (1.f / 24.f)
  389. - (((x * x) * (x * x)) * (x * x)) * (1.f / 720.f)
  390. + (((x * x) * (x * x)) * ((x * x) * (x * x))) * (1.f / 40320.f);
  391. }
  392. static int perf_taylorCosA(float Begin, float End, std::size_t Samples)
  393. {
  394. std::vector<float> Results;
  395. Results.resize(Samples);
  396. float const Steps = (End - Begin) / static_cast<float>(Samples);
  397. std::clock_t const TimeStampBegin = std::clock();
  398. for(std::size_t i = 0; i < Samples; ++i)
  399. Results[i] = taylorCosA(AngleShift.x + Begin + Steps * static_cast<float>(i));
  400. std::clock_t const TimeStampEnd = std::clock();
  401. std::printf("taylorCosA %d clocks\n", static_cast<int>(TimeStampEnd - TimeStampBegin));
  402. int Error = 0;
  403. for(std::size_t i = 0; i < Samples; ++i)
  404. Error += Results[i] >= -1.0f && Results[i] <= 1.0f ? 0 : 1;
  405. return Error;
  406. }
  407. static int perf_taylorCosB(float Begin, float End, std::size_t Samples)
  408. {
  409. std::vector<float> Results;
  410. Results.resize(Samples);
  411. float const Steps = (End - Begin) / static_cast<float>(Samples);
  412. std::clock_t const TimeStampBegin = std::clock();
  413. for(std::size_t i = 0; i < Samples; ++i)
  414. Results[i] = taylorCosB(AngleShift.x + Begin + Steps * static_cast<float>(i));
  415. std::clock_t const TimeStampEnd = std::clock();
  416. std::printf("taylorCosB %d clocks\n", static_cast<int>(TimeStampEnd - TimeStampBegin));
  417. int Error = 0;
  418. for(std::size_t i = 0; i < Samples; ++i)
  419. Error += Results[i] >= -1.0f && Results[i] <= 1.0f ? 0 : 1;
  420. return Error;
  421. }
  422. static int perf_taylorCosC(float Begin, float End, std::size_t Samples)
  423. {
  424. std::vector<float> Results;
  425. Results.resize(Samples);
  426. float const Steps = (End - Begin) / static_cast<float>(Samples);
  427. std::clock_t const TimeStampBegin = std::clock();
  428. for(std::size_t i = 0; i < Samples; ++i)
  429. Results[i] = taylorCosC(AngleShift.x + Begin + Steps * static_cast<float>(i));
  430. std::clock_t const TimeStampEnd = std::clock();
  431. std::printf("taylorCosC %d clocks\n", static_cast<int>(TimeStampEnd - TimeStampBegin));
  432. int Error = 0;
  433. for(std::size_t i = 0; i < Samples; ++i)
  434. Error += Results[i] >= -1.0f && Results[i] <= 1.0f ? 0 : 1;
  435. return Error;
  436. }
  437. static int perf(std::size_t Samples)
  438. {
  439. int Error = 0;
  440. float const Begin = -glm::pi<float>();
  441. float const End = glm::pi<float>();
  442. Error += perf_taylorCosA(Begin, End, Samples);
  443. Error += perf_taylorCosB(Begin, End, Samples);
  444. Error += perf_taylorCosC(Begin, End, Samples);
  445. return Error;
  446. }
  447. }//namespace taylor2
  448. int main()
  449. {
  450. int Error(0);
  451. Error += ::taylor2::perf(1000);
  452. Error += ::taylorCos::test();
  453. Error += ::taylorCos::perf(1000);
  454. ::fastCos::perf(false);
  455. ::fastSin::perf(false);
  456. ::fastTan::perf(false);
  457. ::fastAcos::perf(false);
  458. ::fastAsin::perf(false);
  459. ::fastAtan::perf(false);
  460. return Error;
  461. }