From 23fddb0e93dae8a241fc8234710016c00a4bec14 Mon Sep 17 00:00:00 2001 From: 8573 <8573dd@gmail.com> Date: Wed, 19 Mar 2014 05:42:30 +0000 Subject: [PATCH] Add `count_ones` function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the following function in `src/util.hpp`: template inline unsigned int count_ones(N n); This function returns the quantity of `1` bits in `n` — i.e., `n`’s population count. --- src/tests/test_util.cpp | 15 +++++++++++++++ src/util.hpp | 27 +++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/tests/test_util.cpp b/src/tests/test_util.cpp index 08bffe75aba..e0a54100049 100644 --- a/src/tests/test_util.cpp +++ b/src/tests/test_util.cpp @@ -89,6 +89,21 @@ BOOST_AUTO_TEST_CASE( test_bit_width ) BOOST_CHECK( bit_width((boost::uint64_t) 0) == 64 ); } +BOOST_AUTO_TEST_CASE( test_count_ones ) +{ + BOOST_CHECK( count_ones(0) == 0 ); + BOOST_CHECK( count_ones(1) == 1 ); + BOOST_CHECK( count_ones(2) == 1 ); + BOOST_CHECK( count_ones(3) == 2 ); + BOOST_CHECK( count_ones(4) == 1 ); + BOOST_CHECK( count_ones(5) == 2 ); + BOOST_CHECK( count_ones(6) == 2 ); + BOOST_CHECK( count_ones(7) == 3 ); + BOOST_CHECK( count_ones(8) == 1 ); + BOOST_CHECK( count_ones(9) == 2 ); + BOOST_CHECK( count_ones(12345) == 6 ); +} + /* vim: set ts=4 sw=4: */ BOOST_AUTO_TEST_SUITE_END() diff --git a/src/util.hpp b/src/util.hpp index 4bc75cdada4..edf39fc30c7 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -237,6 +237,33 @@ inline std::size_t bit_width(const T& x) { return sizeof(x) * std::numeric_limits::digits; } +/** + * Returns the quantity of `1` bits in `n` — i.e., `n`’s population count. + * + * Algorithm adapted from: + * + * + * This algorithm was chosen for relative simplicity, not for speed. + * + * @tparam N The type of `n`. This should be a fundamental integer type no + * greater than `UINT_MAX` bits in width; if it is not, the return value is + * undefined. + * + * @param n An integer upon which to operate. + * + * @returns the quantity of `1` bits in `n`, if `N` is a fundamental integer + * type. + */ +template +inline unsigned int count_ones(N n) { + unsigned int r = 0; + while (n) { + n &= n-1; + ++r; + } + return r; +} + #ifdef __GNUC__ #define LIKELY(a) __builtin_expect((a),1) // Tells GCC to optimize code so that if is likely to happen #define UNLIKELY(a) __builtin_expect((a),0) // Tells GCC to optimize code so that if is unlikely to happen