diff --git a/libraries/chain/include/eosio/chain/incremental_merkle.hpp b/libraries/chain/include/eosio/chain/incremental_merkle.hpp index 0a84d076f5..68b4348e9d 100644 --- a/libraries/chain/include/eosio/chain/incremental_merkle.hpp +++ b/libraries/chain/include/eosio/chain/incremental_merkle.hpp @@ -2,53 +2,12 @@ #include #include #include +#include -namespace eosio { namespace chain { +namespace eosio::chain { namespace detail { -/** - * given an unsigned integral number return the smallest - * power-of-2 which is greater than or equal to the given number - * - * @param value - an unsigned integral - * @return - the minimum power-of-2 which is >= value - */ -constexpr uint64_t next_power_of_2(uint64_t value) { - value -= 1; - value |= value >> 1; - value |= value >> 2; - value |= value >> 4; - value |= value >> 8; - value |= value >> 16; - value |= value >> 32; - value += 1; - return value; -} - -/** - * Given a power-of-2 (assumed correct) return the number of leading zeros - * - * This is a classic count-leading-zeros in parallel without the necessary - * math to make it safe for anything that is not already a power-of-2 - * - * @param value - and integral power-of-2 - * @return the number of leading zeros - */ -constexpr int clz_power_2(uint64_t value) { - int lz = 64; - - if (value) lz--; - if (value & 0x00000000FFFFFFFFULL) lz -= 32; - if (value & 0x0000FFFF0000FFFFULL) lz -= 16; - if (value & 0x00FF00FF00FF00FFULL) lz -= 8; - if (value & 0x0F0F0F0F0F0F0F0FULL) lz -= 4; - if (value & 0x3333333333333333ULL) lz -= 2; - if (value & 0x5555555555555555ULL) lz -= 1; - - return lz; -} - /** * Given a number of nodes return the depth required to store them * in a fully balanced binary tree. @@ -56,12 +15,11 @@ constexpr int clz_power_2(uint64_t value) { * @param node_count - the number of nodes in the implied tree * @return the max depth of the minimal tree that stores them */ -constexpr int calcluate_max_depth(uint64_t node_count) { - if (node_count == 0) { +constexpr uint64_t calculate_max_depth(uint64_t node_count) { + if (node_count == 0) return 0; - } - auto implied_count = next_power_of_2(node_count); - return clz_power_2(implied_count) + 1; + // following is non-floating point equivalent to `std::ceil(std::log2(node_count)) + 1)` (and about 9x faster) + return std::bit_width(std::bit_ceil(node_count)); } template @@ -167,7 +125,7 @@ class incremental_merkle_impl { */ const DigestType& append(const DigestType& digest) { bool partial = false; - auto max_depth = detail::calcluate_max_depth(_node_count + 1); + auto max_depth = detail::calculate_max_depth(_node_count + 1); auto current_depth = max_depth - 1; auto index = _node_count; auto top = digest; @@ -246,6 +204,6 @@ class incremental_merkle_impl { typedef incremental_merkle_impl incremental_merkle; typedef incremental_merkle_impl shared_incremental_merkle; -} } /// eosio::chain +} /// eosio::chain FC_REFLECT( eosio::chain::incremental_merkle, (_active_nodes)(_node_count) );