# Add $value to sorted @array, if it's not already there.
my $idx = binsearch { $a <=> $b } $value, @array;
splice(@array, ~$idx, 0, $value) if $idx < 0;
####
sub binsearch(&$\@) {
my $compare = $_[0];
#my $value = $_[1];
my $array = $_[2];
my $i = 0;
my $j = $#$array;
return $j if $j == -1;
my $ap = do { no strict 'refs'; \*{caller().'::a'} }; local *$ap;
my $bp = do { no strict 'refs'; \*{caller().'::b'} }; local *$bp;
*$ap = \($_[1]);
for (;;) {
my $k = int(($i+$j)/2);
*$bp = \($array->[$k]);
my $cmp = $compare->()
or return $k;
if ($cmp < 0) {
$j = $k-1;
return _unsigned_to_signed(~$k) if $i > $j;
} else {
$i = $k+1;
return _unsigned_to_signed(~$i) if $i > $j;
}
}
}
sub _unsigned_to_signed { unpack('j', pack('J', $_[0])) }
####
# Add $value to sorted @array, if it's not already there.
my $idx = binsearch { $value <=> $::_ } @array;
splice(@array, ~$idx, 0, $value) if $idx < 0;
####
sub binsearch(&\@) {
my ($compare, $array) = @_;
my $i = 0;
my $j = $#$array;
return $j if $j == -1;
for (;;) {
my $k = int(($i+$j)/2);
my $cmp;
$cmp = $compare->() for $array->[$k];
return $k if !$cmp;
if ($cmp < 0) {
$j = $k-1;
return _unsigned_to_signed(~$k) if $i > $j;
} else {
$i = $k+1;
return _unsigned_to_signed(~$i) if $i > $j;
}
}
}
sub _unsigned_to_signed { unpack('j', pack('J', $_[0])) }