ext_scalar_integer.cpp 15 KB

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