2023-07-23 00:46:39 +02:00

51 lines
1.1 KiB
Go

package hash
import (
"unsafe"
)
// Bytes hashes the given byte slice.
func Bytes(in []byte) uint64 {
return add(0, in)
}
func add(x uint64, in []byte) uint64 {
var i int
// Cache lines on modern processors are 64 bytes long.
// A single uint64 consumes 64 bits (8 bytes).
// That means we should read 8 uint64 at a time.
for ; i < len(in)-63; i += 64 {
words := (*[8]uint64)(unsafe.Pointer(&in[i]))
x = mix(x, words[0])
x = mix(x, words[1])
x = mix(x, words[2])
x = mix(x, words[3])
x = mix(x, words[4])
x = mix(x, words[5])
x = mix(x, words[6])
x = mix(x, words[7])
}
// While we have at least 8 bytes left, convert them to uint64.
for ; i < len(in)-7; i += 8 {
word := *(*uint64)(unsafe.Pointer(&in[i]))
x = mix(x, word)
}
// Hash the remaining bytes.
for ; i < len(in); i++ {
x = mix(x, uint64(in[i]))
}
// This helps to avoid clashes between different lengths
// of all-zero bytes by making the data length significant.
x = mix(x, uint64(len(in)))
return x
}
func mix(x uint64, b uint64) uint64 {
return (x + b) * 0x50003
}