mirror of
https://github.com/iLoveElysia/openbilibili.git
synced 2026-03-14 05:46:26 -05:00
134 lines
2.2 KiB
Go
134 lines
2.2 KiB
Go
package murmur3
|
|
|
|
import (
|
|
"unsafe"
|
|
)
|
|
|
|
const (
|
|
c1_128 = 0x87c37b91114253d5
|
|
c2_128 = 0x4cf5ad432745937f
|
|
size128 = 16
|
|
)
|
|
|
|
// murmur3_128
|
|
func murmur3_128(seed uint32, b []byte) (uint64, uint64) {
|
|
h1 := uint64(seed)
|
|
h2 := uint64(seed)
|
|
|
|
length := len(b)
|
|
h1, h2 = bmix64(b, h1, h2)
|
|
|
|
// tail
|
|
tail := b[length-(length&15):]
|
|
var k1, k2 uint64
|
|
switch length & 15 {
|
|
case 15:
|
|
k2 ^= uint64(tail[14]) << 48
|
|
fallthrough
|
|
case 14:
|
|
k2 ^= uint64(tail[13]) << 40
|
|
fallthrough
|
|
case 13:
|
|
k2 ^= uint64(tail[12]) << 32
|
|
fallthrough
|
|
case 12:
|
|
k2 ^= uint64(tail[11]) << 24
|
|
fallthrough
|
|
case 11:
|
|
k2 ^= uint64(tail[10]) << 16
|
|
fallthrough
|
|
case 10:
|
|
k2 ^= uint64(tail[9]) << 8
|
|
fallthrough
|
|
case 9:
|
|
k2 ^= uint64(tail[8]) << 0
|
|
k2 *= c2_128
|
|
k2 = (k2 << 33) | (k2 >> 31) // rotl64(k2, 33)
|
|
k2 *= c1_128
|
|
h2 ^= k2
|
|
fallthrough
|
|
case 8:
|
|
k1 ^= uint64(tail[7]) << 56
|
|
fallthrough
|
|
case 7:
|
|
k1 ^= uint64(tail[6]) << 48
|
|
fallthrough
|
|
case 6:
|
|
k1 ^= uint64(tail[5]) << 40
|
|
fallthrough
|
|
case 5:
|
|
k1 ^= uint64(tail[4]) << 32
|
|
fallthrough
|
|
case 4:
|
|
k1 ^= uint64(tail[3]) << 24
|
|
fallthrough
|
|
case 3:
|
|
k1 ^= uint64(tail[2]) << 16
|
|
fallthrough
|
|
case 2:
|
|
k1 ^= uint64(tail[1]) << 8
|
|
fallthrough
|
|
case 1:
|
|
k1 ^= uint64(tail[0]) << 0
|
|
k1 *= c1_128
|
|
k1 = (k1 << 31) | (k1 >> 33) // rotl64(k1, 31)
|
|
k1 *= c2_128
|
|
h1 ^= k1
|
|
}
|
|
|
|
h1 ^= uint64(length)
|
|
h2 ^= uint64(length)
|
|
|
|
h1 += h2
|
|
h2 += h1
|
|
|
|
h1 = fmix64(h1)
|
|
h2 = fmix64(h2)
|
|
|
|
h1 += h2
|
|
h2 += h1
|
|
return h1, h2
|
|
}
|
|
|
|
// bmix64 .
|
|
func bmix64(b []byte, h1, h2 uint64) (uint64, uint64) {
|
|
nblocks := len(b) / 16
|
|
|
|
// body
|
|
for i := 0; i < nblocks; i++ {
|
|
t := (*[2]uint64)(unsafe.Pointer(&b[i*16]))
|
|
k1, k2 := t[0], t[1]
|
|
|
|
k1 *= c1_128
|
|
k1 = (k1 << 31) | (k1 >> 33) // rotl64(k1, 31)
|
|
k1 *= c2_128
|
|
h1 ^= k1
|
|
|
|
h1 = (h1 << 27) | (h1 >> 37) // rotl64(h1, 27)
|
|
h1 += h2
|
|
h1 = h1*5 + 0x52dce729
|
|
|
|
k2 *= c2_128
|
|
k2 = (k2 << 33) | (k2 >> 31) // rotl64(k2, 33)
|
|
k2 *= c1_128
|
|
h2 ^= k2
|
|
|
|
h2 = (h2 << 31) | (h2 >> 33) // rotl64(h2, 31)
|
|
h2 += h1
|
|
h2 = h2*5 + 0x38495ab5
|
|
}
|
|
|
|
return h1, h2
|
|
}
|
|
|
|
// fmix64 .
|
|
func fmix64(k uint64) uint64 {
|
|
k ^= k >> 33
|
|
k *= 0xff51afd7ed558ccd
|
|
k ^= k >> 33
|
|
k *= 0xc4ceb9fe1a85ec53
|
|
k ^= k >> 33
|
|
|
|
return k
|
|
}
|