1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "Prerequisites/BsPrerequisitesUtil.h"
6#include "Math/BsMath.h"
7
8#if BS_COMPILER == BS_COMPILER_MSVC
9#include <intrin.h>
10#endif
11
12namespace bs
13{
14 /** @addtogroup General
15 * @{
16 */
17
18 /** Floating point number broken down into components for easier access. */
19 union Float754
20 {
21 UINT32 raw;
22 float value;
23 struct {
24#if BS_ENDIAN == BS_ENDIAN_BIG
25 UINT32 negative : 1;
26 UINT32 exponent : 8;
27 UINT32 mantissa : 23;
28#else
29 UINT32 mantissa : 23;
30 UINT32 exponent : 8;
31 UINT32 negative : 1;
32#endif
33 } field;
34 };
35
36 /** 10-bit floating point number broken down into components for easier access. */
37 union Float10
38 {
39 UINT32 raw;
40 struct {
41#if BS_ENDIAN == BS_ENDIAN_BIG
42 UINT32 exponent : 5;
43 UINT32 mantissa : 5;
44#else
45 UINT32 mantissa : 5;
46 UINT32 exponent : 5;
47#endif
48 } field;
49 };
50
51 /** 11-bit floating point number broken down into components for easier access. */
52 union Float11
53 {
54 UINT32 raw;
55 struct {
56#if BS_ENDIAN == BS_ENDIAN_BIG
57 UINT32 exponent : 5;
58 UINT32 mantissa : 6;
59#else
60 UINT32 mantissa : 6;
61 UINT32 exponent : 5;
62#endif
63 } field;
64 };
65
66 /** Class for manipulating bit patterns. */
67 class Bitwise
68 {
69 public:
70 /** Returns the power-of-two number greater or equal to the provided value. */
71 static UINT32 nextPow2(UINT32 n)
72 {
73 --n;
74 n |= n >> 16;
75 n |= n >> 8;
76 n |= n >> 4;
77 n |= n >> 2;
78 n |= n >> 1;
79 ++n;
80 return n;
81 }
82
83 /** Returns the power-of-two number closest to the provided value. */
84 static UINT32 closestPow2(UINT32 n)
85 {
86 UINT32 next = nextPow2(n);
87
88 UINT32 prev = next >> 1;
89 if (n - prev < next - n)
90 return prev;
91
92 return next;
93 }
94
95
96 /** Returns base-2 logarithm for common bit counts (8, 16, 32, 64), as a constant expression. */
97 static constexpr UINT32 bitsLog2(UINT32 v)
98 {
99 switch(v)
100 {
101 default:
102 case 8: return 3;
103 case 16: return 4;
104 case 32: return 5;
105 case 64: return 6;
106 }
107 }
108
109 /** Returns modular exponentiation for integers. */
110 static UINT32 modPow(UINT32 val1, UINT32 val2, UINT32 t)
111 {
112 int res = 1;
113
114 while (val2 != 0)
115 {
116 if (val2 & 1)
117 res = (res * val1) % t;
118
119 val2 >>= 1;
120 val1 = (val1 * val1) % t;
121 }
122
123 return res;
124 }
125#if BS_COMPILER == BS_COMPILER_MSVC
126#pragma intrinsic(_BitScanReverse,_BitScanForward)
127#endif
128
129 /** Finds the most-significant non-zero bit in the provided value and returns the index of that bit. */
130 static UINT32 mostSignificantBit(UINT32 val)
131 {
132#if BS_COMPILER == BS_COMPILER_MSVC
133 unsigned long index;
134 _BitScanReverse(&index, val);
135 return index;
136#elif BS_COMPILER == BS_COMPILER_GNUC || BS_COMPILER == BS_COMPILER_CLANG
137 return 31 - __builtin_clz(val);
138#else
139 static_assert(false, "Not implemented");
140#endif
141 }
142 /** Finds the least-significant non-zero bit in the provided value and returns the index of that bit. */
143 static UINT32 leastSignificantBit(UINT32 val)
144 {
145#if BS_COMPILER == BS_COMPILER_MSVC
146 unsigned long index;
147 _BitScanForward(&index, val);
148 return index;
149#elif BS_COMPILER == BS_COMPILER_GNUC || BS_COMPILER == BS_COMPILER_CLANG
150 return __builtin_ctz(val);
151#else
152 static_assert(false, "Not implemented");
153#endif
154 }
155
156 /** Finds the most-significant non-zero bit in the provided value and returns the index of that bit. */
157 static UINT32 mostSignificantBit(UINT64 val)
158 {
159#if BS_COMPILER == BS_COMPILER_MSVC
160#if BS_ARCH_TYPE == BS_ARCHITECTURE_x86_64
161 unsigned long index;
162 _BitScanReverse64(&index, val);
163 return index;
164#else // BS_ARCH_TYPE
165 if (static_cast<UINT32>(val >> 32) != 0)
166 {
167 _BitScanReverse(&index, static_cast<UINT32>(val >> 32));
168 return index + 32;
169 }
170 else
171 {
172 _BitScanReverse(&index, static_cast<UINT32>(val));
173 return index;
174 }
175#endif // BS_ARCH_TYPE
176#elif BS_COMPILER == BS_COMPILER_GNUC || BS_COMPILER == BS_COMPILER_CLANG
177 return 31 - __builtin_clzll(val);
178#else // BS_COMPILER
179 static_assert(false, "Not implemented");
180#endif // BS_COMPILER
181 }
182 /** Finds the least-significant non-zero bit in the provided value and returns the index of that bit. */
183 static UINT32 leastSignificantBit(UINT64 val)
184 {
185#if BS_COMPILER == BS_COMPILER_MSVC
186#if BS_ARCH_TYPE == BS_ARCHITECTURE_x86_64
187 unsigned long index;
188 _BitScanForward64(&index, val);
189 return index;
190#else // BS_ARCH_TYPE
191 if (static_cast<UINT32>(val) != 0)
192 {
193 _BitScanForward(&index, static_cast<UINT32>(val));
194 return index;
195 }
196 else
197 {
198 _BitScanForward(&index, static_cast<UINT32>(val >> 32));
199 return index + 32;
200 }
201#endif // BS_ARCH_TYPE
202#elif BS_COMPILER == BS_COMPILER_GNUC || BS_COMPILER == BS_COMPILER_CLANG
203 return __builtin_ctzll(val);
204#else // BS_COMPILER
205 static_assert(false, "Not implemented");
206#endif // BS_COMPILER
207 }
208
209 /** Determines whether the number is power-of-two or not. */
210 template<typename T>
211 static bool isPow2(T n)
212 {
213 return (n & (n - 1)) == 0;
214 }
215
216 /** Returns the number of bits a pattern must be shifted right by to remove right-hand zeros. */
217 template<typename T>
218 static uint32_t getBitShift(T mask)
219 {
220 if (mask == 0)
221 return 0;
222
223 uint32_t result = 0;
224 while ((mask & 1) == 0) {
225 ++result;
226 mask >>= 1;
227 }
228 return result;
229 }
230
231 /** Count the number of set bits in a mask. */
232 static uint32_t countSetBits(uint32_t val)
233 {
234 uint32_t count = 0;
235 for (count = 0; val; count++)
236 val &= val - 1;
237
238 return count;
239 }
240
241 /** Takes a value with a given src bit mask, and produces another value with a desired bit mask. */
242 template<typename SrcT, typename DestT>
243 static DestT convertBitPattern(SrcT srcValue, SrcT srcBitMask, DestT destBitMask)
244 {
245 // Mask off irrelevant source value bits (if any)
246 srcValue = srcValue & srcBitMask;
247
248 // Shift source down to bottom of DWORD
249 const uint32_t srcBitShift = getBitShift(srcBitMask);
250 srcValue >>= srcBitShift;
251
252 // Get max value possible in source from srcMask
253 const SrcT srcMax = srcBitMask >> srcBitShift;
254
255 // Get max available in dest
256 const uint32_t destBitShift = getBitShift(destBitMask);
257 const DestT destMax = destBitMask >> destBitShift;
258
259 // Scale source value into destination, and shift back
260 DestT destValue = (srcValue * destMax) / srcMax;
261 return (destValue << destBitShift);
262 }
263
264 /**
265 * Convert N bit color channel value to P bits. It fills P bits with the bit pattern repeated.
266 * (this is /((1<<n)-1) in fixed point).
267 */
268 static uint32_t fixedToFixed(UINT32 value, uint32_t n, uint32_t p)
269 {
270 if (n > p)
271 {
272 // Less bits required than available; this is easy
273 value >>= n - p;
274 }
275 else if (n < p)
276 {
277 // More bits required than are there, do the fill
278 // Use old fashioned division, probably better than a loop
279 if (value == 0)
280 value = 0;
281 else if (value == (static_cast<uint32_t>(1) << n) - 1)
282 value = (1 << p) - 1;
283 else value = value*(1 << p) / ((1 << n) - 1);
284 }
285 return value;
286 }
287
288 /**
289 * Converts floating point value in range [0, 1] to an unsigned integer of a certain number of bits. Works for any
290 * value of bits between 0 and 31.
291 */
292 static uint32_t unormToUint(float value, uint32_t bits)
293 {
294 if (value <= 0.0f) return 0;
295 if (value >= 1.0f) return (1 << bits) - 1;
296 return Math::roundToInt(value * (1 << bits));
297 }
298
299 /**
300 * Converts floating point value in range [-1, 1] to an unsigned integer of a certain number of bits. Works for any
301 * value of bits between 0 and 31.
302 */
303 static uint32_t snormToUint(float value, uint32_t bits)
304 {
305 return unormToUint((value + 1.0f) * 0.5f, bits);
306 }
307
308 /** Converts an unsigned integer to a floating point in range [0, 1]. */
309 static float uintToUnorm(uint32_t value, uint32_t bits)
310 {
311 return (float)value / (float)((1 << bits) - 1);
312 }
313
314 /** Converts an unsigned integer to a floating point in range [-1, 1]. */
315 static float uintToSnorm(uint32_t value, uint32_t bits)
316 {
317 return uintToUnorm(value) * 2.0f - 1.0f;
318 }
319
320 /**
321 * Converts floating point value in range [0, 1] to an unsigned integer of a certain number of bits. Works for any
322 * value of bits between 0 and 31.
323 */
324 template<uint32_t bits = 8>
325 static uint32_t unormToUint(float value)
326 {
327 if (value <= 0.0f) return 0;
328 if (value >= 1.0f) return (1 << bits) - 1;
329 return Math::roundToInt(value * (1 << bits));
330 }
331
332 /**
333 * Converts floating point value in range [-1, 1] to an unsigned integer of a certain number of bits. Works for any
334 * value of bits between 0 and 31.
335 */
336 template<uint32_t bits = 8>
337 static uint32_t snormToUint(float value)
338 {
339 return unormToUint<bits>((value + 1.0f) * 0.5f);
340 }
341
342 /** Converts an unsigned integer to a floating point in range [0, 1]. */
343 template<uint32_t bits = 8>
344 static float uintToUnorm(uint32_t value)
345 {
346 return (float)value / (float)((1 << bits) - 1);
347 }
348
349 /** Converts an unsigned integer to a floating point in range [-1, 1]. */
350 template<uint32_t bits = 8>
351 static float uintToSnorm(uint32_t value)
352 {
353 return uintToUnorm<bits>(value) * 2.0f - 1.0f;
354 }
355
356 /**
357 * Interpolates between two values using the @p t parameter. All parameters must be in [0, 255] range. When @p t
358 * is zero, @p from value will be returned, and when it is 255 @p to value will be returned, and interpolation
359 * between @p from and @p to will occurr for in-between values.
360 */
361 static uint32_t lerpByte(uint32_t from, uint32_t to, uint32_t t)
362 {
363 assert((from & 0xFF) == from);
364 assert((to & 0xFF) == to);
365 assert((t & 0xFF) == t);
366 assert(from <= to);
367
368 return (from + (((to - from) * t) >> 8)) & 0xFF;
369 }
370
371 /**
372 * Interpolates between two values using the @p t parameter. All parameters must be in [0, 65536] range. When @p t
373 * is zero, @p from value will be returned, and when it is 65536 @p to value will be returned, and interpolation
374 * between @p from and @p to will occurr for in-between values.
375 */
376 static uint32_t lerpWord(uint32_t from, uint32_t to, uint32_t t)
377 {
378 assert((from & 0xFFFF) == from);
379 assert((to & 0xFFFF) == to);
380 assert((t & 0xFFFF) == t);
381 assert(from <= to);
382
383 return (from + (((to - from) * t) >> 16)) & 0xFFFF;
384 }
385
386 /**
387 * Determines the position of the @p val parameter in the [from, to] range, returned in [0, 255] range where 0 is
388 * returned if @p val is less or equal than @p from, and 255 is returned if @p val is equal to greater to @p to,
389 * and in-between values returned accordingly. All values must be in [0, 255] range.
390 */
391 static uint32_t invLerpByte(uint32_t from, uint32_t to, uint32_t val)
392 {
393 assert((from & 0xFF) == from);
394 assert((to & 0xFF) == to);
395 assert((val & 0xFF) == val);
396 assert(from <= to);
397
398 return ((val - from) << 8) / std::max(to - from, 1u);
399 }
400
401 /**
402 * Determines the position of the @p val parameter in the [from, to] range, returned in [0, 65536] range where 0 is
403 * returned if @p val is less or equal than @p from, and 65536 is returned if @p val is equal to greater to @p to,
404 * and in-between values returned accordingly. All values must be in [0, 65536] range.
405 */
406 static uint32_t invLerpWord(uint32_t from, uint32_t to, uint32_t val)
407 {
408 assert((from & 0xFFFF) == from);
409 assert((to & 0xFFFF) == to);
410 assert((val & 0xFFFF) == val);
411 assert(from <= to);
412
413 return ((val - from) << 16) / std::max(to - from, 1u);
414 }
415
416 /** Write a n*8 bits integer value to memory in native endian. */
417 static void intWrite(void *dest, const int32_t n, const uint32_t value)
418 {
419 switch(n) {
420 case 1:
421 ((UINT8*)dest)[0] = (UINT8)value;
422 break;
423 case 2:
424 ((UINT16*)dest)[0] = (UINT16)value;
425 break;
426 case 3:
427#if BS_ENDIAN == BS_ENDIAN_BIG
428 ((UINT8*)dest)[0] = (UINT8)((value >> 16) & 0xFF);
429 ((UINT8*)dest)[1] = (UINT8)((value >> 8) & 0xFF);
430 ((UINT8*)dest)[2] = (UINT8)(value & 0xFF);
431#else
432 ((UINT8*)dest)[2] = (UINT8)((value >> 16) & 0xFF);
433 ((UINT8*)dest)[1] = (UINT8)((value >> 8) & 0xFF);
434 ((UINT8*)dest)[0] = (UINT8)(value & 0xFF);
435#endif
436 break;
437 case 4:
438 ((UINT32*)dest)[0] = (UINT32)value;
439 break;
440 }
441 }
442
443 /** Read a n*8 bits integer value to memory in native endian. */
444 static uint32_t intRead(const void *src, int32_t n) {
445 switch(n) {
446 case 1:
447 return ((UINT8*)src)[0];
448 case 2:
449 return ((UINT16*)src)[0];
450 case 3:
451#if BS_ENDIAN == BS_ENDIAN_BIG
452 return ((UINT32)((UINT8*)src)[0]<<16)|
453 ((UINT32)((UINT8*)src)[1]<<8)|
454 ((UINT32)((UINT8*)src)[2]);
455#else
456 return ((UINT32)((UINT8*)src)[0])|
457 ((UINT32)((UINT8*)src)[1]<<8)|
458 ((UINT32)((UINT8*)src)[2]<<16);
459#endif
460 case 4:
461 return ((UINT32*)src)[0];
462 }
463 return 0; // ?
464 }
465
466 /** Convert a float32 to a float16 (NV_half_float). */
467 static UINT16 floatToHalf(float i)
468 {
469 union { float f; UINT32 i; } v;
470 v.f = i;
471 return floatToHalfI(v.i);
472 }
473
474 /** Converts float in UINT32 format to a a half in UINT16 format. */
475 static UINT16 floatToHalfI(UINT32 i)
476 {
477 int32_t s = (i >> 16) & 0x00008000;
478 int32_t e = ((i >> 23) & 0x000000ff) - (127 - 15);
479 int32_t m = i & 0x007fffff;
480
481 if (e <= 0)
482 {
483 if (e < -10)
484 {
485 return 0;
486 }
487 m = (m | 0x00800000) >> (1 - e);
488
489 return static_cast<UINT16>(s | (m >> 13));
490 }
491 else if (e == 0xff - (127 - 15))
492 {
493 if (m == 0) // Inf
494 {
495 return static_cast<UINT16>(s | 0x7c00);
496 }
497 else // NAN
498 {
499 m >>= 13;
500 return static_cast<UINT16>(s | 0x7c00 | m | (m == 0));
501 }
502 }
503 else
504 {
505 if (e > 30) // Overflow
506 {
507 return static_cast<UINT16>(s | 0x7c00);
508 }
509
510 return static_cast<UINT16>(s | (e << 10) | (m >> 13));
511 }
512 }
513
514 /** Convert a float16 (NV_half_float) to a float32. */
515 static float halfToFloat(UINT16 y)
516 {
517 union { float f; UINT32 i; } v;
518 v.i = halfToFloatI(y);
519 return v.f;
520 }
521
522 /** Converts a half in UINT16 format to a float in UINT32 format. */
523 static UINT32 halfToFloatI(UINT16 y)
524 {
525 int32_t s = (y >> 15) & 0x00000001;
526 int32_t e = (y >> 10) & 0x0000001f;
527 int32_t m = y & 0x000003ff;
528
529 if (e == 0)
530 {
531 if (m == 0) // Plus or minus zero
532 {
533 return s << 31;
534 }
535 else // Denormalized number -- renormalize it
536 {
537 while (!(m & 0x00000400))
538 {
539 m <<= 1;
540 e -= 1;
541 }
542
543 e += 1;
544 m &= ~0x00000400;
545 }
546 }
547 else if (e == 31)
548 {
549 if (m == 0) // Inf
550 {
551 return (s << 31) | 0x7f800000;
552 }
553 else // NaN
554 {
555 return (s << 31) | 0x7f800000 | (m << 13);
556 }
557 }
558
559 e = e + (127 - 15);
560 m = m << 13;
561
562 return (s << 31) | (e << 23) | m;
563 }
564
565 /** Converts a 32-bit float to a 10-bit float according to OpenGL packed_float extension. */
566 static UINT32 floatToFloat10(float v)
567 {
568 Float754 f;
569 f.value = v;
570
571 if (f.field.exponent == 0xFF)
572 {
573 // NAN or INF
574 if (f.field.mantissa > 0)
575 return 0x3E0 | (((f.raw >> 18) | (f.raw >> 13) | (f.raw >> 3) | f.raw) & 0x1F);
576 else if (f.field.negative)
577 return 0; // Negative infinity clamped to 0
578 else
579 return 0x3E0; // Positive infinity
580
581 }
582 else if (f.field.negative)
583 return 0; // Negative clamped to 0, no negatives allowed
584 else if (f.raw > 0x477C0000)
585 return 0x3DF; // Too large, clamp to max value
586 else
587 {
588 UINT32 val;
589 if (f.raw < 0x38800000U)
590 {
591 // Too small to be represented as a normalized float, convert to denormalized value
592 UINT32 shift = 113 - f.field.exponent;
593 val = (0x800000U | f.field.mantissa) >> shift;
594 }
595 else
596 {
597 // Rebias exponent
598 val = f.raw + 0xC8000000;
599 }
600
601 return ((val + 0x1FFFFU + ((val >> 18) & 1)) >> 18) & 0x3FF;
602 }
603 }
604
605 /** Converts a 32-bit float to a 11-bit float according to OpenGL packed_float extension. */
606 static UINT32 floatToFloat11(float v)
607 {
608 Float754 f;
609 f.value = v;
610
611 if (f.field.exponent == 0xFF)
612 {
613 // NAN or INF
614 if (f.field.mantissa > 0)
615 return 0x7C0 | (((f.raw >> 17) | (f.raw >> 11) | (f.raw >> 6) | f.raw) & 0x3F);
616 else if (f.field.negative)
617 return 0; // Negative infinity clamped to 0
618 else
619 return 0x7C0; // Positive infinity
620
621 }
622 else if (f.field.negative)
623 return 0; // Negative clamped to 0, no negatives allowed
624 else if (f.raw > 0x477E0000)
625 return 0x7BF; // Too large, clamp to max value
626 else
627 {
628 UINT32 val;
629 if(f.raw < 0x38800000U)
630 {
631 // Too small to be represented as a normalized float, convert to denormalized value
632 UINT32 shift = 113 - f.field.exponent;
633 val = (0x800000U | f.field.mantissa) >> shift;
634 }
635 else
636 {
637 // Rebias exponent
638 val = f.raw + 0xC8000000;
639 }
640
641 return ((val + 0xFFFFU + ((val >> 17) & 1)) >> 17) & 0x7FF;
642 }
643 }
644
645 /** Converts a 10-bit float to a 32-bit float according to OpenGL packed_float extension. */
646 static float float10ToFloat(UINT32 v)
647 {
648 Float10 f;
649 f.raw = v;
650
651 UINT32 output;
652 if (f.field.exponent == 0x1F) // INF or NAN
653 {
654 output = 0x7f800000 | (f.field.mantissa << 17);
655 }
656 else
657 {
658 UINT32 exponent;
659 UINT32 mantissa = f.field.mantissa;
660
661 if (f.field.exponent != 0) // The value is normalized
662 exponent = f.field.exponent;
663 else if (mantissa != 0) // The value is denormalized
664 {
665 // Normalize the value in the resulting float
666 exponent = 1;
667
668 do
669 {
670 exponent--;
671 mantissa <<= 1;
672 } while ((mantissa & 0x20) == 0);
673
674 mantissa &= 0x1F;
675 }
676 else // The value is zero
677 exponent = (UINT32)-112;
678
679 output = ((exponent + 112) << 23) | (mantissa << 18);
680 }
681
682 return *(float*)&output;
683 }
684
685 /** Converts a 11-bit float to a 32-bit float according to OpenGL packed_float extension. */
686 static float float11ToFloat(UINT32 v)
687 {
688 Float11 f;
689 f.raw = v;
690
691 UINT32 output;
692 if (f.field.exponent == 0x1F) // INF or NAN
693 {
694 output = 0x7f800000 | (f.field.mantissa << 17);
695 }
696 else
697 {
698 UINT32 exponent;
699 UINT32 mantissa = f.field.mantissa;
700
701 if (f.field.exponent != 0) // The value is normalized
702 exponent = f.field.exponent;
703 else if (mantissa != 0) // The value is denormalized
704 {
705 // Normalize the value in the resulting float
706 exponent = 1;
707
708 do
709 {
710 exponent--;
711 mantissa <<= 1;
712 } while ((mantissa & 0x40) == 0);
713
714 mantissa &= 0x3F;
715 }
716 else // The value is zero
717 exponent = (UINT32)-112;
718
719 output = ((exponent + 112) << 23) | (mantissa << 17);
720 }
721
722 return *(float*)&output;
723 }
724
725 /**
726 * Encodes a 32-bit integer value as a base-128 varint. Varints are a method of serializing integers using one or
727 * more bytes, where smaller values use less bytes.
728 *
729 * @param[in] value Value to encode.
730 * @param[out] output Buffer to store the encoded bytes in. Must be at least 5 bytes in length.
731 * @return Number of bytes required to store the value, in range [1, 5]
732 */
733 static UINT32 encodeVarInt(UINT32 value, UINT8* output)
734 {
735 UINT32 idx = 0;
736 if (value & 0xFFFFFF80U)
737 {
738 output[idx++] = (UINT8)(value | 0x80);
739 value >>= 7;
740
741 if (value & 0xFFFFFF80U)
742 {
743 output[idx++] = (UINT8)(value | 0x80);
744 value >>= 7;
745
746 if (value & 0xFFFFFF80U)
747 {
748 output[idx++] = (UINT8)(value | 0x80);
749 value >>= 7;
750
751 if (value & 0xFFFFFF80U)
752 {
753 output[idx++] = (UINT8)(value | 0x80);
754 value >>= 7;
755 }
756 }
757 }
758 }
759
760 output[idx++] = (UINT8)value;
761 return idx;
762 }
763
764 /**
765 * Decodes a value encoded using encodeVarInt(UINT32, UINT8*).
766 *
767 * @param[out] value Variable to receive the decoded value.
768 * @param[in] input Input buffer to decode the data from.
769 * @param[in] size Size of the input buffer.
770 * @return Number of bytes read.
771 */
772 static UINT32 decodeVarInt(UINT32& value, const UINT8* input, UINT32 size)
773 {
774 if(size == 0)
775 return 0;
776
777 UINT32 idx = 0;
778 value = (UINT32)(input[idx] & 0x7F);
779 if (input[idx++] & 0x80 && --size)
780 {
781 value |= (UINT32)(input[idx] & 0x7F) << 7;
782
783 if (input[idx++] & 0x80 && --size)
784 {
785 value |= (UINT32)(input[idx] & 0x7F) << 14;
786
787 if (input[idx++] & 0x80 && --size)
788 {
789 value |= (UINT32)(input[idx] & 0x7F) << 21;
790
791 if (input[idx++] & 0x80 && --size)
792 value |= (UINT32)(input[idx++]) << 28;
793 }
794 }
795 }
796
797 return !size || input[idx - 1] & 0x80 ? 0 : idx;
798 }
799
800 /** @copydoc encodeVarInt(UINT32, UINT8*) */
801 static UINT32 encodeVarInt(INT32 value, UINT8* output)
802 {
803 // Encode using zig-zag pattern so that negative values don't take up max byte count
804 UINT32 temp = (value << 1) ^ (value >> 31);
805 return encodeVarInt(temp, output);
806 }
807
808 /** @copydoc decodeVarInt(UINT32, UINT8*) */
809 static UINT32 decodeVarInt(INT32& value, const UINT8* input, UINT32 size)
810 {
811 UINT32 temp;
812
813 UINT32 readBytes = decodeVarInt(temp, input, size);
814 value = (INT32)((temp >> 1) ^ -((INT32)temp & 1));
815
816 return readBytes;
817 }
818
819 /**
820 * Encodes a 64-bit integer value as a base-128 varint. Varints are a method of serializing integers using one or
821 * more bytes, where smaller values use less bytes.
822 *
823 * @param[in] value Value to encode.
824 * @param[out] output Buffer to store the encoded bytes in. Must be at least 10 bytes in length.
825 * @return Number of bytes required to store the value, in range [1, 10]
826 */
827 static UINT32 encodeVarInt(UINT64 value, UINT8* output)
828 {
829 UINT32 idx = 0;
830 if (value & 0xFFFFFFFFFFFFFF80ULL)
831 {
832 output[idx++] = (UINT8)(value | 0x80);
833 value >>= 7;
834
835 if (value & 0xFFFFFFFFFFFFFF80ULL)
836 {
837 output[idx++] = (UINT8)(value | 0x80);
838 value >>= 7;
839
840 if (value & 0xFFFFFFFFFFFFFF80ULL)
841 {
842 output[idx++] = (UINT8)(value | 0x80);
843 value >>= 7;
844
845 if (value & 0xFFFFFFFFFFFFFF80ULL)
846 {
847 output[idx++] = (UINT8)(value | 0x80);
848 value >>= 7;
849
850 if (value & 0xFFFFFFFFFFFFFF80ULL)
851 {
852 output[idx++] = (UINT8)(value | 0x80);
853 value >>= 7;
854
855 if (value & 0xFFFFFFFFFFFFFF80ULL)
856 {
857 output[idx++] = (UINT8)(value | 0x80);
858 value >>= 7;
859
860 if (value & 0xFFFFFFFFFFFFFF80ULL)
861 {
862 output[idx++] = (UINT8)(value | 0x80);
863 value >>= 7;
864
865 if (value & 0xFFFFFFFFFFFFFF80ULL)
866 {
867 output[idx++] = (UINT8)(value | 0x80);
868 value >>= 7;
869
870 if (value & 0xFFFFFFFFFFFFFF80ULL)
871 {
872 output[idx++] = (UINT8)(value | 0x80);
873 value >>= 7;
874 }
875 }
876 }
877 }
878 }
879 }
880 }
881 }
882 }
883
884 output[idx++] = (UINT8)value;
885 return idx;
886 }
887
888 /**
889 * Decodes a value encoded using encodeVarInt(UINT64, UINT8*).
890 *
891 * @param[out] value Variable to receive the decoded value.
892 * @param[in] input Input buffer to decode the data from.
893 * @param[in] size Size of the input buffer.
894 * @return Number of bytes read.
895 */
896 static UINT32 decodeVarInt(UINT64& value, const UINT8* input, UINT32 size)
897 {
898 if(size == 0)
899 return 0;
900
901 UINT32 idx = 0;
902 value = (UINT64)(input[idx] & 0x7F);
903 if (input[idx++] & 0x80 && --size)
904 {
905 value |= (UINT64)(input[idx] & 0x7F) << 7;
906
907 if (input[idx++] & 0x80 && --size)
908 {
909 value |= (UINT64)(input[idx] & 0x7F) << 14;
910
911 if (input[idx++] & 0x80 && --size)
912 {
913 value |= (UINT64)(input[idx] & 0x7F) << 21;
914
915 if (input[idx++] & 0x80 && --size)
916 {
917 value |= (UINT64)(input[idx] & 0x7F) << 28;
918
919 if (input[idx++] & 0x80 && --size)
920 {
921 value |= (UINT64)(input[idx] & 0x7F) << 35;
922
923 if (input[idx++] & 0x80 && --size)
924 {
925 value |= (UINT64)(input[idx] & 0x7F) << 42;
926
927 if (input[idx++] & 0x80 && --size)
928 {
929 value |= (UINT64)(input[idx] & 0x7F) << 49;
930
931 if (input[idx++] & 0x80 && --size)
932 {
933 value |= (UINT64)(input[idx] & 0x7F) << 56;
934
935 if (input[idx++] & 0x80 && --size)
936 value |= (UINT64)(input[idx++]) << 63;
937 }
938 }
939 }
940 }
941 }
942 }
943 }
944 }
945
946 return !size || input[idx - 1] & 0x80 ? 0 : idx;
947 }
948
949 /** @copydoc encodeVarInt(UINT64, UINT8*) */
950 static UINT32 encodeVarInt(INT64 value, UINT8* output)
951 {
952 // Encode using zig-zag pattern so that negative values don't take up max byte count
953 UINT64 temp = (value << 1) ^ (value >> 63);
954 return encodeVarInt(temp, output);
955 }
956
957 /** @copydoc decodeVarInt(UINT64, UINT8*) */
958 static UINT32 decodeVarInt(INT64& value, const UINT8* input, UINT32 size)
959 {
960 UINT64 temp;
961
962 UINT32 readBytes = decodeVarInt(temp, input, size);
963 value = (INT64)((temp >> 1) ^ -((INT64)temp & 1));
964
965 return readBytes;
966 }
967
968 /** Converts a float in range [-1,1] into an unsigned 8-bit integer. */
969 static UINT8 quantize8BitSigned(float v)
970 {
971 return quantize8BitUnsigned(v * 0.5f + 0.5f);
972 }
973
974 /** Converts a float in range [0,1] into an unsigned 8-bit integer. */
975 static UINT8 quantize8BitUnsigned(float v)
976 {
977 return (UINT8)(v * 255.999f);
978 }
979 };
980
981 /** @} */
982}
983