#!/usr/bin/perl

# Idiom #263 Integer logarithm in base 2

use POSIX qw( log2 ilogb logb floor ceil );

sub log2d { floor log2 shift };

sub log2u { ceil log2 shift };


my @cols = qw( iter value log2 rnd-dn log2d rnd-up log2u logb ilogb diff );

printf '%9s ' x @cols . "\n", @cols;

foreach my $iter ( 1..20 ) {
    my $r = rand(1000);

    my %z = (
        '1_i'      => $iter,
        '2_value'  => $r,
        '3_log2'   => log2($r),
        '4_rnd-dn' => floor(log($r)/log(2)),
        '5_log2d'  => log2d($r),
        '6_rnd-up' => ceil(log($r)/log(2)),
        '7_log2u'  => log2u($r),
        '8_logb'   => logb($r),
        '9_ilogb'  => ilogb($r),
    );

    my @diff;
    push @diff, 'log2d ' if $z{'4_rnd-dn'} != $z{'5_log2d'};
    push @diff, 'log2u ' if $z{'6_rnd-up'} != $z{'7_log2u'};
    my $diff = @diff ? join ', ', @diff : 'none';
    
    my @values = map { $z{$_} } sort keys %z;
    printf '%9G ' x @values . "%10s\n", @values, $diff;
    
}
printf "\n\nThe diff column indicates whether any differences were " .
       "found between rnd-dn and log2d or rnd-up and log2u\n";

