Added bsr() function to util

This commit is contained in:
SChernykh 2022-05-09 11:25:52 +02:00
parent 820c5db5e8
commit d23c46ff84
6 changed files with 98 additions and 10 deletions

View file

@ -142,6 +142,19 @@ if (HAVE_PTHREAD_CANCEL)
add_definitions(/DHAVE_PTHREAD_CANCEL)
endif()
include(CheckCXXSourceCompiles)
check_cxx_source_compiles("int main(){ return __builtin_clzll(1);}" HAVE_BUILTIN_CLZLL)
check_cxx_source_compiles("#include <intrin.h>\n#pragma intrinsic(_BitScanReverse64)\nint main(){unsigned long r;_BitScanReverse64(&r,1);return r;}" HAVE_BITSCANREVERSE64)
if (HAVE_BUILTIN_CLZLL)
add_definitions(/DHAVE_BUILTIN_CLZLL)
endif()
if (HAVE_BITSCANREVERSE64)
add_definitions(/DHAVE_BITSCANREVERSE64)
endif()
add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES})
if (STATIC_BINARY)

View file

@ -562,19 +562,18 @@ enum HashMaxValue : uint64_t {
value = hash_uncompress(std::numeric_limits<uint16_t>::max())
};
static constexpr FORCEINLINE uint16_t hash_compress(uint64_t h)
static FORCEINLINE uint16_t hash_compress(uint64_t h)
{
if (h > HashMaxValue::value) {
h = HashMaxValue::value;
if (h <= HashValue::mask) {
return static_cast<uint16_t>(h);
}
uint64_t shift = 0;
while (h > HashValue::mask) {
h >>= 1;
shift += (1 << HashValue::bits);
if (h >= HashMaxValue::value) {
return std::numeric_limits<uint16_t>::max();
}
return static_cast<uint16_t>(shift | h);
const uint64_t shift = bsr(h) - (HashValue::bits - 1);
return static_cast<uint16_t>((shift << HashValue::bits) | (h >> shift));
}
}

View file

@ -384,4 +384,43 @@ bool resolve_host(std::string& host, bool& is_v6)
RandomDeviceSeed RandomDeviceSeed::instance;
struct BSR8
{
uint8_t data[256];
static constexpr BSR8 init() {
BSR8 result = { 55 };
for (int i = 1; i < 256; ++i) {
int x = i;
result.data[i] = 63;
while (x < 0x80) {
--result.data[i];
x <<= 1;
}
}
return result;
}
};
static constexpr BSR8 bsr8_table = BSR8::init();
NOINLINE uint64_t bsr_reference(uint64_t x)
{
uint32_t y = static_cast<uint32_t>(x);
uint64_t n0 = (x == y) ? 0 : 32;
y = static_cast<uint32_t>(x >> n0);
n0 ^= 32;
const uint64_t n1 = (y & 0xFFFF0000UL) ? 0 : 16;
y <<= n1;
const uint64_t n2 = (y & 0xFF000000UL) ? 0 : 8;
y <<= n2;
return bsr8_table.data[y >> 24] - n0 - n1 - n2;
}
} // namespace p2pool

View file

@ -203,6 +203,22 @@ FORCEINLINE uint64_t seconds_since_epoch()
return duration_cast<seconds>(steady_clock::now().time_since_epoch()).count();
}
uint64_t bsr_reference(uint64_t x);
#ifdef HAVE_BUILTIN_CLZLL
#define bsr(x) (63 - __builtin_clzll(x))
#elif defined HAVE_BITSCANREVERSE64
#pragma intrinsic(_BitScanReverse64)
FORCEINLINE uint64_t bsr(uint64_t x)
{
unsigned long index;
_BitScanReverse64(&index, x);
return index;
}
#else
#define bsr bsr_reference
#endif
} // namespace p2pool
namespace robin_hood {

View file

@ -74,7 +74,7 @@ set(SOURCES
src/keccak_tests.cpp
src/main.cpp
src/pool_block_tests.cpp
src/varint_tests.cpp
src/util_tests.cpp
src/wallet_tests.cpp
../external/src/cryptonote/crypto-ops-data.c
../external/src/cryptonote/crypto-ops.c
@ -160,6 +160,19 @@ endif()
add_definitions(/DZMQ_STATIC /DP2POOL_LOG_DISABLE)
include(CheckCXXSourceCompiles)
check_cxx_source_compiles("int main(){ return __builtin_clzll(1);}" HAVE_BUILTIN_CLZLL)
check_cxx_source_compiles("#include <intrin.h>\n#pragma intrinsic(_BitScanReverse64)\nint main(){unsigned long r;_BitScanReverse64(&r,1);return r;}" HAVE_BITSCANREVERSE64)
if (HAVE_BUILTIN_CLZLL)
add_definitions(/DHAVE_BUILTIN_CLZLL)
endif()
if (HAVE_BITSCANREVERSE64)
add_definitions(/DHAVE_BITSCANREVERSE64)
endif()
add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES})
target_link_libraries(${CMAKE_PROJECT_NAME} debug ${ZMQ_LIBRARY_DEBUG} debug ${UV_LIBRARY_DEBUG} optimized ${ZMQ_LIBRARY} optimized ${UV_LIBRARY} ${LIBS})
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/src/crypto_tests.txt" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)

View file

@ -21,7 +21,7 @@
namespace p2pool {
TEST(varint, read_write)
TEST(util, varint)
{
std::vector<uint8_t> v;
v.reserve(16);
@ -82,4 +82,12 @@ TEST(varint, read_write)
ASSERT_EQ(readVarint(buf2, buf2 + 1, check), nullptr);
}
TEST(util, bsr)
{
for (uint64_t i = 0, x = 1; i <= 63; ++i, x <<= 1) {
ASSERT_EQ(bsr(x), i);
ASSERT_EQ(bsr_reference(x), i);
}
}
}