Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
pg_bitutils.h340 linesDownload Raw Back to port
1/*-------------------------------------------------------------------------2 *3 * pg_bitutils.h4 *	  Miscellaneous functions for bit-wise operations.5 *6 *7 * Copyright (c) 2019-2023, PostgreSQL Global Development Group8 *9 * src/include/port/pg_bitutils.h10 *11 *-------------------------------------------------------------------------12 */13#ifndef PG_BITUTILS_H14#define PG_BITUTILS_H15 16#ifdef _MSC_VER17#include <intrin.h>18#define HAVE_BITSCAN_FORWARD19#define HAVE_BITSCAN_REVERSE20 21#else22#if defined(HAVE__BUILTIN_CTZ)23#define HAVE_BITSCAN_FORWARD24#endif25 26#if defined(HAVE__BUILTIN_CLZ)27#define HAVE_BITSCAN_REVERSE28#endif29#endif							/* _MSC_VER */30 31extern PGDLLIMPORT const uint8 pg_leftmost_one_pos[256];32extern PGDLLIMPORT const uint8 pg_rightmost_one_pos[256];33extern PGDLLIMPORT const uint8 pg_number_of_ones[256];34 35/*36 * pg_leftmost_one_pos3237 *		Returns the position of the most significant set bit in "word",38 *		measured from the least significant bit.  word must not be 0.39 */40static inline int41pg_leftmost_one_pos32(uint32 word)42{43#ifdef HAVE__BUILTIN_CLZ44	Assert(word != 0);45 46	return 31 - __builtin_clz(word);47#elif defined(_MSC_VER)48	unsigned long result;49	bool		non_zero;50 51	non_zero = _BitScanReverse(&result, word);52	Assert(non_zero);53	return (int) result;54#else55	int			shift = 32 - 8;56 57	Assert(word != 0);58 59	while ((word >> shift) == 0)60		shift -= 8;61 62	return shift + pg_leftmost_one_pos[(word >> shift) & 255];63#endif							/* HAVE__BUILTIN_CLZ */64}65 66/*67 * pg_leftmost_one_pos6468 *		As above, but for a 64-bit word.69 */70static inline int71pg_leftmost_one_pos64(uint64 word)72{73#ifdef HAVE__BUILTIN_CLZ74	Assert(word != 0);75 76#if defined(HAVE_LONG_INT_64)77	return 63 - __builtin_clzl(word);78#elif defined(HAVE_LONG_LONG_INT_64)79	return 63 - __builtin_clzll(word);80#else81#error must have a working 64-bit integer datatype82#endif							/* HAVE_LONG_INT_64 */83 84#elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))85	unsigned long result;86	bool		non_zero;87 88	non_zero = _BitScanReverse64(&result, word);89	Assert(non_zero);90	return (int) result;91#else92	int			shift = 64 - 8;93 94	Assert(word != 0);95 96	while ((word >> shift) == 0)97		shift -= 8;98 99	return shift + pg_leftmost_one_pos[(word >> shift) & 255];100#endif							/* HAVE__BUILTIN_CLZ */101}102 103/*104 * pg_rightmost_one_pos32105 *		Returns the position of the least significant set bit in "word",106 *		measured from the least significant bit.  word must not be 0.107 */108static inline int109pg_rightmost_one_pos32(uint32 word)110{111#ifdef HAVE__BUILTIN_CTZ112	Assert(word != 0);113 114	return __builtin_ctz(word);115#elif defined(_MSC_VER)116	unsigned long result;117	bool		non_zero;118 119	non_zero = _BitScanForward(&result, word);120	Assert(non_zero);121	return (int) result;122#else123	int			result = 0;124 125	Assert(word != 0);126 127	while ((word & 255) == 0)128	{129		word >>= 8;130		result += 8;131	}132	result += pg_rightmost_one_pos[word & 255];133	return result;134#endif							/* HAVE__BUILTIN_CTZ */135}136 137/*138 * pg_rightmost_one_pos64139 *		As above, but for a 64-bit word.140 */141static inline int142pg_rightmost_one_pos64(uint64 word)143{144#ifdef HAVE__BUILTIN_CTZ145	Assert(word != 0);146 147#if defined(HAVE_LONG_INT_64)148	return __builtin_ctzl(word);149#elif defined(HAVE_LONG_LONG_INT_64)150	return __builtin_ctzll(word);151#else152#error must have a working 64-bit integer datatype153#endif							/* HAVE_LONG_INT_64 */154 155#elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))156	unsigned long result;157	bool		non_zero;158 159	non_zero = _BitScanForward64(&result, word);160	Assert(non_zero);161	return (int) result;162#else163	int			result = 0;164 165	Assert(word != 0);166 167	while ((word & 255) == 0)168	{169		word >>= 8;170		result += 8;171	}172	result += pg_rightmost_one_pos[word & 255];173	return result;174#endif							/* HAVE__BUILTIN_CTZ */175}176 177/*178 * pg_nextpower2_32179 *		Returns the next higher power of 2 above 'num', or 'num' if it's180 *		already a power of 2.181 *182 * 'num' mustn't be 0 or be above PG_UINT32_MAX / 2 + 1.183 */184static inline uint32185pg_nextpower2_32(uint32 num)186{187	Assert(num > 0 && num <= PG_UINT32_MAX / 2 + 1);188 189	/*190	 * A power 2 number has only 1 bit set.  Subtracting 1 from such a number191	 * will turn on all previous bits resulting in no common bits being set192	 * between num and num-1.193	 */194	if ((num & (num - 1)) == 0)195		return num;				/* already power 2 */196 197	return ((uint32) 1) << (pg_leftmost_one_pos32(num) + 1);198}199 200/*201 * pg_nextpower2_64202 *		Returns the next higher power of 2 above 'num', or 'num' if it's203 *		already a power of 2.204 *205 * 'num' mustn't be 0 or be above PG_UINT64_MAX / 2  + 1.206 */207static inline uint64208pg_nextpower2_64(uint64 num)209{210	Assert(num > 0 && num <= PG_UINT64_MAX / 2 + 1);211 212	/*213	 * A power 2 number has only 1 bit set.  Subtracting 1 from such a number214	 * will turn on all previous bits resulting in no common bits being set215	 * between num and num-1.216	 */217	if ((num & (num - 1)) == 0)218		return num;				/* already power 2 */219 220	return ((uint64) 1) << (pg_leftmost_one_pos64(num) + 1);221}222 223/*224 * pg_prevpower2_32225 *		Returns the next lower power of 2 below 'num', or 'num' if it's226 *		already a power of 2.227 *228 * 'num' mustn't be 0.229 */230static inline uint32231pg_prevpower2_32(uint32 num)232{233	return ((uint32) 1) << pg_leftmost_one_pos32(num);234}235 236/*237 * pg_prevpower2_64238 *		Returns the next lower power of 2 below 'num', or 'num' if it's239 *		already a power of 2.240 *241 * 'num' mustn't be 0.242 */243static inline uint64244pg_prevpower2_64(uint64 num)245{246	return ((uint64) 1) << pg_leftmost_one_pos64(num);247}248 249/*250 * pg_ceil_log2_32251 *		Returns equivalent of ceil(log2(num))252 */253static inline uint32254pg_ceil_log2_32(uint32 num)255{256	if (num < 2)257		return 0;258	else259		return pg_leftmost_one_pos32(num - 1) + 1;260}261 262/*263 * pg_ceil_log2_64264 *		Returns equivalent of ceil(log2(num))265 */266static inline uint64267pg_ceil_log2_64(uint64 num)268{269	if (num < 2)270		return 0;271	else272		return pg_leftmost_one_pos64(num - 1) + 1;273}274 275/*276 * With MSVC on x86_64 builds, try using native popcnt instructions via the277 * __popcnt and __popcnt64 intrinsics.  These don't work the same as GCC's278 * __builtin_popcount* intrinsic functions as they always emit popcnt279 * instructions.280 */281#if defined(_MSC_VER) && defined(_M_AMD64)282#define HAVE_X86_64_POPCNTQ283#endif284 285/*286 * On x86_64, we can use the hardware popcount instruction, but only if287 * we can verify that the CPU supports it via the cpuid instruction.288 *289 * Otherwise, we fall back to a hand-rolled implementation.290 */291#ifdef HAVE_X86_64_POPCNTQ292#if defined(HAVE__GET_CPUID) || defined(HAVE__CPUID)293#define TRY_POPCNT_FAST 1294#endif295#endif296 297#ifdef TRY_POPCNT_FAST298/* Attempt to use the POPCNT instruction, but perform a runtime check first */299extern int	(*pg_popcount32) (uint32 word);300extern int	(*pg_popcount64) (uint64 word);301 302#else303/* Use a portable implementation -- no need for a function pointer. */304extern int	pg_popcount32(uint32 word);305extern int	pg_popcount64(uint64 word);306 307#endif							/* TRY_POPCNT_FAST */308 309/* Count the number of one-bits in a byte array */310extern uint64 pg_popcount(const char *buf, int bytes);311 312/*313 * Rotate the bits of "word" to the right/left by n bits.314 */315static inline uint32316pg_rotate_right32(uint32 word, int n)317{318	return (word >> n) | (word << (32 - n));319}320 321static inline uint32322pg_rotate_left32(uint32 word, int n)323{324	return (word << n) | (word >> (32 - n));325}326 327/* size_t variants of the above, as required */328 329#if SIZEOF_SIZE_T == 4330#define pg_leftmost_one_pos_size_t pg_leftmost_one_pos32331#define pg_nextpower2_size_t pg_nextpower2_32332#define pg_prevpower2_size_t pg_prevpower2_32333#else334#define pg_leftmost_one_pos_size_t pg_leftmost_one_pos64335#define pg_nextpower2_size_t pg_nextpower2_64336#define pg_prevpower2_size_t pg_prevpower2_64337#endif338 339#endif							/* PG_BITUTILS_H */340 
codekingpro/portable-devtools · Team Ai