|
5 | 5 |
|
6 | 6 | #pragma once
|
7 | 7 |
|
| 8 | +#include <stdint.h> |
| 9 | + |
8 | 10 | #include "feature.h"
|
9 | 11 |
|
10 | 12 | #if defined(__GNUC__) || defined(__clang__)
|
|
27 | 29 |
|
28 | 30 | #define MASK(n) (~((~0U << (n))))
|
29 | 31 |
|
| 32 | +#if defined(_MSC_VER) |
| 33 | +#include <intrin.h> |
| 34 | +static inline int clz(uint32_t v) |
| 35 | +{ |
| 36 | + uint32_t leading_zero = 0; |
| 37 | + if (_BitScanReverse(&leading_zero, v)) |
| 38 | + return 31 - leading_zero; |
| 39 | + return 32; /* undefined behavior */ |
| 40 | +} |
| 41 | +#elif defined(__GNUC__) || defined(__clang__) |
| 42 | +static inline int clz(uint32_t v) |
| 43 | +{ |
| 44 | + return __builtin_clz(v); |
| 45 | +} |
| 46 | +#else /* generic implementation */ |
| 47 | +static inline int clz(uint32_t v) |
| 48 | +{ |
| 49 | + /* http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn */ |
| 50 | + static const uint8_t mul_debruijn[] = { |
| 51 | + 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, |
| 52 | + 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31, |
| 53 | + }; |
| 54 | + |
| 55 | + v |= v >> 1; |
| 56 | + v |= v >> 2; |
| 57 | + v |= v >> 4; |
| 58 | + v |= v >> 8; |
| 59 | + v |= v >> 16; |
| 60 | + |
| 61 | + return mul_debruijn[(uint32_t) (v * 0x07C4ACDDU) >> 27]; |
| 62 | +} |
| 63 | +#endif |
| 64 | + |
30 | 65 | /*
|
31 | 66 | * Integer log base 2
|
32 |
| - * |
33 |
| - * The input will be ORed with 1 to prevent x = 0 since |
34 |
| - * the result is undefined if x = 0 |
35 |
| - * |
36 | 67 | */
|
37 |
| -#if defined(__GNUC__) || defined(__clang__) |
38 |
| -#define ilog2(x) 31 - __builtin_clz(x | 1) |
39 |
| -#elif defined(_MSC_VER) |
40 |
| -/* FIXME */ |
41 |
| -#else /* unsupported compilers */ |
42 |
| -#define ilog2(x) |
43 |
| -#endif |
| 68 | +static inline uint8_t ilog2(uint32_t x) |
| 69 | +{ |
| 70 | + return 31 - clz(x); |
| 71 | +} |
44 | 72 |
|
45 | 73 | /* Alignment macro */
|
46 | 74 | #if defined(__GNUC__) || defined(__clang__)
|
|
0 commit comments