mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
bpo-29782: Consolidate _Py_Bit_Length() (GH-20739)
In GH-2866, _Py_Bit_Length() was added to pymath.h for lack of a better location. GH-20518 added a more appropriate header file for bit utilities. It also shows how to properly use intrinsics. This allows reconsidering bpo-29782. * Move the function to the new header. * Changed return type to match __builtin_clzl() and reviewed usage. * Use intrinsics where available. * Pick a fallback implementation suitable for inlining.
This commit is contained in:
parent
25f38d7044
commit
794e7d1ab2
6 changed files with 100 additions and 36 deletions
|
@ -7,8 +7,8 @@
|
|||
- _Py_bswap64(uint64_t)
|
||||
*/
|
||||
|
||||
#ifndef Py_INTERNAL_BSWAP_H
|
||||
#define Py_INTERNAL_BSWAP_H
|
||||
#ifndef Py_INTERNAL_BITUTILS_H
|
||||
#define Py_INTERNAL_BITUTILS_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -131,8 +131,47 @@ _Py_popcount32(uint32_t x)
|
|||
}
|
||||
|
||||
|
||||
// Return the index of the most significant 1 bit in 'x'. This is the smallest
|
||||
// integer k such that x < 2**k. Equivalent to floor(log2(x)) + 1 for x != 0.
|
||||
static inline int
|
||||
_Py_bit_length(unsigned long x)
|
||||
{
|
||||
#if (defined(__clang__) || defined(__GNUC__))
|
||||
if (x != 0) {
|
||||
// __builtin_clzl() is available since GCC 3.4.
|
||||
// Undefined behavior for x == 0.
|
||||
return (int)sizeof(unsigned long) * 8 - __builtin_clzl(x);
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
#elif defined(_MSC_VER)
|
||||
// _BitScanReverse() is documented to search 32 bits.
|
||||
Py_BUILD_ASSERT(sizeof(unsigned long) <= 4);
|
||||
unsigned long msb;
|
||||
if (_BitScanReverse(&msb, x)) {
|
||||
return (int)msb + 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
const int BIT_LENGTH_TABLE[32] = {
|
||||
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
|
||||
};
|
||||
int msb = 0;
|
||||
while (x >= 32) {
|
||||
msb += 6;
|
||||
x >>= 6;
|
||||
}
|
||||
msb += BIT_LENGTH_TABLE[x];
|
||||
return msb;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_BSWAP_H */
|
||||
|
||||
#endif /* !Py_INTERNAL_BITUTILS_H */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue