in reply to falling through cases?

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.

Replies are listed 'Best First'.
Re: Re: falling through cases?
by John M. Dlugosz (Monsignor) on Feb 28, 2003 at 07:18 UTC
    Hm? Unless I'm missing something, that leaves out the part that's relevant to this thread of how to best code the case fall-through thing in Perl.

    If the input is not a multiple of 12 bytes, it needs to do this (from the original C version):

    switch(len) /* all the case statements fall through */ { case 11: c+=((ub4)k[10]<<24); case 10: c+=((ub4)k[9]<<16); case 9 : c+=((ub4)k[8]<<8); /* the first byte of c is reserved for the length */ case 8 : b+=((ub4)k[7]<<24); case 7 : b+=((ub4)k[6]<<16); case 6 : b+=((ub4)k[5]<<8); case 5 : b+=k[4]; case 4 : a+=((ub4)k[3]<<24); case 3 : a+=((ub4)k[2]<<16); case 2 : a+=((ub4)k[1]<<8); case 1 : a+=k[0]; /* case 0: nothing left to add */ } mix(a,b,c);
    And you left out the $c += $length (using 32-bit integer overflow).

    Hmm again... or is the . (chr(0)x11), $p, 12 taking the place of that, to fill out the last "gulp"?

    So even if that's not quite right, your answer to how to write such a switch statement is "don't. a more natural way (at a higher level in the algorithm) in Perl suggests itself and prevents the need".

    Back to the other thread: thanks for sharing fastest implementation of the mix() function you found in pure Perl.