// // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #pragma once #include "td/utils/common.h" #include "td/utils/logging.h" #if TD_MSVC #include #endif namespace td { inline int32 count_leading_zeroes32(uint32 x); inline int32 count_leading_zeroes64(uint64 x); inline int32 count_trailing_zeroes32(uint32 x); inline int32 count_trailing_zeroes64(uint64 x); inline uint32 bswap32(uint32 x); inline uint64 bswap64(uint64 x); inline int32 count_bits32(uint32 x); inline int32 count_bits64(uint64 x); #if TD_MSVC inline int32 count_leading_zeroes32(uint32 x) { unsigned long res = 0; if (_BitScanReverse(&res, x)) { return 31 - res; } return 32; } inline int32 count_leading_zeroes64(uint64 x) { #if defined(_M_X64) unsigned long res = 0; if (_BitScanReverse64(&res, x)) { return 63 - res; } return 64; #else if ((x >> 32) == 0) { return count_leading_zeroes32(static_cast(x)) + 32; } else { return count_leading_zeroes32(static_cast(x >> 32)); } #endif } inline int32 count_trailing_zeroes32(uint32 x) { unsigned long res = 0; if (_BitScanForward(&res, x)) { return res; } return 32; } inline int32 count_trailing_zeroes64(uint64 x) { #if defined(_M_X64) unsigned long res = 0; if (_BitScanForward64(&res, x)) { return res; } return 64; #else if (static_cast(x) == 0) { return count_trailing_zeroes32(static_cast(x >> 32)) + 32; } else { return count_trailing_zeroes32(static_cast(x)); } #endif } inline uint32 bswap32(uint32 x) { return _byteswap_ulong(x); } inline uint64 bswap64(uint64 x) { return _byteswap_uint64(x); } inline int32 count_bits32(uint32 x) { return __popcnt(x); } inline int32 count_bits64(uint64 x) { #if defined(_M_X64) return __popcnt64(x); #else return count_bits32(static_cast(x >> 32)) + count_bits32(static_cast(x)); #endif } #else inline int32 count_leading_zeroes32(uint32 x) { if (x == 0) { return 32; } return __builtin_clz(x); } inline int32 count_leading_zeroes64(uint64 x) { if (x == 0) { return 64; } return __builtin_clzll(x); } inline int32 count_trailing_zeroes32(uint32 x) { if (x == 0) { return 32; } return __builtin_ctz(x); } inline int32 count_trailing_zeroes64(uint64 x) { if (x == 0) { return 64; } return __builtin_ctzll(x); } inline uint32 bswap32(uint32 x) { return __builtin_bswap32(x); } inline uint64 bswap64(uint64 x) { return __builtin_bswap64(x); } inline int32 count_bits32(uint32 x) { return __builtin_popcount(x); } inline int32 count_bits64(uint64 x) { return __builtin_popcountll(x); } #endif //TODO: optimize inline int32 count_leading_zeroes_non_zero32(uint32 x) { DCHECK(x != 0); return count_leading_zeroes32(x); } inline int32 count_leading_zeroes_non_zero64(uint64 x) { DCHECK(x != 0); return count_leading_zeroes64(x); } inline int32 count_trailing_zeroes_non_zero32(uint32 x) { DCHECK(x != 0); return count_trailing_zeroes32(x); } inline int32 count_trailing_zeroes_non_zero64(uint64 x) { DCHECK(x != 0); return count_trailing_zeroes64(x); } } // namespace td