70 lines
1.5 KiB
Go
70 lines
1.5 KiB
Go
package murmur3
|
|
|
|
import "math/bits"
|
|
|
|
// SeedSum32 returns the murmur3 sum of data with the digest initialized to
|
|
// seed.
|
|
//
|
|
// This reads and processes the data in chunks of little endian uint32s;
|
|
// thus, the returned hash is portable across architectures.
|
|
func SeedSum32(seed uint32, data []byte) (h1 uint32) {
|
|
return SeedStringSum32(seed, strslice(data))
|
|
}
|
|
|
|
// Sum32 returns the murmur3 sum of data. It is equivalent to the following
|
|
// sequence (without the extra burden and the extra allocation):
|
|
// hasher := New32()
|
|
// hasher.Write(data)
|
|
// return hasher.Sum32()
|
|
func Sum32(data []byte) uint32 {
|
|
return SeedStringSum32(0, strslice(data))
|
|
}
|
|
|
|
// StringSum32 is the string version of Sum32.
|
|
func StringSum32(data string) uint32 {
|
|
return SeedStringSum32(0, data)
|
|
}
|
|
|
|
// SeedStringSum32 is the string version of SeedSum32.
|
|
func SeedStringSum32(seed uint32, data string) (h1 uint32) {
|
|
h1 = seed
|
|
clen := uint32(len(data))
|
|
for len(data) >= 4 {
|
|
k1 := uint32(data[0]) | uint32(data[1])<<8 | uint32(data[2])<<16 | uint32(data[3])<<24
|
|
data = data[4:]
|
|
|
|
k1 *= c1_32
|
|
k1 = bits.RotateLeft32(k1, 15)
|
|
k1 *= c2_32
|
|
|
|
h1 ^= k1
|
|
h1 = bits.RotateLeft32(h1, 13)
|
|
h1 = h1*5 + 0xe6546b64
|
|
}
|
|
var k1 uint32
|
|
switch len(data) {
|
|
case 3:
|
|
k1 ^= uint32(data[2]) << 16
|
|
fallthrough
|
|
case 2:
|
|
k1 ^= uint32(data[1]) << 8
|
|
fallthrough
|
|
case 1:
|
|
k1 ^= uint32(data[0])
|
|
k1 *= c1_32
|
|
k1 = bits.RotateLeft32(k1, 15)
|
|
k1 *= c2_32
|
|
h1 ^= k1
|
|
}
|
|
|
|
h1 ^= uint32(clen)
|
|
|
|
h1 ^= h1 >> 16
|
|
h1 *= 0x85ebca6b
|
|
h1 ^= h1 >> 13
|
|
h1 *= 0xc2b2ae35
|
|
h1 ^= h1 >> 16
|
|
|
|
return h1
|
|
}
|