pub fn splitmix64_finalize(z: u64) -> u64Expand description
splitmix64’s finalizer — the same function std/core’s mix64 computes.
std/core writes it in signed Nova with masked shifts, because Nova’s >>
on a negative Int sign-extends; on u64 here the plain form is the same
function. Its constants correspond: Nova’s -4658895280553007687 is
0xbf58476d1ce4e5b9 and -7723592293110705685 is 0x94d049bb133111eb.
This is LOAD-BEARING, not decoration. Map selects buckets with
hash & (cap - 1) – the low bits – and FNV-1a’s low bits barely depend on
its starting value: bit 0 of an FNV-1a result is bit 0 of the basis XOR the
parity of the input bytes’ low bits, so changing the basis flips bit 0
identically for both keys of a colliding pair and leaves the collision
standing. Measured, seeding alone left 30 of a constructed 48-key attack in
one bucket and moved only 66.7% of keys at capacity 8; with this finalizer
the same attack falls to 3 and 87.3% of keys move, against an ideal of
87.5%. The spec’s section 2 carries the method and the full figures.
pub for one reason: nova-driver’s async_end_to_end tests tie this
function to std/core’s mix64 by running Nova’s .hash() through the
real pipeline and comparing against this one, over a seed both sides read
from the same process-global OnceLock. The records have long said the two
compute the same function and nothing asserted it.
This is Rust-internal visibility and creates no Nova surface, which is
what distinguishes it from ADR 0005’s prohibition on publishing mix64.
That prohibition is about Nova’s namespace: publishing mix64 would make
its exact definition a compatibility surface and forecloses the freedom ADR
0005 reserves to replace its constants or rounds. Nothing here reaches a
Nova program, and mix64 stays module-private.