github.com/TykTechnologies/murmur3@v0.0.0-20230310161213-aad17efd5632/murmur32.go (about) 1 package murmur3 2 3 // http://code.google.com/p/guava-libraries/source/browse/guava/src/com/google/common/hash/Murmur3_32HashFunction.java 4 5 import ( 6 "hash" 7 "unsafe" 8 ) 9 10 // Make sure interfaces are correctly implemented. 11 var ( 12 _ hash.Hash = new(digest32) 13 _ hash.Hash32 = new(digest32) 14 ) 15 16 const ( 17 c1_32 uint32 = 0xcc9e2d51 18 c2_32 uint32 = 0x1b873593 19 ) 20 21 // digest32 represents a partial evaluation of a 32 bites hash. 22 type digest32 struct { 23 digest 24 h1 uint32 // Unfinalized running hash. 25 } 26 27 func New32() hash.Hash32 { 28 d := new(digest32) 29 d.bmixer = d 30 d.Reset() 31 return d 32 } 33 34 func (d *digest32) Size() int { return 4 } 35 36 func (d *digest32) reset() { d.h1 = 0 } 37 38 func (d *digest32) Sum(b []byte) []byte { 39 h := d.h1 40 return append(b, byte(h>>24), byte(h>>16), byte(h>>8), byte(h)) 41 } 42 43 // Digest as many blocks as possible. 44 func (d *digest32) bmix(p []byte) (tail []byte) { 45 h1 := d.h1 46 47 nblocks := len(p) / 4 48 for i := 0; i < nblocks; i++ { 49 k1 := *(*uint32)(unsafe.Pointer(&p[i*4])) 50 51 k1 *= c1_32 52 k1 = (k1 << 15) | (k1 >> 17) // rotl32(k1, 15) 53 k1 *= c2_32 54 55 h1 ^= k1 56 h1 = (h1 << 13) | (h1 >> 19) // rotl32(h1, 13) 57 h1 = h1*5 + 0xe6546b64 58 } 59 d.h1 = h1 60 return p[nblocks*d.Size():] 61 } 62 63 func (d *digest32) Sum32() (h1 uint32) { 64 65 h1 = d.h1 66 67 var k1 uint32 68 switch len(d.tail) & 3 { 69 case 3: 70 k1 ^= uint32(d.tail[2]) << 16 71 fallthrough 72 case 2: 73 k1 ^= uint32(d.tail[1]) << 8 74 fallthrough 75 case 1: 76 k1 ^= uint32(d.tail[0]) 77 k1 *= c1_32 78 k1 = (k1 << 15) | (k1 >> 17) // rotl32(k1, 15) 79 k1 *= c2_32 80 h1 ^= k1 81 } 82 83 h1 ^= uint32(d.clen) 84 85 h1 ^= h1 >> 16 86 h1 *= 0x85ebca6b 87 h1 ^= h1 >> 13 88 h1 *= 0xc2b2ae35 89 h1 ^= h1 >> 16 90 91 return h1 92 } 93 94 /* 95 func rotl32(x uint32, r byte) uint32 { 96 return (x << r) | (x >> (32 - r)) 97 } 98 */ 99 100 // Sum32 returns the MurmurHash3 sum of data. It is equivalent to the 101 // following sequence (without the extra burden and the extra allocation): 102 // hasher := New32() 103 // hasher.Write(data) 104 // return hasher.Sum32() 105 func Sum32(data []byte) uint32 { 106 107 var h1 uint32 = 0 108 109 nblocks := len(data) / 4 110 var p uintptr 111 if len(data) > 0 { 112 p = uintptr(unsafe.Pointer(&data[0])) 113 } 114 p1 := p + uintptr(4*nblocks) 115 for ; p < p1; p += 4 { 116 k1 := *(*uint32)(unsafe.Pointer(p)) 117 118 k1 *= c1_32 119 k1 = (k1 << 15) | (k1 >> 17) // rotl32(k1, 15) 120 k1 *= c2_32 121 122 h1 ^= k1 123 h1 = (h1 << 13) | (h1 >> 19) // rotl32(h1, 13) 124 h1 = h1*5 + 0xe6546b64 125 } 126 127 tail := data[nblocks*4:] 128 129 var k1 uint32 130 switch len(tail) & 3 { 131 case 3: 132 k1 ^= uint32(tail[2]) << 16 133 fallthrough 134 case 2: 135 k1 ^= uint32(tail[1]) << 8 136 fallthrough 137 case 1: 138 k1 ^= uint32(tail[0]) 139 k1 *= c1_32 140 k1 = (k1 << 15) | (k1 >> 17) // rotl32(k1, 15) 141 k1 *= c2_32 142 h1 ^= k1 143 } 144 145 h1 ^= uint32(len(data)) 146 147 h1 ^= h1 >> 16 148 h1 *= 0x85ebca6b 149 h1 ^= h1 >> 13 150 h1 *= 0xc2b2ae35 151 h1 ^= h1 >> 16 152 153 return h1 154 }