deduplicate code implementing log2p1()

This commit is contained in:
Arvid Norberg 2019-03-23 12:53:36 +01:00 committed by Arvid Norberg
parent 20cb26fcc1
commit 3a4a7b742a
3 changed files with 31 additions and 43 deletions

View File

@ -37,7 +37,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/aux_/export.hpp" #include "libtorrent/aux_/export.hpp"
#include "libtorrent/span.hpp" #include "libtorrent/span.hpp"
namespace libtorrent { namespace aux { namespace libtorrent {
namespace aux {
// For a general reference of the problems these routines are about // For a general reference of the problems these routines are about
// see http://en.wikipedia.org/wiki/Find_first_set // 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 // this function statically determines if hardware or software is used
// and expect the range to be in big-endian byte order // and expect the range to be in big-endian byte order
TORRENT_EXTRA_EXPORT int count_trailing_ones(span<std::uint32_t const> buf); TORRENT_EXTRA_EXPORT int count_trailing_ones(span<std::uint32_t const> buf);
// returns the index of the most significant set bit.
TORRENT_EXTRA_EXPORT int log2p1(std::uint32_t v);
}} }}
#endif // TORRENT_FFS_HPP_INCLUDE #endif // TORRENT_FFS_HPP_INCLUDE

View File

@ -42,7 +42,28 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/aux_/disable_warnings_pop.hpp" #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<std::uint32_t const> buf) int count_leading_zeros_sw(span<std::uint32_t const> buf)
{ {
@ -55,23 +76,7 @@ namespace libtorrent { namespace aux {
for (int i = 0; i < num; i++) for (int i = 0; i < num; i++)
{ {
if (ptr[i] == 0) continue; if (ptr[i] == 0) continue;
std::uint32_t v = aux::network_to_host(ptr[i]); return i * 32 + 31 - log2p1(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<std::uint32_t>(v * 0x07C4ACDDU) >> 27];
} }
return num * 32; return num * 32;

View File

@ -90,6 +90,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/aux_/scope_end.hpp" #include "libtorrent/aux_/scope_end.hpp"
#include "libtorrent/aux_/set_socket_buffer.hpp" #include "libtorrent/aux_/set_socket_buffer.hpp"
#include "libtorrent/aux_/generate_peer_id.hpp" #include "libtorrent/aux_/generate_peer_id.hpp"
#include "libtorrent/aux_/ffs.hpp"
#ifndef TORRENT_DISABLE_LOGGING #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) 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); m_stats_counters.inc_stats_counter(counters::socket_recv_size3 + index);
} }
void session_impl::sent_buffer(int s) 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); m_stats_counters.inc_stats_counter(counters::socket_send_size3 + index);
} }