diff options
Diffstat (limited to 'src/google/protobuf/stubs/port.h')
-rw-r--r-- | src/google/protobuf/stubs/port.h | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/src/google/protobuf/stubs/port.h b/src/google/protobuf/stubs/port.h index d7f93b4c..376be5f7 100644 --- a/src/google/protobuf/stubs/port.h +++ b/src/google/protobuf/stubs/port.h @@ -327,6 +327,61 @@ static inline uint64 bswap_64(uint64 x) { #endif // =================================================================== +// from google3/util/bits/bits.h + +class Bits { + public: + static uint32 Log2FloorNonZero(uint32 n) { +#if defined(__GNUC__) + return 31 ^ __builtin_clz(n); +#elif defined(COMPILER_MSVC) && defined(_M_IX86) + _asm { + bsr ebx, n + mov n, ebx + } + return n; +#else + return Log2FloorNonZero_Portable(n); +#endif + } + + static uint64 Log2FloorNonZero64(uint64 n) { +#if defined(__GNUC__) + return 63 ^ __builtin_clzll(n); +#else + return Log2FloorNonZero64_Portable(n); +#endif + } + private: + static int Log2FloorNonZero_Portable(uint32 n) { + if (n == 0) + return -1; + int log = 0; + uint32 value = n; + for (int i = 4; i >= 0; --i) { + int shift = (1 << i); + uint32 x = value >> shift; + if (x != 0) { + value = x; + log += shift; + } + } + assert(value == 1); + return log; + } + + static int Log2FloorNonZero64_Portable(uint64 n) { + const uint32 topbits = static_cast<uint32>(n >> 32); + if (topbits == 0) { + // Top bits are zero, so scan in bottom bits + return Log2FloorNonZero(static_cast<uint32>(n)); + } else { + return 32 + Log2FloorNonZero(topbits); + } + } +}; + +// =================================================================== // from google3/util/endian/endian.h LIBPROTOBUF_EXPORT uint32 ghtonl(uint32 x); |