From 3a4a7b742a64de0250a0d108096e3643c6cae578 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sat, 23 Mar 2019 12:53:36 +0100 Subject: [PATCH] deduplicate code implementing log2p1() --- include/libtorrent/aux_/ffs.hpp | 6 ++++- src/ffs.cpp | 41 ++++++++++++++++++--------------- src/session_impl.cpp | 27 +++------------------- 3 files changed, 31 insertions(+), 43 deletions(-) diff --git a/include/libtorrent/aux_/ffs.hpp b/include/libtorrent/aux_/ffs.hpp index 12ffba387..c243b9f2e 100644 --- a/include/libtorrent/aux_/ffs.hpp +++ b/include/libtorrent/aux_/ffs.hpp @@ -37,7 +37,8 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/aux_/export.hpp" #include "libtorrent/span.hpp" -namespace libtorrent { namespace aux { +namespace libtorrent { +namespace aux { // For a general reference of the problems these routines are about // see http://en.wikipedia.org/wiki/Find_first_set @@ -61,6 +62,9 @@ namespace libtorrent { namespace aux { // this function statically determines if hardware or software is used // and expect the range to be in big-endian byte order TORRENT_EXTRA_EXPORT int count_trailing_ones(span buf); + + // returns the index of the most significant set bit. + TORRENT_EXTRA_EXPORT int log2p1(std::uint32_t v); }} #endif // TORRENT_FFS_HPP_INCLUDE diff --git a/src/ffs.cpp b/src/ffs.cpp index 2540fac22..f00a8c7f0 100644 --- a/src/ffs.cpp +++ b/src/ffs.cpp @@ -42,7 +42,28 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/aux_/disable_warnings_pop.hpp" -namespace libtorrent { namespace aux { +namespace libtorrent { +namespace aux { + + // returns the index of the first set bit. + // Use std::log2p1 in C++20 + int log2p1(std::uint32_t v) + { +// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn + static const int MultiplyDeBruijnBitPosition[32] = + { + 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, + 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 + }; + + v |= v >> 1; // first round down to one less than a power of 2 + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + + return MultiplyDeBruijnBitPosition[std::uint32_t(v * 0x07C4ACDDU) >> 27]; + } int count_leading_zeros_sw(span buf) { @@ -55,23 +76,7 @@ namespace libtorrent { namespace aux { for (int i = 0; i < num; i++) { if (ptr[i] == 0) continue; - std::uint32_t v = aux::network_to_host(ptr[i]); - - // http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious - static const int MultiplyDeBruijnBitPosition[32] = - { - 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, - 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 - }; - - v |= v >> 1; // first round down to one less than a power of 2 - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - - return i * 32 + 31 - MultiplyDeBruijnBitPosition[ - static_cast(v * 0x07C4ACDDU) >> 27]; + return i * 32 + 31 - log2p1(aux::network_to_host(ptr[i])); } return num * 32; diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 958395ae4..f7ca7da20 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -90,6 +90,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/aux_/scope_end.hpp" #include "libtorrent/aux_/set_socket_buffer.hpp" #include "libtorrent/aux_/generate_peer_id.hpp" +#include "libtorrent/aux_/ffs.hpp" #ifndef TORRENT_DISABLE_LOGGING @@ -3510,37 +3511,15 @@ namespace aux { } } - namespace { - // returns the index of the first set bit. - int log2(std::uint32_t v) - { -// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn - static const int MultiplyDeBruijnBitPosition[32] = - { - 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, - 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 - }; - - v |= v >> 1; // first round down to one less than a power of 2 - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - - return MultiplyDeBruijnBitPosition[std::uint32_t(v * 0x07C4ACDDU) >> 27]; - } - - } // anonymous namespace - void session_impl::received_buffer(int s) { - int index = std::min(log2(std::uint32_t(s >> 3)), 17); + int index = std::min(aux::log2p1(std::uint32_t(s >> 3)), 17); m_stats_counters.inc_stats_counter(counters::socket_recv_size3 + index); } void session_impl::sent_buffer(int s) { - int index = std::min(log2(std::uint32_t(s >> 3)), 17); + int index = std::min(aux::log2p1(std::uint32_t(s >> 3)), 17); m_stats_counters.inc_stats_counter(counters::socket_send_size3 + index); }