Add count_ones function

Add the following function in `src/util.hpp`:

    template<typename N> inline unsigned int count_ones(N n);

This function returns the quantity of `1` bits in `n` — i.e., `n`’s
population count.
This commit is contained in:
8573 2014-03-19 05:42:30 +00:00
parent 2313201837
commit 23fddb0e93
2 changed files with 42 additions and 0 deletions

View File

@ -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()

View File

@ -237,6 +237,33 @@ inline std::size_t bit_width(const T& x) {
return sizeof(x) * std::numeric_limits<unsigned char>::digits;
}
/**
* Returns the quantity of `1` bits in `n` i.e., `n`s population count.
*
* Algorithm adapted from:
* <https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan>
*
* 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<typename N>
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