diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
commit | e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch) | |
tree | 68cb5ef9081156392f1dd62a00c6ccc1451b93df /wsutil/bits_ctz.h | |
parent | Initial commit. (diff) | |
download | wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip |
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'wsutil/bits_ctz.h')
-rw-r--r-- | wsutil/bits_ctz.h | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/wsutil/bits_ctz.h b/wsutil/bits_ctz.h new file mode 100644 index 00000000..b4c43e3f --- /dev/null +++ b/wsutil/bits_ctz.h @@ -0,0 +1,92 @@ +/** @file + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef __WSUTIL_BITS_CTZ_H__ +#define __WSUTIL_BITS_CTZ_H__ + +#include <inttypes.h> + +/* ws_ctz == trailing zeros == position of lowest set bit [0..63] */ +/* ws_ilog2 == position of highest set bit == 63 - leading zeros [0..63] */ + +/* The return value of both ws_ctz and ws_ilog2 is undefined for x == 0 */ + +#if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) + +static inline int +ws_ctz(uint64_t x) +{ + return __builtin_ctzll(x); +} + +static inline int +ws_ilog2(uint64_t x) +{ + return 63 - __builtin_clzll(x); +} + +#else + +static inline int +__ws_ctz32(uint32_t x) +{ + /* From http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup */ + static const uint8_t table[32] = { + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + }; + + return table[((uint32_t)((x & -(int32_t)x) * 0x077CB531U)) >> 27]; +} + +static inline int +ws_ctz(uint64_t x) +{ + uint32_t hi = x >> 32; + uint32_t lo = (uint32_t) x; + + if (lo == 0) + return 32 + __ws_ctz32(hi); + else + return __ws_ctz32(lo); +} + +static inline int +__ws_ilog2_32(uint32_t x) +{ + /* From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn */ + static const uint8_t table[32] = { + 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, + 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 + }; + + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + + return table[((uint32_t)(x * 0x07C4ACDDU)) >> 27]; +} + +static inline int +ws_ilog2(uint64_t x) +{ + uint32_t hi = x >> 32; + uint32_t lo = (uint32_t) x; + + if (hi == 0) + return __ws_ilog2_32(lo); + else + return 32 + __ws_ilog2_32(hi); +} + +#endif + +#endif /* __WSUTIL_BITS_CTZ_H__ */ |