/usr/local/CPAN/Heap-Simple-Perl/Heap/Simple/Wrapper.pm
package Heap::Simple::Wrapper;
$VERSION = "0.04";
use strict;
sub _ELEMENTS_PREPARE {
return "";
}
sub _QUICK_KEY {
return shift->_KEY(@_);
}
sub _KEY {
return $_[1] . "->[0]";
}
sub _VALUE {
return $_[1] . "->[1]";
}
sub _WRAPPER {
return "[$_[1], $_[2]]";
}
sub insert {
my $heap = shift;
Carp::croak "Wrapped class with noop key" if $heap->_KEY("") eq "";
$heap->_make('sub insert {
my $heap = shift;
_REAL_PREPARE()
_CANT_DIE(
_MAX_COUNT(my $available = _THE_MAX_COUNT()-$#$heap;)
if (@_ > 1 _MAX_COUNT(&& $available > 1)) {
my $first = @$heap;
my $i = push(@$heap, map _WRAPPER(_REAL_KEY($_), $_), _MAX_COUNT(splice(@_, 0, $available), @_))-1;
my @todo = reverse $first/2..$#$heap/2;
while (my $j = shift @todo) {
my $value = $heap->[$j];
my $key = _KEY($value);
my $l = $j*2;
while ($l < $i) {
if (_SMALLER(_KEY($heap->[$l]), $key)) {
$l++ if _SMALLER(_KEY($heap->[$l+1]), _KEY($heap->[$l]));
} elsif (!(_SMALLER(_KEY($heap->[++$l]), $key))) {
$l--;
last;
}
$heap->[$l >> 1] = $heap->[$l];
$l *= 2;
}
if ($l == $i && _SMALLER(_KEY($heap->[$l]), $key)) {
$heap->[$l >> 1] = $heap->[$l];
} else {
$l >>= 1;
}
if ($j != $l) {
$heap->[$l] = $value;
$l >>= 1;
push(@todo, $l) if !@todo || $l < $todo[0];
}
}
return _MAX_COUNT(unless @_);
})
for my $value (@_) {
my $key = _REAL_KEY($value);
my $i = @$heap;
_MAX_COUNT(if ($i > _THE_MAX_COUNT()) {
next unless _SMALLER(_KEY($heap->[1]), $key);
$i--;
my $l = 2;
_CAN_DIE(my $min = $heap->[1]; eval {)
while ($l < $i) {
if (_SMALLER(_KEY($heap->[$l]), $key)) {
$l++ if _SMALLER(_KEY($heap->[$l+1]), _KEY($heap->[$l]));
} elsif (!(_SMALLER(_KEY($heap->[++$l]), $key))) {
$l--;
last;
}
$heap->[$l >> 1] = $heap->[$l];
$l *= 2;
}
if ($l == $i && _SMALLER(_KEY($heap->[$l]), $key)) {
$heap->[$l >> 1] = $heap->[$l];
$l *= 2;
}
_CAN_DIE( 1
} || $heap->_e_recover($l, $min);)
$heap->[$l >> 1] = _WRAPPER($key, $value);
next;})
_CAN_DIE(eval {)
$i = $i >> 1 while
$i > 1 && _SMALLER($key, _KEY(($heap->[$i] = $heap->[$i >> 1])));
_CAN_DIE(1} || $heap->_i_recover($i);)
$heap->[$i] = _WRAPPER($key, $value);
}}');
$heap->insert(@_);
}
sub key_insert {
my $heap = shift;
$heap->_make('sub key_insert {
my $heap = shift;
_PREPARE()
while (@_) {
my $key = shift;
my $i = @$heap;
_MAX_COUNT(if ($i > _THE_MAX_COUNT()) {
shift _COMMA() next unless _SMALLER(_KEY($heap->[1]), $key);
$i--;
my $l = 2;
_CAN_DIE(my $min = $heap->[1]; eval {)
while ($l < $i) {
if (_SMALLER(_KEY($heap->[$l]), $key)) {
$l++ if _SMALLER(_KEY($heap->[$l+1]), _KEY($heap->[$l]));
} elsif (!(_SMALLER(_KEY($heap->[++$l]), $key))) {
$l--;
last;
}
$heap->[$l >> 1] = $heap->[$l];
$l *= 2;
}
if ($l == $i && _SMALLER(_KEY($heap->[$l]), $key)) {
$heap->[$l >> 1] = $heap->[$l];
$l *= 2;
}
_CAN_DIE( 1
} || $heap->_e_recover($l, $min);)
$heap->[$l >> 1] = _WRAPPER($key, shift);
next;})
_CAN_DIE(eval {)
$i = $i >> 1 while
$i > 1 && _SMALLER($key, _KEY(($heap->[$i] = $heap->[$i >> 1])));
_CAN_DIE(1} || $heap->_i_recover($i);)
$heap->[$i] = _WRAPPER($key, shift);
}}');
$heap->key_insert(@_);
}
sub _key_insert {
my $heap = shift;
$heap->_make('sub _key_insert {
my $heap = shift;
_PREPARE()
for my $pair (@_) {
my $key = $pair->[0];
my $i = @$heap;
_MAX_COUNT(if ($i > _THE_MAX_COUNT()) {
next unless _SMALLER(_KEY($heap->[1]), $key);
$i--;
my $l = 2;
_CAN_DIE(my $min = $heap->[1]; eval {)
while ($l < $i) {
if (_SMALLER(_KEY($heap->[$l]), $key)) {
$l++ if _SMALLER(_KEY($heap->[$l+1]), _KEY($heap->[$l]));
} elsif (!(_SMALLER(_KEY($heap->[++$l]), $key))) {
$l--;
last;
}
$heap->[$l >> 1] = $heap->[$l];
$l *= 2;
}
if ($l == $i && _SMALLER(_KEY($heap->[$l]), $key)) {
$heap->[$l >> 1] = $heap->[$l];
$l *= 2;
}
_CAN_DIE( 1
} || $heap->_e_recover($l, $min);)
$heap->[$l >> 1] = $pair;
next;})
_CAN_DIE(eval {)
$i = $i >> 1 while
$i > 1 && _SMALLER($key, _KEY(($heap->[$i] = $heap->[$i >> 1])));
_CAN_DIE(1} || $heap->_i_recover($i);)
$heap->[$i] = $pair;
}}');
$heap->_key_insert(@_);
}
sub _key_absorb {
my ($from, $to) = @_;
Carp::croak "Self absorption" if $from == $to;
if (@$from > 2 && !$to->can_die) {
$to->_key_insert(@$from[1..$#$from]);
$#$from = 0;
return;
}
while (@$from > 1) {
$to->_key_insert($from->[-1]);
pop @$from;
}
}
sub wrapped {
return 1;
}
1;