Modern non-cryptographic 32- and 64-bit valued hash functions, for example, lookup3, MurmurHash3 and CityHash, have quite sophisticated loops, each iteration of which include many multiplications, XORs and rotates. Why this is needed, since there are good avalanche procedures (32 -> 32 and 64 -> 64 bits), which mix the bits effectively randomly. So, even if this simple loop:
hash = seed;
while (input_len >= 8)
hash = hash * prime + fetch_8_input_bytes();
... do something for rest 0..7 bytes of input
produce whatever flawed, biased results for similar input (or a certain subset of input), finalizing avalanche:
return good_avalanche(hash)
"fixes" this.
The last deal is direct collisions, but they are often not so important, assuming hash function produce decently little collisions. I think the above multimplication loop does.
What I'm missing?