Algorithm-Heapify-XS

 view release on metacpan or  search on metacpan

t/overload_precision.t  view on Meta::CPAN

use strict;
use warnings;

use Config;
use Test::More;

use Algorithm::Heapify::XS qw(
    max_heapify
    max_heap_shift
    max_heap_push
    max_heap_adjust_item
    max_heap_adjust_top
    maxstr_heapify
    maxstr_heap_shift
    maxstr_heap_push
    maxstr_heap_adjust_item
    maxstr_heap_adjust_top
    min_heapify
    min_heap_shift
    min_heap_push
    min_heap_adjust_item
    min_heap_adjust_top
    minstr_heapify
    minstr_heap_shift
    minstr_heap_push
    minstr_heap_adjust_item
    minstr_heap_adjust_top
);

{
    package Local::BigNumOnly;

    use overload
        '0+' => sub { ${$_[0]} },
        '""' => sub { ${$_[0]} },
        fallback => 1;

    sub new {
        my ($class, $value) = @_;
        return bless \$value, $class;
    }
}

{
    package Local::BigNumCmp;

    use overload
        '<=>' => sub {
            my ($left, $right, $swap) = @_;
            ($left, $right) = ($right, $left) if $swap;
            return ${$left} <=> ${$right};
        },
        '""' => sub { ${$_[0]} },
        fallback => 1;

    sub new {
        my ($class, $value) = @_;
        return bless \$value, $class;
    }
}

{
    package Local::BigStrCmp;

    use overload
        'cmp' => sub {
            my ($left, $right, $swap) = @_;
            ($left, $right) = ($right, $left) if $swap;
            return ${$left} cmp ${$right};
        },
        '""' => sub { ${$_[0]} },
        fallback => 1;

    sub new {
        my ($class, $value) = @_;
        return bless \$value, $class;
    }
}

my $nv_preserves_64bit_uv =
    ($Config{nvsize} * 8) >= 64
    && (~0 <= 9_007_199_254_740_992);

plan skip_all => 'needs UV values larger than NV can exactly represent'
    if $nv_preserves_64bit_uv;

my $big = ~0;
my @values = ($big - 1, $big, $big - 2, $big - 3, $big - 4);
my @expect_max = ($big, $big - 1, $big - 2, $big - 3, $big - 4);
my @expect_min = reverse @expect_max;

sub drain_max_num {
    my (@heap) = @_;
    my @got;
    push @got, 0 + max_heap_shift(@heap) while @heap;
    return @got;
}

sub drain_min_num {
    my (@heap) = @_;
    my @got;
    push @got, 0 + min_heap_shift(@heap) while @heap;
    return @got;
}

sub drain_max_str {
    my (@heap) = @_;
    my @got;
    push @got, '' . maxstr_heap_shift(@heap) while @heap;
    return @got;
}

sub drain_min_str {
    my (@heap) = @_;
    my @got;
    push @got, '' . minstr_heap_shift(@heap) while @heap;
    return @got;
}

sub find_idx {
    my ($heap, $want) = @_;
    for my $idx (0 .. $#$heap) {
        return $idx if "$heap->[$idx]" eq "$want";
    }
    die "value $want not found in heap";
}

{
    my @heap = map Local::BigNumOnly->new($_), @values;

    max_heapify(@heap);

    is_deeply(
        [ drain_max_num(@heap) ],
        \@expect_max,
        'max heap keeps overloaded large UVs in numeric order',



( run in 1.569 second using v1.01-cache-2.11-cpan-f0ff5d10edf )