ext_scalar_integer.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. #include <glm/ext/scalar_integer.hpp>
  2. #include <glm/ext/scalar_int_sized.hpp>
  3. #include <glm/ext/scalar_uint_sized.hpp>
  4. #include <vector>
  5. #include <ctime>
  6. #include <cstdio>
  7. #if GLM_LANG & GLM_LANG_CXX11_FLAG
  8. #include <chrono>
  9. namespace isPowerOfTwo
  10. {
  11. template<typename genType>
  12. struct type
  13. {
  14. genType Value;
  15. bool Return;
  16. };
  17. int test_int16()
  18. {
  19. type<glm::int16> const Data[] =
  20. {
  21. {0x0001, true},
  22. {0x0002, true},
  23. {0x0004, true},
  24. {0x0080, true},
  25. {0x0000, true},
  26. {0x0003, false}
  27. };
  28. int Error = 0;
  29. for(std::size_t i = 0, n = sizeof(Data) / sizeof(type<glm::int16>); i < n; ++i)
  30. {
  31. bool Result = glm::isPowerOfTwo(Data[i].Value);
  32. Error += Data[i].Return == Result ? 0 : 1;
  33. }
  34. return Error;
  35. }
  36. int test_uint16()
  37. {
  38. type<glm::uint16> const Data[] =
  39. {
  40. {0x0001, true},
  41. {0x0002, true},
  42. {0x0004, true},
  43. {0x0000, true},
  44. {0x0000, true},
  45. {0x0003, false}
  46. };
  47. int Error = 0;
  48. for(std::size_t i = 0, n = sizeof(Data) / sizeof(type<glm::uint16>); i < n; ++i)
  49. {
  50. bool Result = glm::isPowerOfTwo(Data[i].Value);
  51. Error += Data[i].Return == Result ? 0 : 1;
  52. }
  53. return Error;
  54. }
  55. int test_int32()
  56. {
  57. type<int> const Data[] =
  58. {
  59. {0x00000001, true},
  60. {0x00000002, true},
  61. {0x00000004, true},
  62. {0x0000000f, false},
  63. {0x00000000, true},
  64. {0x00000003, false}
  65. };
  66. int Error = 0;
  67. for(std::size_t i = 0, n = sizeof(Data) / sizeof(type<int>); i < n; ++i)
  68. {
  69. bool Result = glm::isPowerOfTwo(Data[i].Value);
  70. Error += Data[i].Return == Result ? 0 : 1;
  71. }
  72. return Error;
  73. }
  74. int test_uint32()
  75. {
  76. type<glm::uint> const Data[] =
  77. {
  78. {0x00000001, true},
  79. {0x00000002, true},
  80. {0x00000004, true},
  81. {0x80000000, true},
  82. {0x00000000, true},
  83. {0x00000003, false}
  84. };
  85. int Error = 0;
  86. for(std::size_t i = 0, n = sizeof(Data) / sizeof(type<glm::uint>); i < n; ++i)
  87. {
  88. bool Result = glm::isPowerOfTwo(Data[i].Value);
  89. Error += Data[i].Return == Result ? 0 : 1;
  90. }
  91. return Error;
  92. }
  93. int test()
  94. {
  95. int Error = 0;
  96. Error += test_int16();
  97. Error += test_uint16();
  98. Error += test_int32();
  99. Error += test_uint32();
  100. return Error;
  101. }
  102. }//isPowerOfTwo
  103. namespace nextPowerOfTwo_advanced
  104. {
  105. template<typename genIUType>
  106. GLM_FUNC_QUALIFIER genIUType highestBitValue(genIUType Value)
  107. {
  108. genIUType tmp = Value;
  109. genIUType result = genIUType(0);
  110. while(tmp)
  111. {
  112. result = (tmp & (~tmp + 1)); // grab lowest bit
  113. tmp &= ~result; // clear lowest bit
  114. }
  115. return result;
  116. }
  117. template<typename genType>
  118. GLM_FUNC_QUALIFIER genType nextPowerOfTwo_loop(genType value)
  119. {
  120. return glm::isPowerOfTwo(value) ? value : highestBitValue(value) << 1;
  121. }
  122. template<typename genType>
  123. struct type
  124. {
  125. genType Value;
  126. genType Return;
  127. };
  128. int test_int32()
  129. {
  130. type<glm::int32> const Data[] =
  131. {
  132. {0x0000ffff, 0x00010000},
  133. {-3, -4},
  134. {-8, -8},
  135. {0x00000001, 0x00000001},
  136. {0x00000002, 0x00000002},
  137. {0x00000004, 0x00000004},
  138. {0x00000007, 0x00000008},
  139. {0x0000fff0, 0x00010000},
  140. {0x0000f000, 0x00010000},
  141. {0x08000000, 0x08000000},
  142. {0x00000000, 0x00000000},
  143. {0x00000003, 0x00000004}
  144. };
  145. int Error(0);
  146. for(std::size_t i = 0, n = sizeof(Data) / sizeof(type<glm::int32>); i < n; ++i)
  147. {
  148. glm::int32 Result = glm::nextPowerOfTwo(Data[i].Value);
  149. Error += Data[i].Return == Result ? 0 : 1;
  150. }
  151. return Error;
  152. }
  153. int test_uint32()
  154. {
  155. type<glm::uint32> const Data[] =
  156. {
  157. {0x00000001, 0x00000001},
  158. {0x00000002, 0x00000002},
  159. {0x00000004, 0x00000004},
  160. {0x00000007, 0x00000008},
  161. {0x0000ffff, 0x00010000},
  162. {0x0000fff0, 0x00010000},
  163. {0x0000f000, 0x00010000},
  164. {0x80000000, 0x80000000},
  165. {0x00000000, 0x00000000},
  166. {0x00000003, 0x00000004}
  167. };
  168. int Error(0);
  169. for(std::size_t i = 0, n = sizeof(Data) / sizeof(type<glm::uint32>); i < n; ++i)
  170. {
  171. glm::uint32 Result = glm::nextPowerOfTwo(Data[i].Value);
  172. Error += Data[i].Return == Result ? 0 : 1;
  173. }
  174. return Error;
  175. }
  176. int perf()
  177. {
  178. int Error(0);
  179. std::vector<glm::uint> v;
  180. v.resize(100000000);
  181. std::clock_t Timestramp0 = std::clock();
  182. for(glm::uint32 i = 0, n = static_cast<glm::uint>(v.size()); i < n; ++i)
  183. v[i] = nextPowerOfTwo_loop(i);
  184. std::clock_t Timestramp1 = std::clock();
  185. for(glm::uint32 i = 0, n = static_cast<glm::uint>(v.size()); i < n; ++i)
  186. v[i] = glm::nextPowerOfTwo(i);
  187. std::clock_t Timestramp2 = std::clock();
  188. std::printf("nextPowerOfTwo_loop: %d clocks\n", static_cast<int>(Timestramp1 - Timestramp0));
  189. std::printf("glm::nextPowerOfTwo: %d clocks\n", static_cast<int>(Timestramp2 - Timestramp1));
  190. return Error;
  191. }
  192. int test()
  193. {
  194. int Error(0);
  195. Error += test_int32();
  196. Error += test_uint32();
  197. return Error;
  198. }
  199. }//namespace nextPowerOfTwo_advanced
  200. namespace prevPowerOfTwo
  201. {
  202. template <typename T>
  203. int run()
  204. {
  205. int Error = 0;
  206. T const A = glm::prevPowerOfTwo(static_cast<T>(7));
  207. Error += A == static_cast<T>(4) ? 0 : 1;
  208. T const B = glm::prevPowerOfTwo(static_cast<T>(15));
  209. Error += B == static_cast<T>(8) ? 0 : 1;
  210. T const C = glm::prevPowerOfTwo(static_cast<T>(31));
  211. Error += C == static_cast<T>(16) ? 0 : 1;
  212. T const D = glm::prevPowerOfTwo(static_cast<T>(32));
  213. Error += D == static_cast<T>(32) ? 0 : 1;
  214. return Error;
  215. }
  216. int test()
  217. {
  218. int Error = 0;
  219. Error += run<glm::int8>();
  220. Error += run<glm::int16>();
  221. Error += run<glm::int32>();
  222. Error += run<glm::int64>();
  223. Error += run<glm::uint8>();
  224. Error += run<glm::uint16>();
  225. Error += run<glm::uint32>();
  226. Error += run<glm::uint64>();
  227. return Error;
  228. }
  229. }//namespace prevPowerOfTwo
  230. namespace nextPowerOfTwo
  231. {
  232. template <typename T>
  233. int run()
  234. {
  235. int Error = 0;
  236. T const A = glm::nextPowerOfTwo(static_cast<T>(7));
  237. Error += A == static_cast<T>(8) ? 0 : 1;
  238. T const B = glm::nextPowerOfTwo(static_cast<T>(15));
  239. Error += B == static_cast<T>(16) ? 0 : 1;
  240. T const C = glm::nextPowerOfTwo(static_cast<T>(31));
  241. Error += C == static_cast<T>(32) ? 0 : 1;
  242. T const D = glm::nextPowerOfTwo(static_cast<T>(32));
  243. Error += D == static_cast<T>(32) ? 0 : 1;
  244. return Error;
  245. }
  246. int test()
  247. {
  248. int Error = 0;
  249. Error += run<glm::int8>();
  250. Error += run<glm::int16>();
  251. Error += run<glm::int32>();
  252. Error += run<glm::int64>();
  253. Error += run<glm::uint8>();
  254. Error += run<glm::uint16>();
  255. Error += run<glm::uint32>();
  256. Error += run<glm::uint64>();
  257. return Error;
  258. }
  259. }//namespace nextPowerOfTwo
  260. namespace prevMultiple
  261. {
  262. template<typename genIUType>
  263. struct type
  264. {
  265. genIUType Source;
  266. genIUType Multiple;
  267. genIUType Return;
  268. };
  269. template <typename T>
  270. int run()
  271. {
  272. type<T> const Data[] =
  273. {
  274. {8, 3, 6},
  275. {7, 7, 7}
  276. };
  277. int Error = 0;
  278. for(std::size_t i = 0, n = sizeof(Data) / sizeof(type<T>); i < n; ++i)
  279. {
  280. T const Result = glm::prevMultiple(Data[i].Source, Data[i].Multiple);
  281. Error += Data[i].Return == Result ? 0 : 1;
  282. }
  283. return Error;
  284. }
  285. int test()
  286. {
  287. int Error = 0;
  288. Error += run<glm::int8>();
  289. Error += run<glm::int16>();
  290. Error += run<glm::int32>();
  291. Error += run<glm::int64>();
  292. Error += run<glm::uint8>();
  293. Error += run<glm::uint16>();
  294. Error += run<glm::uint32>();
  295. Error += run<glm::uint64>();
  296. return Error;
  297. }
  298. }//namespace prevMultiple
  299. namespace nextMultiple
  300. {
  301. static glm::uint const Multiples = 128;
  302. int perf_nextMultiple(glm::uint Samples)
  303. {
  304. std::vector<glm::uint> Results(Samples * Multiples);
  305. std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now();
  306. for(glm::uint Source = 0; Source < Samples; ++Source)
  307. for(glm::uint Multiple = 0; Multiple < Multiples; ++Multiple)
  308. {
  309. Results[Source * Multiples + Multiple] = glm::nextMultiple(Source, Multiples);
  310. }
  311. std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
  312. std::printf("- glm::nextMultiple Time %d microseconds\n", static_cast<int>(std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0).count()));
  313. glm::uint Result = 0;
  314. for(std::size_t i = 0, n = Results.size(); i < n; ++i)
  315. Result += Results[i];
  316. return Result > 0 ? 0 : 1;
  317. }
  318. template <typename T>
  319. GLM_FUNC_QUALIFIER T nextMultipleMod(T Source, T Multiple)
  320. {
  321. T const Tmp = Source - static_cast<T>(1);
  322. return Tmp + (Multiple - (Tmp % Multiple));
  323. }
  324. int perf_nextMultipleMod(glm::uint Samples)
  325. {
  326. std::vector<glm::uint> Results(Samples * Multiples);
  327. std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now();
  328. for(glm::uint Multiple = 0; Multiple < Multiples; ++Multiple)
  329. for (glm::uint Source = 0; Source < Samples; ++Source)
  330. {
  331. Results[Source * Multiples + Multiple] = nextMultipleMod(Source, Multiples);
  332. }
  333. std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
  334. std::printf("- nextMultipleMod Time %d microseconds\n", static_cast<int>(std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0).count()));
  335. glm::uint Result = 0;
  336. for(std::size_t i = 0, n = Results.size(); i < n; ++i)
  337. Result += Results[i];
  338. return Result > 0 ? 0 : 1;
  339. }
  340. template <typename T>
  341. GLM_FUNC_QUALIFIER T nextMultipleNeg(T Source, T Multiple)
  342. {
  343. if(Source > static_cast<T>(0))
  344. {
  345. T const Tmp = Source - static_cast<T>(1);
  346. return Tmp + (Multiple - (Tmp % Multiple));
  347. }
  348. else
  349. return Source + (-Source % Multiple);
  350. }
  351. int perf_nextMultipleNeg(glm::uint Samples)
  352. {
  353. std::vector<glm::uint> Results(Samples * Multiples);
  354. std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now();
  355. for(glm::uint Source = 0; Source < Samples; ++Source)
  356. for(glm::uint Multiple = 0; Multiple < Multiples; ++Multiple)
  357. {
  358. Results[Source * Multiples + Multiple] = nextMultipleNeg(Source, Multiples);
  359. }
  360. std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
  361. std::printf("- nextMultipleNeg Time %d microseconds\n", static_cast<int>(std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0).count()));
  362. glm::uint Result = 0;
  363. for (std::size_t i = 0, n = Results.size(); i < n; ++i)
  364. Result += Results[i];
  365. return Result > 0 ? 0 : 1;
  366. }
  367. template <typename T>
  368. GLM_FUNC_QUALIFIER T nextMultipleUFloat(T Source, T Multiple)
  369. {
  370. return Source + (Multiple - std::fmod(Source, Multiple));
  371. }
  372. int perf_nextMultipleUFloat(glm::uint Samples)
  373. {
  374. std::vector<float> Results(Samples * Multiples);
  375. std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now();
  376. for(glm::uint Source = 0; Source < Samples; ++Source)
  377. for(glm::uint Multiple = 0; Multiple < Multiples; ++Multiple)
  378. {
  379. Results[Source * Multiples + Multiple] = nextMultipleUFloat(static_cast<float>(Source), static_cast<float>(Multiples));
  380. }
  381. std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
  382. std::printf("- nextMultipleUFloat Time %d microseconds\n", static_cast<int>(std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0).count()));
  383. float Result = 0;
  384. for (std::size_t i = 0, n = Results.size(); i < n; ++i)
  385. Result += Results[i];
  386. return Result > 0.0f ? 0 : 1;
  387. }
  388. template <typename T>
  389. GLM_FUNC_QUALIFIER T nextMultipleFloat(T Source, T Multiple)
  390. {
  391. if(Source > static_cast<float>(0))
  392. return Source + (Multiple - std::fmod(Source, Multiple));
  393. else
  394. return Source + std::fmod(-Source, Multiple);
  395. }
  396. int perf_nextMultipleFloat(glm::uint Samples)
  397. {
  398. std::vector<float> Results(Samples * Multiples);
  399. std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now();
  400. for(glm::uint Source = 0; Source < Samples; ++Source)
  401. for(glm::uint Multiple = 0; Multiple < Multiples; ++Multiple)
  402. {
  403. Results[Source * Multiples + Multiple] = nextMultipleFloat(static_cast<float>(Source), static_cast<float>(Multiples));
  404. }
  405. std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
  406. std::printf("- nextMultipleFloat Time %d microseconds\n", static_cast<int>(std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0).count()));
  407. float Result = 0;
  408. for (std::size_t i = 0, n = Results.size(); i < n; ++i)
  409. Result += Results[i];
  410. return Result > 0.0f ? 0 : 1;
  411. }
  412. template<typename genIUType>
  413. struct type
  414. {
  415. genIUType Source;
  416. genIUType Multiple;
  417. genIUType Return;
  418. };
  419. template <typename T>
  420. int test_uint()
  421. {
  422. type<T> const Data[] =
  423. {
  424. { 3, 4, 4 },
  425. { 6, 3, 6 },
  426. { 5, 3, 6 },
  427. { 7, 7, 7 },
  428. { 0, 1, 0 },
  429. { 8, 3, 9 }
  430. };
  431. int Error = 0;
  432. for(std::size_t i = 0, n = sizeof(Data) / sizeof(type<T>); i < n; ++i)
  433. {
  434. T const Result0 = glm::nextMultiple(Data[i].Source, Data[i].Multiple);
  435. Error += Data[i].Return == Result0 ? 0 : 1;
  436. assert(!Error);
  437. T const Result1 = nextMultipleMod(Data[i].Source, Data[i].Multiple);
  438. Error += Data[i].Return == Result1 ? 0 : 1;
  439. assert(!Error);
  440. }
  441. return Error;
  442. }
  443. int perf()
  444. {
  445. int Error = 0;
  446. glm::uint const Samples = 10000;
  447. for(int i = 0; i < 4; ++i)
  448. {
  449. std::printf("Run %d :\n", i);
  450. Error += perf_nextMultiple(Samples);
  451. Error += perf_nextMultipleMod(Samples);
  452. Error += perf_nextMultipleNeg(Samples);
  453. Error += perf_nextMultipleUFloat(Samples);
  454. Error += perf_nextMultipleFloat(Samples);
  455. std::printf("\n");
  456. }
  457. return Error;
  458. }
  459. int test()
  460. {
  461. int Error = 0;
  462. Error += test_uint<glm::int8>();
  463. Error += test_uint<glm::int16>();
  464. Error += test_uint<glm::int32>();
  465. Error += test_uint<glm::int64>();
  466. Error += test_uint<glm::uint8>();
  467. Error += test_uint<glm::uint16>();
  468. Error += test_uint<glm::uint32>();
  469. Error += test_uint<glm::uint64>();
  470. return Error;
  471. }
  472. }//namespace nextMultiple
  473. namespace findNSB
  474. {
  475. template<typename T>
  476. struct type
  477. {
  478. T Source;
  479. int SignificantBitCount;
  480. int Return;
  481. };
  482. template <typename T>
  483. int run()
  484. {
  485. type<T> const Data[] =
  486. {
  487. { 0x00, 1,-1 },
  488. { 0x01, 2,-1 },
  489. { 0x02, 2,-1 },
  490. { 0x06, 3,-1 },
  491. { 0x01, 1, 0 },
  492. { 0x03, 1, 0 },
  493. { 0x03, 2, 1 },
  494. { 0x07, 2, 1 },
  495. { 0x05, 2, 2 },
  496. { 0x0D, 2, 2 }
  497. };
  498. int Error = 0;
  499. for (std::size_t i = 0, n = sizeof(Data) / sizeof(type<T>); i < n; ++i)
  500. {
  501. int const Result0 = glm::findNSB(Data[i].Source, Data[i].SignificantBitCount);
  502. Error += Data[i].Return == Result0 ? 0 : 1;
  503. assert(!Error);
  504. }
  505. return Error;
  506. }
  507. int test()
  508. {
  509. int Error = 0;
  510. Error += run<glm::uint8>();
  511. Error += run<glm::uint16>();
  512. Error += run<glm::uint32>();
  513. Error += run<glm::uint64>();
  514. Error += run<glm::int8>();
  515. Error += run<glm::int16>();
  516. Error += run<glm::int32>();
  517. Error += run<glm::int64>();
  518. return Error;
  519. }
  520. }//namespace findNSB
  521. int main()
  522. {
  523. int Error = 0;
  524. Error += findNSB::test();
  525. Error += isPowerOfTwo::test();
  526. Error += prevPowerOfTwo::test();
  527. Error += nextPowerOfTwo::test();
  528. Error += nextPowerOfTwo_advanced::test();
  529. Error += prevMultiple::test();
  530. Error += nextMultiple::test();
  531. # ifdef NDEBUG
  532. Error += nextPowerOfTwo_advanced::perf();
  533. Error += nextMultiple::perf();
  534. # endif//NDEBUG
  535. return Error;
  536. }
  537. #else
  538. int main()
  539. {
  540. return 0;
  541. }
  542. #endif