From 5f43c06bae6d03e319dd2f230fe7cbd74399a773 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Mon, 13 Jul 2015 15:56:04 -0400 Subject: [PATCH] uint128: Implement popcount() --- include/fc/uint128.hpp | 2 ++ src/uint128.cpp | 28 +++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/include/fc/uint128.hpp b/include/fc/uint128.hpp index 2e79a56..5e599dc 100644 --- a/include/fc/uint128.hpp +++ b/include/fc/uint128.hpp @@ -108,6 +108,8 @@ namespace fc static void full_product( const uint128& a, const uint128& b, uint128& result_hi, uint128& result_lo ); + uint8_t popcount() const; + // fields must be public for serialization uint64_t hi; uint64_t lo; diff --git a/src/uint128.cpp b/src/uint128.cpp index e834fba..dae2aef 100644 --- a/src/uint128.cpp +++ b/src/uint128.cpp @@ -325,7 +325,33 @@ namespace fc return; } - + + static uint8_t _popcount_64( uint64_t x ) + { + static const uint64_t m[] = { + 0x5555555555555555ULL, + 0x3333333333333333ULL, + 0x0F0F0F0F0F0F0F0FULL, + 0x00FF00FF00FF00FFULL, + 0x0000FFFF0000FFFFULL, + 0x00000000FFFFFFFFULL + }; + // TODO future optimization: replace slow, portable version + // with fast, non-portable __builtin_popcountll intrinsic + // (when available) + + for( int i=0, w=1; i<6; i++, w+=w ) + { + x = (x & m[i]) + ((x >> w) & m[i]); + } + return uint8_t(x); + } + + uint8_t uint128::popcount()const + { + return _popcount_64( lo ) + _popcount_64( hi ); + } + void to_variant( const uint128& var, variant& vo ) { vo = std::string(var); } void from_variant( const variant& var, uint128& vo ){ vo = uint128(var.as_string()); }