4 #include <intrin.h> /* _BitScanForward, _BitScanReverse */
7 /* First define ctz and clz functions; these are compiler-dependent if
8 * you want them to be fast. */
9 #if defined(__GNUC__) && !defined(TIMEOUT_DISABLE_GNUC_BITOPS)
12 #define LONG_BIT (SIZEOF_LONG*CHAR_BIT)
15 /* On GCC and clang and some others, we can use __builtin functions. They
16 * are not defined for n==0, but timeout.s never calls them with n==0. */
18 #define ctz64(n) __builtin_ctzll(n)
19 #define clz64(n) __builtin_clzll(n)
21 #define ctz32(n) __builtin_ctzl(n)
22 #define clz32(n) __builtin_clzl(n)
24 #define ctz32(n) __builtin_ctz(n)
25 #define clz32(n) __builtin_clz(n)
28 #elif defined(_MSC_VER) && !defined(TIMEOUT_DISABLE_MSVC_BITOPS)
30 /* On MSVC, we have these handy functions. We can ignore their return
31 * values, since we will never supply val == 0. */
33 static __inline
int ctz32(unsigned long val
)
36 _BitScanForward(&zeros
, val
);
39 static __inline
int clz32(unsigned long val
)
42 _BitScanReverse(&zeros
, val
);
46 /* According to the documentation, these only exist on Win64. */
47 static __inline
int ctz64(uint64_t val
)
50 _BitScanForward64(&zeros
, val
);
53 static __inline
int clz64(uint64_t val
)
56 _BitScanReverse64(&zeros
, val
);
60 static __inline
int ctz64(uint64_t val
)
62 uint32_t lo
= (uint32_t) val
;
63 uint32_t hi
= (uint32_t) (val
>> 32);
64 return lo
? ctz32(lo
) : 32 + ctz32(hi
);
66 static __inline
int clz64(uint64_t val
)
68 uint32_t lo
= (uint32_t) val
;
69 uint32_t hi
= (uint32_t) (val
>> 32);
70 return hi
? clz32(hi
) : 32 + clz32(lo
);
74 /* End of MSVC case. */
78 /* TODO: There are more clever ways to do this in the generic case. */
81 #define process_(one, cz_bits, bits) \
82 if (x < ( one << (cz_bits - bits))) { rv += bits; x <<= bits; }
84 #define process64(bits) process_((UINT64_C(1)), 64, (bits))
85 static inline int clz64(uint64_t x
)
97 #define process32(bits) process_((UINT32_C(1)), 32, (bits))
98 static inline int clz32(uint32_t x
)
113 #define process_(one, bits) \
114 if ((x & ((one << (bits))-1)) == 0) { rv += bits; x >>= bits; }
116 #define process64(bits) process_((UINT64_C(1)), bits)
117 static inline int ctz64(uint64_t x
)
130 #define process32(bits) process_((UINT32_C(1)), bits)
131 static inline int ctz32(uint32_t x
)
147 /* End of generic case */
149 #endif /* End of defining ctz */
155 static uint64_t testcases
[] = {
160 (((uint64_t)1)<<63) + (((uint64_t)1)<<31) + 10101
164 naive_clz(int bits
, uint64_t v
)
167 uint64_t bit
= ((uint64_t)1) << (bits
-1);
168 while (bit
&& 0 == (v
& bit
)) {
172 /* printf("clz(%d,%lx) -> %d\n", bits, v, r); */
177 naive_ctz(int bits
, uint64_t v
)
181 while (bit
&& 0 == (v
& bit
)) {
187 /* printf("ctz(%d,%lx) -> %d\n", bits, v, r); */
194 uint32_t v32
= (uint32_t) vv
;
197 return 1; /* c[tl]z64(0) is undefined. */
199 if (ctz64(vv
) != naive_ctz(64, vv
)) {
200 printf("mismatch with ctz64: %d\n", ctz64(vv
));
204 if (clz64(vv
) != naive_clz(64, vv
)) {
205 printf("mismatch with clz64: %d\n", clz64(vv
));
211 return 1; /* c[lt]z(0) is undefined. */
213 if (ctz32(v32
) != naive_ctz(32, v32
)) {
214 printf("mismatch with ctz32: %d\n", ctz32(v32
));
218 if (clz32(v32
) != naive_clz(32, v32
)) {
219 printf("mismatch with clz32: %d\n", clz32(v32
));
227 main(int c
, char **v
)
230 const unsigned int n
= sizeof(testcases
)/sizeof(testcases
[0]);
233 for (i
= 0; i
<= 63; ++i
) {
243 for (i
= 0; i
< n
; ++i
) {
244 if (! check(testcases
[i
]))