};
/* hash a key */
+/* FYI: This is the "One-at-a-Time" algorithm by Bob Jenkins */
+/* from requirements by Colin Plumb. */
+/* (http://burtleburtle.net/bob/hash/doobs.html) */
#define PERL_HASH(hash,str,len) \
STMT_START { \
register const char *s_PeRlHaSh = str; \
register I32 i_PeRlHaSh = len; \
register U32 hash_PeRlHaSh = 0; \
- while (i_PeRlHaSh--) \
- hash_PeRlHaSh = hash_PeRlHaSh * 33 + *s_PeRlHaSh++; \
- (hash) = hash_PeRlHaSh + (hash_PeRlHaSh>>5); \
+ while (i_PeRlHaSh--) { \
+ hash_PeRlHaSh += *s_PeRlHaSh++; \
+ hash_PeRlHaSh += (hash_PeRlHaSh << 10); \
+ hash_PeRlHaSh ^= (hash_PeRlHaSh >> 6); \
+ } \
+ hash_PeRlHaSh += (hash_PeRlHaSh << 3); \
+ hash_PeRlHaSh ^= (hash_PeRlHaSh >> 11); \
+ (hash) = (hash_PeRlHaSh += (hash_PeRlHaSh << 15)); \
} STMT_END
/*
the interface was a mistake. Sorry about that. For similar
functionality, see pack('U0', ...) and pack('C0', ...).
+=item *
+
+Although "you shouldn't do that", it was possible to write code that
+depends on Perl's hashed key order (Data::Dumper does this). The new
+algorithm "One-at-a-Time" produces a different hashed key order.
+More details are in L<perldelta/Performance Enhancements>.
+
=back
=head1 Core Enhancements
and that sort() is now stable (meaning that elements with identical
keys will stay ordered as they were before the sort).
+=item *
+
+Hashes now use Bob Jenkins "One-at-a-Time" hashing key algorithm
+(http://burtleburtle.net/bob/hash/doobs.html).
+This algorithm is reasonably fast while producing a much better spread
+of values. Hash values output from the algorithm on a hash of all
+3-char printable ASCII keys comes much closer to passing the DIEHARD
+random number generation tests. According to perlbench, this change
+has not affected the overall speed of Perl.
+
+
=back
=head1 Installation and Configuration Improvements
#$a = [
# 1,
# {
-# 'a' => $a,
-# 'b' => $a->[1],
# 'c' => [
# 'c'
-# ]
+# ],
+# 'a' => $a,
+# 'b' => $a->[1]
# },
# $a->[1]{'c'}
# ];
#@a = (
# 1,
# {
-# 'a' => [],
-# 'b' => {},
# 'c' => [
# 'c'
-# ]
+# ],
+# 'a' => [],
+# 'b' => {}
# },
# []
# );
##
$WANT = <<'EOT';
#%b = (
+# 'c' => [
+# 'c'
+# ],
# 'a' => [
# 1,
# {},
-# [
-# 'c'
-# ]
+# []
# ],
-# 'b' => {},
-# 'c' => []
+# 'b' => {}
# );
#$b{'a'}[1] = \%b;
+#$b{'a'}[2] = $b{'c'};
#$b{'b'} = \%b;
-#$b{'c'} = $b{'a'}[2];
#$a = $b{'a'};
EOT
#$a = [
# 1,
# {
+# 'c' => [],
# 'a' => [],
-# 'b' => {},
-# 'c' => []
+# 'b' => {}
# },
# []
#];
+#$a->[1]{'c'} = \@c;
#$a->[1]{'a'} = $a;
#$a->[1]{'b'} = $a->[1];
-#$a->[1]{'c'} = \@c;
#$a->[2] = \@c;
#$b = $a->[1];
EOT
# 1,
# #1
# {
-# a => $a,
-# b => $a->[1],
# c => [
# #0
# 'c'
-# ]
+# ],
+# a => $a,
+# b => $a->[1]
# },
# #2
# $a->[1]{c}
#$VAR1 = [
# 1,
# {
-# 'a' => [],
-# 'b' => {},
# 'c' => [
# 'c'
-# ]
+# ],
+# 'a' => [],
+# 'b' => {}
# },
# []
#];
#[
# 1,
# {
-# a => $VAR1,
-# b => $VAR1->[1],
# c => [
# 'c'
-# ]
+# ],
+# a => $VAR1,
+# b => $VAR1->[1]
# },
# $VAR1->[1]{c}
#]
##
$WANT = <<'EOT';
#$VAR1 = {
-# "abc\0'\efg" => "mno\0",
-# "reftest" => \\1
+# "reftest" => \\1,
+# "abc\0'\efg" => "mno\0"
#};
EOT
$WANT = <<"EOT";
#\$VAR1 = {
-# 'abc\0\\'\efg' => 'mno\0',
-# 'reftest' => \\\\1
+# 'reftest' => \\\\1,
+# 'abc\0\\'\efg' => 'mno\0'
#};
EOT
# do{my $o},
# #2
# {
+# 'c' => [],
# 'a' => 1,
# 'b' => do{my $o},
-# 'c' => [],
# 'd' => {}
# }
# ];
#*::foo{ARRAY}->[1] = $foo;
-#*::foo{ARRAY}->[2]{'b'} = *::foo{SCALAR};
#*::foo{ARRAY}->[2]{'c'} = *::foo{ARRAY};
+#*::foo{ARRAY}->[2]{'b'} = *::foo{SCALAR};
#*::foo{ARRAY}->[2]{'d'} = *::foo{ARRAY}->[2];
#*::foo = *::foo{ARRAY}->[2];
#@bar = @{*::foo{ARRAY}};
# -10,
# do{my $o},
# {
+# 'c' => [],
# 'a' => 1,
# 'b' => do{my $o},
-# 'c' => [],
# 'd' => {}
# }
#];
#*::foo{ARRAY}->[1] = $foo;
-#*::foo{ARRAY}->[2]{'b'} = *::foo{SCALAR};
#*::foo{ARRAY}->[2]{'c'} = *::foo{ARRAY};
+#*::foo{ARRAY}->[2]{'b'} = *::foo{SCALAR};
#*::foo{ARRAY}->[2]{'d'} = *::foo{ARRAY}->[2];
#*::foo = *::foo{ARRAY}->[2];
#$bar = *::foo{ARRAY};
#*::foo = \5;
#*::foo = \@bar;
#*::foo = {
+# 'c' => [],
# 'a' => 1,
# 'b' => do{my $o},
-# 'c' => [],
# 'd' => {}
#};
-#*::foo{HASH}->{'b'} = *::foo{SCALAR};
#*::foo{HASH}->{'c'} = \@bar;
+#*::foo{HASH}->{'b'} = *::foo{SCALAR};
#*::foo{HASH}->{'d'} = *::foo{HASH};
#$bar[2] = *::foo{HASH};
#%baz = %{*::foo{HASH}};
#*::foo = \5;
#*::foo = $bar;
#*::foo = {
+# 'c' => [],
# 'a' => 1,
# 'b' => do{my $o},
-# 'c' => [],
# 'd' => {}
#};
-#*::foo{HASH}->{'b'} = *::foo{SCALAR};
#*::foo{HASH}->{'c'} = $bar;
+#*::foo{HASH}->{'b'} = *::foo{SCALAR};
#*::foo{HASH}->{'d'} = *::foo{HASH};
#$bar->[2] = *::foo{HASH};
#$baz = *::foo{HASH};
# -10,
# $foo,
# {
+# c => \@bar,
# a => 1,
# b => \5,
-# c => \@bar,
# d => $bar[2]
# }
#);
# -10,
# $foo,
# {
+# c => $bar,
# a => 1,
# b => \5,
-# c => $bar,
# d => $bar->[2]
# }
#];
##
$WANT = <<'EOT';
#%kennels = (
-# First => \'Fido',
-# Second => \'Wags'
+# Second => \'Wags',
+# First => \'Fido'
#);
#@dogs = (
# ${$kennels{First}},
##
$WANT = <<'EOT';
#%kennels = (
-# First => \'Fido',
-# Second => \'Wags'
+# Second => \'Wags',
+# First => \'Fido'
#);
#@dogs = (
# ${$kennels{First}},
# 'Fido',
# 'Wags',
# {
-# First => \$dogs[0],
-# Second => \$dogs[1]
+# Second => \$dogs[1],
+# First => \$dogs[0]
# }
#);
#%kennels = %{$dogs[2]};
# 'Fido',
# 'Wags',
# {
-# First => \'Fido',
-# Second => \'Wags'
+# Second => \'Wags',
+# First => \'Fido'
# }
#);
#%kennels = (
-# First => \'Fido',
-# Second => \'Wags'
+# Second => \'Wags',
+# First => \'Fido'
#);
EOT
use warnings 'once' ;
$z = 3 ;
EXPECT
-Name "main::x" used only once: possible typo at - line 4.
Name "main::z" used only once: possible typo at - line 6.
+Name "main::x" used only once: possible typo at - line 4.
########
-X
# perl.c