///|
// SplitMix64 finalizer. Integer operations intentionally wrap modulo 2^64.
fn mix(value : UInt64) -> UInt64 {
let a = (value ^ (value >> 30)) * 0xbf58476d1ce4e5b9UL
let b = (a ^ (a >> 27)) * 0x94d049bb133111ebUL
b ^ (b >> 31)
}
///|
fn check_key(key : UInt64, seed : UInt64) -> UInt64 {
mix(key ^ seed ^ 0xd6e8feb86659fd93UL)
}
///|
fn positions(key : UInt64, config : Config) -> Array[Int32] {
let salts = [0x9e3779b97f4a7c15UL, 0x3c6ef372fe94f82aUL, 0xdaa66d2c7ddef743UL]
Array::makei(3, fn(i) {
(mix(key ^ config.seed ^ salts[i]) % config.width.to_uint64()).to_int() +
i * config.width
})
}
///|
fn empty_fingerprint() -> Fingerprint {
{ count: 0, sum: 0UL, xor: 0UL, }
}
///|
fn fingerprint_add(fp : Fingerprint, key : UInt64, sign : Int32) -> Fingerprint {
let h = mix(key ^ 0xa0761d6478bd642fUL)
{
count: fp.count + sign,
sum: if sign == 1 {
fp.sum + h
} else {
fp.sum - h
},
xor: fp.xor ^ mix(key ^ 0xe7037ed1a0b428dbUL),
}
}