1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
|
// +build noasm !amd64 gccgo
package metro
import (
"encoding/binary"
"math/bits"
)
func Hash64(buffer []byte, seed uint64) uint64 {
const (
k0 = 0xD6D018F5
k1 = 0xA2AA033B
k2 = 0x62992FC1
k3 = 0x30BC5B29
)
ptr := buffer
hash := (seed + k2) * k0
if len(ptr) >= 32 {
v0, v1, v2, v3 := hash, hash, hash, hash
for len(ptr) >= 32 {
v0 += binary.LittleEndian.Uint64(ptr[:8]) * k0
v0 = bits.RotateLeft64(v0, -29) + v2
v1 += binary.LittleEndian.Uint64(ptr[8:16]) * k1
v1 = bits.RotateLeft64(v1, -29) + v3
v2 += binary.LittleEndian.Uint64(ptr[16:24]) * k2
v2 = bits.RotateLeft64(v2, -29) + v0
v3 += binary.LittleEndian.Uint64(ptr[24:32]) * k3
v3 = bits.RotateLeft64(v3, -29) + v1
ptr = ptr[32:]
}
v2 ^= bits.RotateLeft64(((v0+v3)*k0)+v1, -37) * k1
v3 ^= bits.RotateLeft64(((v1+v2)*k1)+v0, -37) * k0
v0 ^= bits.RotateLeft64(((v0+v2)*k0)+v3, -37) * k1
v1 ^= bits.RotateLeft64(((v1+v3)*k1)+v2, -37) * k0
hash += v0 ^ v1
}
if len(ptr) >= 16 {
v0 := hash + (binary.LittleEndian.Uint64(ptr[:8]) * k2)
v0 = bits.RotateLeft64(v0, -29) * k3
v1 := hash + (binary.LittleEndian.Uint64(ptr[8:16]) * k2)
v1 = bits.RotateLeft64(v1, -29) * k3
v0 ^= bits.RotateLeft64(v0*k0, -21) + v1
v1 ^= bits.RotateLeft64(v1*k3, -21) + v0
hash += v1
ptr = ptr[16:]
}
if len(ptr) >= 8 {
hash += binary.LittleEndian.Uint64(ptr[:8]) * k3
ptr = ptr[8:]
hash ^= bits.RotateLeft64(hash, -55) * k1
}
if len(ptr) >= 4 {
hash += uint64(binary.LittleEndian.Uint32(ptr[:4])) * k3
hash ^= bits.RotateLeft64(hash, -26) * k1
ptr = ptr[4:]
}
if len(ptr) >= 2 {
hash += uint64(binary.LittleEndian.Uint16(ptr[:2])) * k3
ptr = ptr[2:]
hash ^= bits.RotateLeft64(hash, -48) * k1
}
if len(ptr) >= 1 {
hash += uint64(ptr[0]) * k3
hash ^= bits.RotateLeft64(hash, -37) * k1
}
hash ^= bits.RotateLeft64(hash, -28)
hash *= k0
hash ^= bits.RotateLeft64(hash, -29)
return hash
}
func Hash64Str(buffer string, seed uint64) uint64 {
return Hash64([]byte(buffer), seed)
}
|