Faster lk hash for the sobol sampler.

This gets about the same quality as the previous hash, but in
much fewer operations.
This commit is contained in:
Nathan Vegdahl 2020-04-24 10:47:53 +09:00
parent 2c68e18bd6
commit 78b5cf4c53

View File

@ -67,24 +67,21 @@ fn lk_scramble(mut n: u32, scramble: u32) -> u32 {
// The basic idea is that we're running a special kind of hash function // The basic idea is that we're running a special kind of hash function
// that only allows avalanche to happen upwards (i.e. a bit is only // that only allows avalanche to happen upwards (i.e. a bit is only
// affected by the bits lower than it). This is achieved by only doing // affected by the bits lower than it). This is achieved by only doing
// mixing via operations that also adhere to that property, such as // mixing via operations that also adhere to that property.
// multiplication by even numbers.
// //
// Normally this would be considered a poor hash function, because normally // Normally this would be considered a poor hash function, because normally
// you want all bits to have an equal chance of affecting all other bits. // you want all bits to have an equal chance of affecting all other bits.
// But in this case that only-upward behavior is exactly what we want, // But in this case that only-upward behavior is exactly what we want,
// because it ends up being equivalent to Owen scrambling on // because it ends up being equivalent to Owen scrambling on
// reverse-ordered bits. // reverse-ordered bits.
//
// The permutation constants here were selected through an optimization
// process to maximize low-bias avalanche between bits.
const PERMS: [u32; 3] = [0x97b756bc, 0x4b0a8a12, 0x75c77e36];
n = n.wrapping_add(hash(scramble, 2)); n = n.wrapping_add(hash(scramble, 2));
for &p in PERMS.iter() {
n ^= n.wrapping_mul(p); n ^= 0xdc967795;
n = n.wrapping_add(n << 1); n = n.wrapping_mul(0x97b754b7);
} n ^= 0x866350b1;
n = n.wrapping_mul(0x9e3779cd);
n n
} }