|
22 | 22 | * @file clz.h |
23 | 23 | * @brief Count leading zeros (clz) routine |
24 | 24 | * |
25 | | - * @author cristian.martinez@univ-paris-est.fr (martinec) |
| 25 | + * @author cristian.martinez@unitexgramlab.org (martinec) |
26 | 26 | * |
27 | 27 | * @attention Do not include this file directly, rather include the base/common.h |
28 | | - * header file to gain this file's functionality |
| 28 | + * header file to gain this file's functionality |
29 | 29 | * |
30 | 30 | * @note Use cpplint.py tool to detect style errors: |
31 | 31 | * `cpplint.py --linelength=120 clz.h` |
|
45 | 45 | #include "base/integer/types.h" // uint32_t, uint64_t |
46 | 46 | #include "base/integer/wordsize.h" // UNITEX_WORDSIZE_IS() |
47 | 47 | /* ************************************************************************** */ |
| 48 | +/** |
| 49 | + * @def unitex_builtin_clz_16 |
| 50 | + * @brief Count the number of leading 0-bits on a 16-bits data type |
| 51 | + */ |
| 52 | +#if UNITEX_COMPILER_AT_LEAST(MSVC,14,0) |
| 53 | +#pragma intrinsic(_BitScanReverse) |
| 54 | +#endif // UNITEX_COMPILER_AT_LEAST(MSVC,14,0) |
| 55 | +UNITEX_FORCE_INLINE |
| 56 | +uint16_t unitex_builtin_clz_16(uint16_t n) { |
| 57 | +// GNU C/C++ compiler |
| 58 | +// LLVM native C/C++ compiler |
| 59 | +#if UNITEX_COMPILER_AT_LEAST(GCC,3,4) ||\ |
| 60 | + UNITEX_COMPILER_AT_LEAST(CLANG,1,5) |
| 61 | +# define UNITEX_HAS_BUILTIN_CLZ 1 |
| 62 | + return UNITEX_LIKELY(n) ? __builtin_clz(n) - 16 : 16; |
| 63 | +// Visual Studio 2005 and later |
| 64 | +#elif UNITEX_COMPILER_AT_LEAST(MSVC,14,0) |
| 65 | +# define UNITEX_HAS_BUILTIN_CLZ 1 |
| 66 | + uint16_t count = 16; |
| 67 | + if (UNITEX_LIKELY(n)) { |
| 68 | + _BitScanReverse((uint16_t*)&count, n); |
| 69 | + count ^= 15; |
| 70 | + } |
| 71 | + return count; |
| 72 | +// Intel Compiler |
| 73 | +#elif UNITEX_COMPILER_IS(INTEL) |
| 74 | +# define UNITEX_HAS_BUILTIN_CLZ 1 |
| 75 | + return UNITEX_LIKELY(n) ? _bit_scan_reverse(static_cast<uint16_t>(n)) ^ 15 : 16; |
| 76 | +#else |
| 77 | +# define UNITEX_HAS_BUILTIN_CLZ 0 |
| 78 | +// Bit Twiddling Hacks |
| 79 | +// @see https://graphics.stanford.edu/~seander/bithacks.html |
| 80 | + static const int8_t LogTable256[256] = { |
| 81 | +# define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n |
| 82 | + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, |
| 83 | + LT(5), LT(6), LT(6), LT(7), LT(7), LT(7), LT(7), |
| 84 | + LT(8), LT(8), LT(8), LT(8), LT(8), LT(8), LT(8), LT(8) |
| 85 | +# undef LT |
| 86 | + }; |
| 87 | + int8_t count = 0; |
| 88 | + uint16_t t = 0; |
| 89 | + if ((t = n >> UINT32_C(8))) count = 8 - LogTable256[t]; |
| 90 | + else count = 16 - LogTable256[n]; |
| 91 | + return static_cast<uint16_t>(count); |
| 92 | +#endif |
| 93 | +} |
| 94 | + |
48 | 95 | /** |
49 | 96 | * @def unitex_builtin_clz_32 |
50 | 97 | * @brief Count the number of leading 0-bits on a 32-bits data type |
|
0 commit comments