# `jamhash_u64`
`jamhash_u64` is the stable algorithm exposed as `jamhash::jamhash_u64`. It
accepts any `u64` and returns a non-cryptographic 64-bit hash.
## Formula
For 64-bit values `a` and `b`, define:
```text
fold(a, b) = low64(u128(a) * u128(b)) XOR high64(u128(a) * u128(b))
```
The complete algorithm is:
```text
C1 = 0xb8e1afed6a267e96
C2 = 0x082efa98ec4e6c89
p1 = rotate_left(input, 16)
p2 = rotate_left(input, 48)
f1 = fold(p1, C1)
f2 = fold(p2, C2)
output = fold(f1, f2)
```
There is no seed, byte conversion, final XOR, or output remapping.
`jamhash_u64(0) == 0` is intentional and stable.
## Test vectors
| `0x0000000000000000` | `0x0000000000000000` |
| `0x0000000000000001` | `0x2d673a90c3c14c02` |
| `0x0000006f93b4b1bc` | `0xaf47a96184814793` |
| `0xffffffffffffffff` | `0xffffffffffffffff` |
These vectors are release-gated by `tests/public_api.rs`.
## Packed DNA input
The primary input is a canonical DNA kmer packed into two bits per base. A
`u64` holds at most 32 bases. Encoding, canonicalization, orientation selection,
invalid-base handling, and clearing unused high bits are caller responsibilities.
The documented DNA convention uses `A=00`, `C=01`, `G=10`, `T=11`,
left-to-right packing, and `min(forward, reverse_complement)` canonicalization.
Current `jam-rs` screening paths exclude hash zero before applying their
FracMinHash threshold.
## Compatibility
Patch and minor releases preserve every `u64` input/output mapping. Changing a
constant, rotation, multiplication, folding step, zero behavior, or output
mapping is an explicit compatibility break.
`jamhash_bytes` and `JamHasher` are separate algorithms and are not covered by
this mapping promise. Their paths for four bytes and longer use native-endian
reads. Their outputs are therefore architecture-local and must not be used as
persistent or exchanged identifiers.
`JamHasher` hashes a sequence of non-empty write frames. Frame boundaries affect
the result, empty writes are no-ops, and one frame is not equivalent to
`jamhash_bytes`.