This was my final version of the algorithm. It benchmarked quickest of all the versions (7) that I tried, but I haven't found a simple way of verifying that it's a faithful re-implementation of the C version.
use constant A => 0;
use constant B => 1;
use constant C => 2;
sub mix ($$$) {
use integer;
$_[A] -= $_[B]; $_[A] -= $_[C]; $_[A] ^= ($_[C]>>13);
$_[B] -= $_[C]; $_[B] -= $_[A]; $_[B] ^= ($_[A]<< 8);
$_[C] -= $_[A]; $_[C] -= $_[B]; $_[C] ^= ($_[B]>>13);
$_[A] -= $_[B]; $_[A] -= $_[C]; $_[A] ^= ($_[C]>>12);
$_[B] -= $_[C]; $_[B] -= $_[A]; $_[B] ^= ($_[A]<<16);
$_[C] -= $_[A]; $_[C] -= $_[B]; $_[C] ^= ($_[B]>> 5);
$_[A] -= $_[B]; $_[A] -= $_[C]; $_[A] ^= ($_[C]>> 3);
$_[B] -= $_[C]; $_[B] -= $_[A]; $_[B] ^= ($_[A]<<10);
$_[C] -= $_[A]; $_[C] -= $_[B]; $_[C] ^= ($_[B]>>15);
}
use constant GOLDEN_RATIO => 0x9e3779b9;
use constant INITHASH => 2;
sub hash {
use integer;
my($a,$b,$c) = (GOLDEN_RATIO, GOLDEN_RATIO, $_[INITHASH]);
my ($p, $len) = (0, length $_[KEY]);
do {
my($x,$y,$z) = unpack 'V3', substr($_[KEY] . (chr(0)x11), $p,
+12);
mix($a += $x, $b += $y, $c += $z + $len);
$p+=12;
} while $p <= $len;
return $c;
}
Examine what is said, not who speaks.
1) When a distinguished but elderly scientist states that something is possible, he is almost certainly right. When he states that something is impossible, he is very probably wrong.
2) The only way of discovering the limits of the possible is to venture a little way past them into the impossible
3) Any sufficiently advanced technology is indistinguishable from magic.
Arthur C. Clarke.
|