diff options
-rw-r--r-- | src/include/port/pg_bitutils.h | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/src/include/port/pg_bitutils.h b/src/include/port/pg_bitutils.h index 498e5323081..4ca92f076dc 100644 --- a/src/include/port/pg_bitutils.h +++ b/src/include/port/pg_bitutils.h @@ -129,6 +129,78 @@ pg_rightmost_one_pos64(uint64 word) #endif /* HAVE__BUILTIN_CTZ */ } +/* + * pg_nextpower2_32 + * Returns the next highest power of 2 of 'num', or 'num', if it's + * already a power of 2. + * + * 'num' mustn't be 0 or be above PG_UINT32_MAX / 2 + 1. + */ +static inline uint32 +pg_nextpower2_32(uint32 num) +{ + Assert(num > 0 && num <= PG_UINT32_MAX / 2 + 1); + + /* + * A power 2 number has only 1 bit set. Subtracting 1 from such a number + * will turn on all previous bits resulting in no common bits being set + * between num and num-1. + */ + if ((num & (num - 1)) == 0) + return num; /* already power 2 */ + + return ((uint32) 1) << (pg_leftmost_one_pos32(num) + 1); +} + +/* + * pg_nextpower2_64 + * Returns the next highest power of 2 of 'num', or 'num', if it's + * already a power of 2. + * + * 'num' mustn't be 0 or be above PG_UINT64_MAX / 2 + 1. + */ +static inline uint64 +pg_nextpower2_64(uint64 num) +{ + Assert(num > 0 && num <= PG_UINT64_MAX / 2 + 1); + + /* + * A power 2 number has only 1 bit set. Subtracting 1 from such a number + * will turn on all previous bits resulting in no common bits being set + * between num and num-1. + */ + if ((num & (num - 1)) == 0) + return num; /* already power 2 */ + + return ((uint64) 1) << (pg_leftmost_one_pos64(num) + 1); +} + +/* + * pg_ceil_log2_32 + * Returns equivalent of ceil(log2(num)) + */ +static inline uint32 +pg_ceil_log2_32(uint32 num) +{ + if (num < 2) + return 0; + else + return pg_leftmost_one_pos32(num - 1) + 1; +} + +/* + * pg_ceil_log2_64 + * Returns equivalent of ceil(log2(num)) + */ +static inline uint64 +pg_ceil_log2_64(uint64 num) +{ + if (num < 2) + return 0; + else + return pg_leftmost_one_pos64(num - 1) + 1; +} + /* Count the number of one-bits in a uint32 or uint64 */ extern int (*pg_popcount32) (uint32 word); extern int (*pg_popcount64) (uint64 word); |