sub straight_merge { my ($array)=(@_); my $buffer=[]; $#$buffer=$#$array; my $len=1; # starts with "runs" of length 1 while ($len<@$array) { my ($al,$ar)=(0,$#$array); my ($bl,$br)=(-1,scalar @$array); my $dir=1; my ($lremain,$rremain)=($len,$len); # how many elements from each side PASS: while ($al<=$ar) { if ($array->[$al] < $array->[$ar]) { $bl+=$dir; $buffer->[$bl]=$array->[$al]; $al++; next if --$lremain>0; while (1) { $bl+=$dir; last PASS if $bl==$br; $buffer->[$bl]=$array->[$ar]; $ar--; last unless --$rremain; } } else { $bl+=$dir; $buffer->[$bl]=$array->[$ar]; $ar--; $rremain--; next if $rremain>0; while (1) { $bl+=$dir; last PASS if $bl==$br; $buffer->[$bl]=$array->[$al]; $al++; last unless --$lremain; } } #Switch sides ($lremain,$rremain)=($len,$len); $dir=-$dir; ($bl,$br)=($br,$bl); if ($ar-$al<$len) { # do a partial copy while (1) { $bl+=$dir; last PASS if $bl==$br; $buffer->[$bl]=$array->[$al]; $al++; } } #eof PASS } #flip the buffers $len+=$len; last if $len>@$array; ($array,$buffer)=($buffer,$array); } unless ($array==$_[0]) { #do a copy @$array=@$buffer; } }