123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- package murmur3
- // https://github.com/spaolacci/murmur3/blob/master/murmur32.go
- import (
- "hash"
- "math/bits"
- "unsafe"
- )
- // Make sure interfaces are correctly implemented.
- var (
- _ hash.Hash32 = new(digest32)
- _ bmixer = new(digest32)
- )
- const (
- c1_32 uint32 = 0xcc9e2d51
- c2_32 uint32 = 0x1b873593
- )
- // digest32 represents a partial evaluation of a 32 bites hash.
- type digest32 struct {
- digest
- h1 uint32 // Unfinalized running hash.
- }
- // New32 returns new 32-bit hasher
- func New32() hash.Hash32 { return New32WithSeed(0) }
- // New32WithSeed returns new 32-bit hasher set with explicit seed value
- func New32WithSeed(seed uint32) hash.Hash32 {
- d := new(digest32)
- d.seed = seed
- d.bmixer = d
- d.Reset()
- return d
- }
- func (d *digest32) Size() int { return 4 }
- func (d *digest32) reset() { d.h1 = d.seed }
- func (d *digest32) Sum(b []byte) []byte {
- h := d.Sum32()
- return append(b, byte(h>>24), byte(h>>16), byte(h>>8), byte(h))
- }
- // Digest as many blocks as possible.
- func (d *digest32) bmix(p []byte) (tail []byte) {
- h1 := d.h1
- nblocks := len(p) / 4
- for i := 0; i < nblocks; i++ {
- k1 := *(*uint32)(unsafe.Pointer(&p[i*4]))
- k1 *= c1_32
- k1 = bits.RotateLeft32(k1, 15)
- k1 *= c2_32
- h1 ^= k1
- h1 = bits.RotateLeft32(h1, 13)
- h1 = h1*4 + h1 + 0xe6546b64
- }
- d.h1 = h1
- return p[nblocks*d.Size():]
- }
- func (d *digest32) Sum32() (h1 uint32) {
- h1 = d.h1
- var k1 uint32
- switch len(d.tail) & 3 {
- case 3:
- k1 ^= uint32(d.tail[2]) << 16
- fallthrough
- case 2:
- k1 ^= uint32(d.tail[1]) << 8
- fallthrough
- case 1:
- k1 ^= uint32(d.tail[0])
- k1 *= c1_32
- k1 = bits.RotateLeft32(k1, 15)
- k1 *= c2_32
- h1 ^= k1
- }
- h1 ^= uint32(d.clen)
- h1 ^= h1 >> 16
- h1 *= 0x85ebca6b
- h1 ^= h1 >> 13
- h1 *= 0xc2b2ae35
- h1 ^= h1 >> 16
- return h1
- }
- func Sum32(data []byte) uint32 { return Sum32WithSeed(data, 0) }
- func Sum32WithSeed(data []byte, seed uint32) uint32 {
- h1 := seed
- nblocks := len(data) / 4
- for i := 0; i < nblocks; i++ {
- k1 := *(*uint32)(unsafe.Pointer(&data[i*4]))
- k1 *= c1_32
- k1 = bits.RotateLeft32(k1, 15)
- k1 *= c2_32
- h1 ^= k1
- h1 = bits.RotateLeft32(h1, 13)
- h1 = h1*4 + h1 + 0xe6546b64
- }
- tail := data[nblocks*4:]
- var k1 uint32
- switch len(tail) & 3 {
- case 3:
- k1 ^= uint32(tail[2]) << 16
- fallthrough
- case 2:
- k1 ^= uint32(tail[1]) << 8
- fallthrough
- case 1:
- k1 ^= uint32(tail[0])
- k1 *= c1_32
- k1 = bits.RotateLeft32(k1, 15)
- k1 *= c2_32
- h1 ^= k1
- }
- h1 ^= uint32(len(data))
- h1 ^= h1 >> 16
- h1 *= 0x85ebca6b
- h1 ^= h1 >> 13
- h1 *= 0xc2b2ae35
- h1 ^= h1 >> 16
- return h1
- }
|