Skip to content

Commit ecc937c

Browse files
committed
[enhance] Add unitex_builtin_clz_16
1 parent d820ad9 commit ecc937c

File tree

1 file changed

+49
-2
lines changed
  • src/base/compiler/intrinsic

1 file changed

+49
-2
lines changed

src/base/compiler/intrinsic/clz.h

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@
2222
* @file clz.h
2323
* @brief Count leading zeros (clz) routine
2424
*
25-
* @author cristian.martinez@univ-paris-est.fr (martinec)
25+
* @author cristian.martinez@unitexgramlab.org (martinec)
2626
*
2727
* @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
2929
*
3030
* @note Use cpplint.py tool to detect style errors:
3131
* `cpplint.py --linelength=120 clz.h`
@@ -45,6 +45,53 @@
4545
#include "base/integer/types.h" // uint32_t, uint64_t
4646
#include "base/integer/wordsize.h" // UNITEX_WORDSIZE_IS()
4747
/* ************************************************************************** */
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+
4895
/**
4996
* @def unitex_builtin_clz_32
5097
* @brief Count the number of leading 0-bits on a 32-bits data type

0 commit comments

Comments
 (0)