in reply to Re: About the expected number of comparisons for n keys into k buckets
in thread About the expected number of comparisons for n keys into k buckets

To the best of my knowledge, the Perl hash algorithm is:
unsigned int hash = 0; while (*s) /* s is pointer to string */ hash = hash * 33 + *s++; return hash;
Except that it isn't anymore. The above was the case for 5.6.*, but it has changed in 5.8.0, and then again in 5.8.1. Since 5.8, it is doing the shifts you seem to dislike. From hv.h:
/* 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) */ /* The use of a temporary pointer and the casting games * is needed to serve the dual purposes of * (a) the hashed data being interpreted as "unsigned char" (new since + 5.8, * a "char" can be either signed or unsigned, depending on the com +piler) * (b) catering for old code that uses a "char" * * The "hash seed" feature was added in Perl 5.8.1 to perturb the resu +lts * to avoid "algorithmic complexity attacks". * * If USE_HASH_SEED is defined, hash randomisation is done by default * If USE_HASH_SEED_EXPLICIT is defined, hash randomisation is done * only if the environment variable PERL_HASH_SEED is set. * For maximal control, one can define PERL_HASH_SEED. * (see also perl.c:perl_parse()). */ #ifndef PERL_HASH_SEED # if defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT) # define PERL_HASH_SEED PL_hash_seed # else # define PERL_HASH_SEED 0 # endif #endif #define PERL_HASH(hash,str,len) PERL_HASH_INTERNAL_(hash,str,len,0) /* Only hv.c and mod_perl should be doing this. */ #ifdef PERL_HASH_INTERNAL_ACCESS #define PERL_HASH_INTERNAL(hash,str,len) PERL_HASH_INTERNAL_(hash,str, +len,1) #endif /* Common base for PERL_HASH and PERL_HASH_INTERNAL that parameterises * the source of the seed. Not for direct use outside of hv.c. */ #define PERL_HASH_INTERNAL_(hash,str,len,internal) \ STMT_START { \ register const char * const s_PeRlHaSh_tmp = str; \ register const unsigned char *s_PeRlHaSh = (const unsigned cha +r *)s_PeRl HaSh_tmp; \ register I32 i_PeRlHaSh = len; \ register U32 hash_PeRlHaSh = (internal ? PL_rehash_seed : PERL +_HASH_SEED ); \ 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