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 | |
12 | namespace 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 | |