mirror of
https://github.com/postgres/postgres.git
synced 2025-04-25 21:42:33 +03:00
Add functions to calculate the next power of 2
There are many areas in the code where we need to determine the next highest power of 2 of a given number. We tend to always do that in an ad-hoc way each time, generally with some tight for loop which performs a bitshift left once per loop and goes until it finds a number above the given number. Here we add two generic functions which make use of the existing pg_leftmost_one_pos* functions which, when available, will allow us to calculate the next power of 2 without any looping. Here we don't add any code which uses these new functions. That will be done in follow-up commits. Author: David Fetter, with some minor adjustments by me Reviewed-by: John Naylor, Jesse Zhang Discussion: https://postgr.es/m/20200114173553.GE32763%40fetter.org
This commit is contained in:
parent
7a5d74b7dd
commit
f0705bb628
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user