#!/usr/bin/env perl
use strict;
use warnings;
#use Test::More;
#use List::Util qw(reduce);

my @masks = map {
  my $group_bin = 0 x $_ . 1 x $_;
  my $bin_length = $_ * 2;
  my $mask_bin = $group_bin x ( 32 / $bin_length );
  unpack 'N', pack 'B32', $mask_bin;
} 1, 2, 4, 8, 16;

sub popcount($) {
  my $num = shift;
  maskshift( $num, 0, 1 );
}

sub maskshift {
  my ( $num, $mask_index, $length ) = @_;
  my $mask = $masks[$mask_index];
  my $sum = ( $num & $mask ) + ( $num >> $length & $mask );
  if ( $mask_index < $#masks ) {
    maskshift( $sum, $mask_index + 1, $length * 2 );
  } else {
    $sum;
  }
}

my $x = 10000000;
my $i;
for ($i = 1; $i <= $x; ++$i) {
	popcount($i);
}	

