diff options
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/bitscan.h | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/src/util/bitscan.h b/src/util/bitscan.h index 4999b74..0743fe7 100644 --- a/src/util/bitscan.h +++ b/src/util/bitscan.h @@ -29,6 +29,7 @@ #ifndef BITSCAN_H #define BITSCAN_H +#include <assert.h> #include <stdint.h> #if defined(_MSC_VER) @@ -146,6 +147,73 @@ u_bit_scan_consecutive_range64(uint64_t *mask, int *start, int *count) } +/** + * Find last bit set in a word. The least significant bit is 1. + * Return 0 if no bits are set. + * Essentially ffs() in the reverse direction. + */ +static inline unsigned +util_last_bit(unsigned u) +{ +#if defined(HAVE___BUILTIN_CLZ) + return u == 0 ? 0 : 32 - __builtin_clz(u); +#else + unsigned r = 0; + while (u) { + r++; + u >>= 1; + } + return r; +#endif +} + +/** + * Find last bit set in a word. The least significant bit is 1. + * Return 0 if no bits are set. + * Essentially ffsll() in the reverse direction. + */ +static inline unsigned +util_last_bit64(uint64_t u) +{ +#if defined(HAVE___BUILTIN_CLZLL) + return u == 0 ? 0 : 64 - __builtin_clzll(u); +#else + unsigned r = 0; + while (u) { + r++; + u >>= 1; + } + return r; +#endif +} + +/** + * Find last bit in a word that does not match the sign bit. The least + * significant bit is 1. + * Return 0 if no bits are set. + */ +static inline unsigned +util_last_bit_signed(int i) +{ + if (i >= 0) + return util_last_bit(i); + else + return util_last_bit(~(unsigned)i); +} + +/* Returns a bitfield in which the first count bits starting at start are + * set. + */ +static inline unsigned +u_bit_consecutive(unsigned start, unsigned count) +{ + assert(start + count <= 32); + if (count == 32) + return ~0; + return ((1u << count) - 1) << start; +} + + #ifdef __cplusplus } #endif |