diff --git a/src/hash.rs b/src/hash.rs index de535d4..038316c 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -1,7 +1,9 @@ /// A fast seedable 32-bit hash function. pub fn hash_u32(mut n: u32, seed: u32) -> u32 { - n ^= 0xe6fe3beb; // So zero doesn't map to zero. - n ^= seed; + // We rotate the bits of `seed` so it's unlikely to interact with `n` + // in bad ways if they're both e.g. incrementing. The particular + // rotation constant used here isn't special. + n ^= seed.rotate_left(23); // From https://github.com/skeeto/hash-prospector n ^= n >> 16; @@ -10,15 +12,17 @@ pub fn hash_u32(mut n: u32, seed: u32) -> u32 { n = n.wrapping_mul(0xd35a2d97); n ^= n >> 15; - // We xor by `seed` again in case the first time cancelled out our - // "zero doesn't map to zero" precaution. - n ^ seed + // Xor by a random number so input zero doesn't map to output zero. + // The particular number used here isn't special. + n ^ 0xe6fe3beb } /// A fast seedable 64-bit hash function. pub fn hash_u64(mut n: u64, seed: u64) -> u64 { - n ^= 0x4acc3f27cc712c9d; // So zero doesn't map to zero. - n ^= seed; + // We rotate the bits of `seed` so it's unlikely to interact with `n` + // in bad ways if they're both e.g. incrementing. The particular + // rotation constant used here isn't special. + n ^= seed.rotate_left(47); // From https://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html n ^= n >> 30; @@ -27,9 +31,9 @@ pub fn hash_u64(mut n: u64, seed: u64) -> u64 { n = n.wrapping_mul(0x94d049bb133111eb); n ^= n >> 31; - // We xor by `seed` again in case the first time cancelled out our - // "zero doesn't map to zero" precaution. - n ^ seed + // Xor by a random number so input zero doesn't map to output zero. + // The particular number used here isn't special. + n ^ 0x4acc3f27cc712c9d } /// Returns a random float in [0, 1] based on 'n' and a seed.