Skip to content

Instantly share code, notes, and snippets.

@lichray
Created June 24, 2013 00:00
Show Gist options
  • Save lichray/5846992 to your computer and use it in GitHub Desktop.
Save lichray/5846992 to your computer and use it in GitHub Desktop.
#include <limits>
#include <climits>
#include <type_traits>
template <int bit>
struct fill_bits
{
template <typename Int>
static constexpr auto apply(Int n) -> Int
{
return _lambda(fill_bits<bit / 2>::apply(n));
}
private:
template <typename Int>
static constexpr auto _lambda(Int x) -> Int
{
return (x << (bit / 2)) ^ x;
}
};
template <>
struct fill_bits<CHAR_BIT>
{
template <typename Int>
static constexpr auto apply(Int n) -> Int
{
return n;
}
};
template <typename Int>
constexpr auto magic(Int n)
-> typename std::enable_if<std::is_unsigned<Int>::value, Int>::type
{
return fill_bits<std::numeric_limits<Int>::digits>::apply(n);
}
template <typename Int>
struct m1 : std::integral_constant<Int, magic(Int(0x55))> {};
template <typename Int>
struct m2 : std::integral_constant<Int, magic(Int(0x33))> {};
template <typename Int>
struct m4 : std::integral_constant<Int, magic(Int(0x0f))> {};
template <typename Int>
struct h01 : std::integral_constant<Int, magic(Int(0x01))> {};
template <typename Int>
/* c++14 */ inline auto popcount(Int x) -> std::size_t
{
x -= (x >> 1) & m1<Int>();
x = (x & m2<Int>()) + ((x >> 2) & m2<Int>());
x = (x + (x >> 4)) & m4<Int>();
return Int(x * h01<Int>()) >>
(std::numeric_limits<Int>::digits - CHAR_BIT);
}
#include <iostream>
#include <chrono>
#include <cstdlib>
int main() {
using namespace std::chrono;
using traits = std::numeric_limits<uint32_t>;
steady_clock::time_point t1, t2;
t1 = steady_clock::now();
for (uint32_t x = 0; x < traits::max(); ++x)
if (popcount(x) > traits::digits)
std::exit(1);
t2 = steady_clock::now();
std::cout << "my popcount: "
<< duration_cast<duration<double>>(t2 - t1).count() << std::endl;
t1 = steady_clock::now();
for (uint32_t x = 0; x < traits::max(); ++x)
if (__builtin_popcount(x) > traits::digits)
std::exit(1);
t2 = steady_clock::now();
std::cout << "__builtin_popcount: "
<< duration_cast<duration<double>>(t2 - t1).count() << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment