// xxHash32, required by the LZ4 frame format for header and content
// checksums.
///|
let xxh32_primes : (UInt, UInt, UInt, UInt, UInt) = (
2654435761, 2246822519, 3266489917, 668265263, 374761393,
)
///|
fn xxh32_round(acc : UInt, input : UInt) -> UInt {
let (p1, p2, _, _, _) = xxh32_primes
let acc = acc + input * p2
let acc = (acc << 13) | (acc >> 19)
acc * p1
}
///|
fn read_le32(data : BytesView, at : Int) -> UInt {
data[at].to_uint() |
(data[at + 1].to_uint() << 8) |
(data[at + 2].to_uint() << 16) |
(data[at + 3].to_uint() << 24)
}
///|
/// Compute xxHash32 of `data` with seed 0.
pub fn xxhash32(data : BytesView) -> UInt {
let (p1, p2, p3, p4, p5) = xxh32_primes
let len = data.length()
let mut offset = 0
let mut acc : UInt = 0
if len >= 16 {
let mut acc1 : UInt = p1 + p2
let mut acc2 : UInt = p2
let mut acc3 : UInt = 0
let mut acc4 : UInt = 0 - p1
while offset + 16 <= len {
acc1 = xxh32_round(acc1, read_le32(data, offset))
acc2 = xxh32_round(acc2, read_le32(data, offset + 4))
acc3 = xxh32_round(acc3, read_le32(data, offset + 8))
acc4 = xxh32_round(acc4, read_le32(data, offset + 12))
offset += 16
}
acc = ((acc1 << 1) | (acc1 >> 31)) +
((acc2 << 7) | (acc2 >> 25)) +
((acc3 << 12) | (acc3 >> 20)) +
((acc4 << 18) | (acc4 >> 14))
} else {
acc = p5
}
acc += len.reinterpret_as_uint()
while offset + 4 <= len {
acc += read_le32(data, offset) * p3
acc = ((acc << 17) | (acc >> 15)) * p4
offset += 4
}
while offset < len {
acc += data[offset].to_uint() * p5
acc = ((acc << 11) | (acc >> 21)) * p1
offset += 1
}
acc = acc ^ (acc >> 15)
acc = acc * p2
acc = acc ^ (acc >> 13)
acc = acc * p3
acc ^ (acc >> 16)
}