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