stas 2003/11/04 10:22:53
Modified: t/response/TestPerl hash_attack.pm
Log:
Tels came up with an even faster hash function working U32.
Submitted by: Tels <[EMAIL PROTECTED]>
Revision Changes Path
1.3 +22 -0 modperl-2.0/t/response/TestPerl/hash_attack.pm
Index: hash_attack.pm
===================================================================
RCS file: /home/cvs/modperl-2.0/t/response/TestPerl/hash_attack.pm,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -u -r1.2 -r1.3
--- hash_attack.pm 3 Nov 2003 23:38:33 -0000 1.2
+++ hash_attack.pm 4 Nov 2003 18:22:53 -0000 1.3
@@ -114,6 +114,28 @@
# integer'). So we outsmart Perl and take modules 2*32 after each
# calculation, emulating overflows that happen in C.
sub hash {
+ my ($s) = @_;
+ my ($u, @c);
+ @c = split //, $s;
+ $u = 0;
+ for (@c) {
+ # (A % M) + (B % M) == (A + B) % M
+ # This works because '+' produces a NV, which is big enough to hold
+ # the intermidiate result. We only need the % before any "^" and "&"
+ # to get the result in the range for an I32.
+ # and << doesn't work on NV, so using 1 << 10
+ $u += ord;
+ $u += $u * (1 << 10); $u %= MASK_U32;
+ $u ^= $u >> 6;
+ }
+ $u += $u << 3; $u %= MASK_U32;
+ $u ^= $u >> 11; $u %= MASK_U32;
+ $u += $u << 15; $u %= MASK_U32;
+ $u;
+}
+
+# a bit slower but simpler version
+sub hash_original {
my $s = shift;
my @c = split //, $s;
my $u = 0;