ext_scalar_integer.cpp 15 KB

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