diff --git a/panda/src/putil/pbitops.I b/panda/src/putil/pbitops.I index 3d830306f4..041c55d6d1 100644 --- a/panda/src/putil/pbitops.I +++ b/panda/src/putil/pbitops.I @@ -15,7 +15,7 @@ * Returns the number of 1 bits in the indicated word. */ INLINE int -count_bits_in_word(uint16_t x) { +count_bits_in_word(unsigned short x) { return (int)num_bits_on[x]; } @@ -23,9 +23,9 @@ count_bits_in_word(uint16_t x) { * Returns the number of 1 bits in the indicated word. */ INLINE int -count_bits_in_word(uint32_t x) { +count_bits_in_word(unsigned int x) { #if defined(__GNUC__) && defined(__POPCNT__) - return __builtin_popcount((unsigned int) x); + return __builtin_popcount(x); #else return (int)num_bits_on[x & 0xffff] + (int)num_bits_on[(x >> 16) & 0xffff]; #endif @@ -35,19 +35,33 @@ count_bits_in_word(uint32_t x) { * Returns the number of 1 bits in the indicated word. */ INLINE int -count_bits_in_word(uint64_t x) { +count_bits_in_word(unsigned long x) { #if defined(__GNUC__) && defined(__POPCNT__) - return __builtin_popcountll((unsigned long long) x); + return __builtin_popcountl(x); +#elif defined(_LP64) + return count_bits_in_word((unsigned int)x) + count_bits_in_word((unsigned int)(x >> 32)); #else - return count_bits_in_word((uint32_t)x) + count_bits_in_word((uint32_t)(x >> 32)); + return count_bits_in_word((unsigned int)x); +#endif +} + +/** + * Returns the number of 1 bits in the indicated word. + */ +INLINE int +count_bits_in_word(unsigned long long x) { +#if defined(__GNUC__) && defined(__POPCNT__) + return __builtin_popcountll(x); +#else + return count_bits_in_word((unsigned int)x) + count_bits_in_word((unsigned int)(x >> 32)); #endif } /** * Returns a value such that every bit at or below the highest bit in x is 1. */ -INLINE uint16_t -flood_bits_down(uint16_t x) { +INLINE unsigned short +flood_bits_down(unsigned short x) { x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); @@ -58,8 +72,8 @@ flood_bits_down(uint16_t x) { /** * Returns a value such that every bit at or below the highest bit in x is 1. */ -INLINE uint32_t -flood_bits_down(uint32_t x) { +INLINE unsigned int +flood_bits_down(unsigned int x) { x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); @@ -71,8 +85,24 @@ flood_bits_down(uint32_t x) { /** * Returns a value such that every bit at or below the highest bit in x is 1. */ -INLINE uint64_t -flood_bits_down(uint64_t x) { +INLINE unsigned long +flood_bits_down(unsigned long x) { + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); +#if defined(_LP64) || defined(__LP64__) + x |= (x >> 32); +#endif + return x; +} + +/** + * Returns a value such that every bit at or below the highest bit in x is 1. + */ +INLINE unsigned long long +flood_bits_down(unsigned long long x) { x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); @@ -85,8 +115,8 @@ flood_bits_down(uint64_t x) { /** * Returns a value such that every bit at or above the highest bit in x is 1. */ -INLINE uint16_t -flood_bits_up(uint16_t x) { +INLINE unsigned short +flood_bits_up(unsigned short x) { x |= (x << 1); x |= (x << 2); x |= (x << 4); @@ -97,8 +127,8 @@ flood_bits_up(uint16_t x) { /** * Returns a value such that every bit at or above the highest bit in x is 1. */ -INLINE uint32_t -flood_bits_up(uint32_t x) { +INLINE unsigned int +flood_bits_up(unsigned int x) { x |= (x << 1); x |= (x << 2); x |= (x << 4); @@ -110,8 +140,24 @@ flood_bits_up(uint32_t x) { /** * Returns a value such that every bit at or above the highest bit in x is 1. */ -INLINE uint64_t -flood_bits_up(uint64_t x) { +INLINE unsigned long +flood_bits_up(unsigned long x) { + x |= (x << 1); + x |= (x << 2); + x |= (x << 4); + x |= (x << 8); + x |= (x << 16); +#if defined(_LP64) || defined(__LP64__) + x |= (x << 32); +#endif + return x; +} + +/** + * Returns a value such that every bit at or above the highest bit in x is 1. + */ +INLINE unsigned long long +flood_bits_up(unsigned long long x) { x |= (x << 1); x |= (x << 2); x |= (x << 4); @@ -126,7 +172,7 @@ flood_bits_up(uint64_t x) { * no 1 bits. */ INLINE int -get_lowest_on_bit(uint16_t x) { +get_lowest_on_bit(unsigned short x) { #if defined(_MSC_VER) unsigned long result; return (_BitScanForward(&result, (unsigned long) x) == 0) ? -1 : result; @@ -137,7 +183,7 @@ get_lowest_on_bit(uint16_t x) { return -1; } - uint16_t w = (x & (~x + 1)); + unsigned short w = (x & (~x + 1)); return (int)num_bits_on[w - 1]; #endif } @@ -147,7 +193,7 @@ get_lowest_on_bit(uint16_t x) { * no 1 bits. */ INLINE int -get_lowest_on_bit(uint32_t x) { +get_lowest_on_bit(unsigned int x) { #if defined(_MSC_VER) unsigned long result; return (_BitScanForward(&result, (unsigned long) x) == 0) ? -1 : result; @@ -158,7 +204,7 @@ get_lowest_on_bit(uint32_t x) { return -1; } - uint32_t w = (x & (~x + 1)); + unsigned int w = (x & (~x + 1)); return count_bits_in_word(w - 1); #endif } @@ -168,7 +214,28 @@ get_lowest_on_bit(uint32_t x) { * no 1 bits. */ INLINE int -get_lowest_on_bit(uint64_t x) { +get_lowest_on_bit(unsigned long x) { +#if defined(_MSC_VER) && defined(_M_X64) + unsigned long result; + return (_BitScanForward(&result, x) == 0) ? -1 : result; +#elif defined(__GNUC__) + return __builtin_ffsl((long) x) - 1; +#else + if (x == 0) { + return -1; + } + + unsigned long w = (x & (~x + 1)); + return count_bits_in_word(w - 1); +#endif +} + +/** + * Returns the index of the lowest 1 bit in the word. Returns -1 if there are + * no 1 bits. + */ +INLINE int +get_lowest_on_bit(unsigned long long x) { #if defined(_MSC_VER) && defined(_M_X64) unsigned long result; return (_BitScanForward64(&result, (unsigned __int64) x) == 0) ? -1 : result; @@ -179,7 +246,7 @@ get_lowest_on_bit(uint64_t x) { return -1; } - uint64_t w = (x & (~x + 1)); + unsigned long long w = (x & (~x + 1)); return count_bits_in_word(w - 1); #endif } @@ -189,14 +256,14 @@ get_lowest_on_bit(uint64_t x) { * are no 1 bits. */ INLINE int -get_highest_on_bit(uint16_t x) { +get_highest_on_bit(unsigned short x) { #if defined(_MSC_VER) unsigned long result; return (_BitScanReverse(&result, (unsigned long) x) == 0) ? -1 : result; #elif defined(__GNUC__) return (x == 0) ? -1 : 31 - __builtin_clz((unsigned int) x); #else - uint16_t w = flood_bits_down(x); + unsigned short w = flood_bits_down(x); return count_bits_in_word(w) - 1; #endif } @@ -206,14 +273,14 @@ get_highest_on_bit(uint16_t x) { * are no 1 bits. */ INLINE int -get_highest_on_bit(uint32_t x) { +get_highest_on_bit(unsigned int x) { #if defined(_MSC_VER) unsigned long result; return (_BitScanReverse(&result, (unsigned long) x) == 0) ? -1 : result; #elif defined(__GNUC__) - return (x == 0) ? -1 : 31 - __builtin_clz((unsigned int) x); + return (x == 0) ? -1 : 31 - __builtin_clz(x); #else - uint32_t w = flood_bits_down(x); + unsigned int w = flood_bits_down(x); return count_bits_in_word(w) - 1; #endif } @@ -223,14 +290,31 @@ get_highest_on_bit(uint32_t x) { * are no 1 bits. */ INLINE int -get_highest_on_bit(uint64_t x) { +get_highest_on_bit(unsigned long x) { +#if defined(_MSC_VER) && defined(_M_X64) + unsigned long result; + return (_BitScanReverse(&result, (unsigned long) x) == 0) ? -1 : result; +#elif defined(__GNUC__) + return (x == 0) ? -1 : 63 - __builtin_clzl(x); +#else + unsigned long long w = flood_bits_down(x); + return count_bits_in_word(w) - 1; +#endif +} + +/** + * Returns the index of the highest 1 bit in the word. Returns -1 if there + * are no 1 bits. + */ +INLINE int +get_highest_on_bit(unsigned long long x) { #if defined(_MSC_VER) && defined(_M_X64) unsigned long result; return (_BitScanReverse64(&result, (unsigned __int64) x) == 0) ? -1 : result; #elif defined(__GNUC__) - return (x == 0) ? -1 : 63 - __builtin_clzll((unsigned long long) x); + return (x == 0) ? -1 : 63 - __builtin_clzll(x); #else - uint64_t w = flood_bits_down(x); + unsigned long long w = flood_bits_down(x); return count_bits_in_word(w) - 1; #endif } @@ -241,7 +325,7 @@ get_highest_on_bit(uint64_t x) { * Returns the smallest number n such that (1 << n) is larger than x. */ INLINE int -get_next_higher_bit(uint16_t x) { +get_next_higher_bit(unsigned short x) { return get_highest_on_bit(x) + 1; } @@ -251,7 +335,7 @@ get_next_higher_bit(uint16_t x) { * Returns the smallest number n such that (1 << n) is larger than x. */ INLINE int -get_next_higher_bit(uint32_t x) { +get_next_higher_bit(unsigned int x) { return get_highest_on_bit(x) + 1; } @@ -261,6 +345,16 @@ get_next_higher_bit(uint32_t x) { * Returns the smallest number n such that (1 << n) is larger than x. */ INLINE int -get_next_higher_bit(uint64_t x) { +get_next_higher_bit(unsigned long x) { + return get_highest_on_bit(x) + 1; +} + +/** + * Returns the smallest power of 2 greater than x. + * + * Returns the smallest number n such that (1 << n) is larger than x. + */ +INLINE int +get_next_higher_bit(unsigned long long x) { return get_highest_on_bit(x) + 1; } diff --git a/panda/src/putil/pbitops.h b/panda/src/putil/pbitops.h index 5b4a10b601..342827f983 100644 --- a/panda/src/putil/pbitops.h +++ b/panda/src/putil/pbitops.h @@ -24,27 +24,33 @@ // This file defines a few low-level bit-operation routines, optimized all to // heck. -INLINE int count_bits_in_word(uint16_t x); -INLINE int count_bits_in_word(uint32_t x); -INLINE int count_bits_in_word(uint64_t x); +INLINE int count_bits_in_word(unsigned short x); +INLINE int count_bits_in_word(unsigned int x); +INLINE int count_bits_in_word(unsigned long x); +INLINE int count_bits_in_word(unsigned long long x); -INLINE uint16_t flood_bits_down(uint16_t x); -INLINE uint32_t flood_bits_down(uint32_t x); -INLINE uint64_t flood_bits_down(uint64_t x); -INLINE uint16_t flood_bits_up(uint16_t x); -INLINE uint32_t flood_bits_up(uint32_t x); -INLINE uint64_t flood_bits_up(uint64_t x); +INLINE unsigned short flood_bits_down(unsigned short x); +INLINE unsigned int flood_bits_down(unsigned int x); +INLINE unsigned long flood_bits_down(unsigned long x); +INLINE unsigned long long flood_bits_down(unsigned long long x); +INLINE unsigned short flood_bits_up(unsigned short x); +INLINE unsigned int flood_bits_up(unsigned int x); +INLINE unsigned long flood_bits_up(unsigned long x); +INLINE unsigned long long flood_bits_up(unsigned long long x); -INLINE int get_lowest_on_bit(uint16_t x); -INLINE int get_lowest_on_bit(uint32_t x); -INLINE int get_lowest_on_bit(uint64_t x); -INLINE int get_highest_on_bit(uint16_t x); -INLINE int get_highest_on_bit(uint32_t x); -INLINE int get_highest_on_bit(uint64_t x); +INLINE int get_lowest_on_bit(unsigned short x); +INLINE int get_lowest_on_bit(unsigned int x); +INLINE int get_lowest_on_bit(unsigned long x); +INLINE int get_lowest_on_bit(unsigned long long x); +INLINE int get_highest_on_bit(unsigned short x); +INLINE int get_highest_on_bit(unsigned int x); +INLINE int get_highest_on_bit(unsigned long x); +INLINE int get_highest_on_bit(unsigned long long x); -INLINE int get_next_higher_bit(uint16_t x); -INLINE int get_next_higher_bit(uint32_t x); -INLINE int get_next_higher_bit(uint64_t x); +INLINE int get_next_higher_bit(unsigned short x); +INLINE int get_next_higher_bit(unsigned int x); +INLINE int get_next_higher_bit(unsigned long x); +INLINE int get_next_higher_bit(unsigned long long x); // This table precomputes the number of on bits in each 16-bit word. extern EXPCL_PANDA_PUTIL const unsigned char num_bits_on[65536];