123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- #include <stdint.h>
- #include <limits.h>
- #ifdef _MSC_VER
- #include <intrin.h> /* _BitScanForward, _BitScanReverse */
- #endif
- /* First define ctz and clz functions; these are compiler-dependent if
- * you want them to be fast. */
- #if defined(__GNUC__) && !defined(TIMEOUT_DISABLE_GNUC_BITOPS)
- #ifndef LONG_BIT
- #define LONG_BIT (SIZEOF_LONG*CHAR_BIT)
- #endif
- /* On GCC and clang and some others, we can use __builtin functions. They
- * are not defined for n==0, but timeout.s never calls them with n==0. */
- #define ctz64(n) __builtin_ctzll(n)
- #define clz64(n) __builtin_clzll(n)
- #if LONG_BIT == 32
- #define ctz32(n) __builtin_ctzl(n)
- #define clz32(n) __builtin_clzl(n)
- #else
- #define ctz32(n) __builtin_ctz(n)
- #define clz32(n) __builtin_clz(n)
- #endif
- #elif defined(_MSC_VER) && !defined(TIMEOUT_DISABLE_MSVC_BITOPS)
- /* On MSVC, we have these handy functions. We can ignore their return
- * values, since we will never supply val == 0. */
- static __inline int ctz32(unsigned long val)
- {
- DWORD zeros = 0;
- _BitScanForward(&zeros, val);
- return zeros;
- }
- static __inline int clz32(unsigned long val)
- {
- DWORD zeros = 0;
- _BitScanReverse(&zeros, val);
- return 31 - zeros;
- }
- #ifdef _WIN64
- /* According to the documentation, these only exist on Win64. */
- static __inline int ctz64(uint64_t val)
- {
- DWORD zeros = 0;
- _BitScanForward64(&zeros, val);
- return zeros;
- }
- static __inline int clz64(uint64_t val)
- {
- DWORD zeros = 0;
- _BitScanReverse64(&zeros, val);
- return 63 - zeros;
- }
- #else
- static __inline int ctz64(uint64_t val)
- {
- uint32_t lo = (uint32_t) val;
- uint32_t hi = (uint32_t) (val >> 32);
- return lo ? ctz32(lo) : 32 + ctz32(hi);
- }
- static __inline int clz64(uint64_t val)
- {
- uint32_t lo = (uint32_t) val;
- uint32_t hi = (uint32_t) (val >> 32);
- return hi ? clz32(hi) : 32 + clz32(lo);
- }
- #endif
- /* End of MSVC case. */
- #else
- /* TODO: There are more clever ways to do this in the generic case. */
- #define process_(one, cz_bits, bits) \
- if (x < ( one << (cz_bits - bits))) { rv += bits; x <<= bits; }
- #define process64(bits) process_((UINT64_C(1)), 64, (bits))
- static inline int clz64(uint64_t x)
- {
- int rv = 0;
- process64(32);
- process64(16);
- process64(8);
- process64(4);
- process64(2);
- process64(1);
- return rv;
- }
- #define process32(bits) process_((UINT32_C(1)), 32, (bits))
- static inline int clz32(uint32_t x)
- {
- int rv = 0;
- process32(16);
- process32(8);
- process32(4);
- process32(2);
- process32(1);
- return rv;
- }
- #undef process_
- #undef process32
- #undef process64
- #define process_(one, bits) \
- if ((x & ((one << (bits))-1)) == 0) { rv += bits; x >>= bits; }
- #define process64(bits) process_((UINT64_C(1)), bits)
- static inline int ctz64(uint64_t x)
- {
- int rv = 0;
- process64(32);
- process64(16);
- process64(8);
- process64(4);
- process64(2);
- process64(1);
- return rv;
- }
- #define process32(bits) process_((UINT32_C(1)), bits)
- static inline int ctz32(uint32_t x)
- {
- int rv = 0;
- process32(16);
- process32(8);
- process32(4);
- process32(2);
- process32(1);
- return rv;
- }
- #undef process32
- #undef process64
- #undef process_
- /* End of generic case */
- #endif /* End of defining ctz */
- #ifdef TEST_BITOPS
- #include <stdio.h>
- #include <stdlib.h>
- static uint64_t testcases[] = {
- 13371337 * 10,
- 100,
- 385789752,
- 82574,
- (((uint64_t)1)<<63) + (((uint64_t)1)<<31) + 10101
- };
- static int
- naive_clz(int bits, uint64_t v)
- {
- int r = 0;
- uint64_t bit = ((uint64_t)1) << (bits-1);
- while (bit && 0 == (v & bit)) {
- r++;
- bit >>= 1;
- }
- /* printf("clz(%d,%lx) -> %d\n", bits, v, r); */
- return r;
- }
- static int
- naive_ctz(int bits, uint64_t v)
- {
- int r = 0;
- uint64_t bit = 1;
- while (bit && 0 == (v & bit)) {
- r++;
- bit <<= 1;
- if (r == bits)
- break;
- }
- /* printf("ctz(%d,%lx) -> %d\n", bits, v, r); */
- return r;
- }
- static int
- check(uint64_t vv)
- {
- uint32_t v32 = (uint32_t) vv;
- if (vv == 0)
- return 1; /* c[tl]z64(0) is undefined. */
- if (ctz64(vv) != naive_ctz(64, vv)) {
- printf("mismatch with ctz64: %d\n", ctz64(vv));
- exit(1);
- return 0;
- }
- if (clz64(vv) != naive_clz(64, vv)) {
- printf("mismatch with clz64: %d\n", clz64(vv));
- exit(1);
- return 0;
- }
- if (v32 == 0)
- return 1; /* c[lt]z(0) is undefined. */
- if (ctz32(v32) != naive_ctz(32, v32)) {
- printf("mismatch with ctz32: %d\n", ctz32(v32));
- exit(1);
- return 0;
- }
- if (clz32(v32) != naive_clz(32, v32)) {
- printf("mismatch with clz32: %d\n", clz32(v32));
- exit(1);
- return 0;
- }
- return 1;
- }
- int
- main(int c, char **v)
- {
- unsigned int i;
- const unsigned int n = sizeof(testcases)/sizeof(testcases[0]);
- int result = 0;
- for (i = 0; i <= 63; ++i) {
- uint64_t x = 1;
- x <<= i;
- if (!check(x))
- result = 1;
- --x;
- if (!check(x))
- result = 1;
- }
- for (i = 0; i < n; ++i) {
- if (! check(testcases[i]))
- result = 1;
- }
- if (result) {
- puts("FAIL");
- } else {
- puts("OK");
- }
- return result;
- }
- #endif
|