github.com/spaolacci/murmur3@v1.1.0/murmur128.go (about) 1 package murmur3 2 3 import ( 4 //"encoding/binary" 5 "hash" 6 "unsafe" 7 ) 8 9 const ( 10 c1_128 = 0x87c37b91114253d5 11 c2_128 = 0x4cf5ad432745937f 12 ) 13 14 // Make sure interfaces are correctly implemented. 15 var ( 16 _ hash.Hash = new(digest128) 17 _ Hash128 = new(digest128) 18 _ bmixer = new(digest128) 19 ) 20 21 // Hash128 represents a 128-bit hasher 22 // Hack: the standard api doesn't define any Hash128 interface. 23 type Hash128 interface { 24 hash.Hash 25 Sum128() (uint64, uint64) 26 } 27 28 // digest128 represents a partial evaluation of a 128 bites hash. 29 type digest128 struct { 30 digest 31 h1 uint64 // Unfinalized running hash part 1. 32 h2 uint64 // Unfinalized running hash part 2. 33 } 34 35 // New128 returns a 128-bit hasher 36 func New128() Hash128 { return New128WithSeed(0) } 37 38 // New128WithSeed returns a 128-bit hasher set with explicit seed value 39 func New128WithSeed(seed uint32) Hash128 { 40 d := new(digest128) 41 d.seed = seed 42 d.bmixer = d 43 d.Reset() 44 return d 45 } 46 47 func (d *digest128) Size() int { return 16 } 48 49 func (d *digest128) reset() { d.h1, d.h2 = uint64(d.seed), uint64(d.seed) } 50 51 func (d *digest128) Sum(b []byte) []byte { 52 h1, h2 := d.Sum128() 53 return append(b, 54 byte(h1>>56), byte(h1>>48), byte(h1>>40), byte(h1>>32), 55 byte(h1>>24), byte(h1>>16), byte(h1>>8), byte(h1), 56 57 byte(h2>>56), byte(h2>>48), byte(h2>>40), byte(h2>>32), 58 byte(h2>>24), byte(h2>>16), byte(h2>>8), byte(h2), 59 ) 60 } 61 62 func (d *digest128) bmix(p []byte) (tail []byte) { 63 h1, h2 := d.h1, d.h2 64 65 nblocks := len(p) / 16 66 for i := 0; i < nblocks; i++ { 67 t := (*[2]uint64)(unsafe.Pointer(&p[i*16])) 68 k1, k2 := t[0], t[1] 69 70 k1 *= c1_128 71 k1 = (k1 << 31) | (k1 >> 33) // rotl64(k1, 31) 72 k1 *= c2_128 73 h1 ^= k1 74 75 h1 = (h1 << 27) | (h1 >> 37) // rotl64(h1, 27) 76 h1 += h2 77 h1 = h1*5 + 0x52dce729 78 79 k2 *= c2_128 80 k2 = (k2 << 33) | (k2 >> 31) // rotl64(k2, 33) 81 k2 *= c1_128 82 h2 ^= k2 83 84 h2 = (h2 << 31) | (h2 >> 33) // rotl64(h2, 31) 85 h2 += h1 86 h2 = h2*5 + 0x38495ab5 87 } 88 d.h1, d.h2 = h1, h2 89 return p[nblocks*d.Size():] 90 } 91 92 func (d *digest128) Sum128() (h1, h2 uint64) { 93 94 h1, h2 = d.h1, d.h2 95 96 var k1, k2 uint64 97 switch len(d.tail) & 15 { 98 case 15: 99 k2 ^= uint64(d.tail[14]) << 48 100 fallthrough 101 case 14: 102 k2 ^= uint64(d.tail[13]) << 40 103 fallthrough 104 case 13: 105 k2 ^= uint64(d.tail[12]) << 32 106 fallthrough 107 case 12: 108 k2 ^= uint64(d.tail[11]) << 24 109 fallthrough 110 case 11: 111 k2 ^= uint64(d.tail[10]) << 16 112 fallthrough 113 case 10: 114 k2 ^= uint64(d.tail[9]) << 8 115 fallthrough 116 case 9: 117 k2 ^= uint64(d.tail[8]) << 0 118 119 k2 *= c2_128 120 k2 = (k2 << 33) | (k2 >> 31) // rotl64(k2, 33) 121 k2 *= c1_128 122 h2 ^= k2 123 124 fallthrough 125 126 case 8: 127 k1 ^= uint64(d.tail[7]) << 56 128 fallthrough 129 case 7: 130 k1 ^= uint64(d.tail[6]) << 48 131 fallthrough 132 case 6: 133 k1 ^= uint64(d.tail[5]) << 40 134 fallthrough 135 case 5: 136 k1 ^= uint64(d.tail[4]) << 32 137 fallthrough 138 case 4: 139 k1 ^= uint64(d.tail[3]) << 24 140 fallthrough 141 case 3: 142 k1 ^= uint64(d.tail[2]) << 16 143 fallthrough 144 case 2: 145 k1 ^= uint64(d.tail[1]) << 8 146 fallthrough 147 case 1: 148 k1 ^= uint64(d.tail[0]) << 0 149 k1 *= c1_128 150 k1 = (k1 << 31) | (k1 >> 33) // rotl64(k1, 31) 151 k1 *= c2_128 152 h1 ^= k1 153 } 154 155 h1 ^= uint64(d.clen) 156 h2 ^= uint64(d.clen) 157 158 h1 += h2 159 h2 += h1 160 161 h1 = fmix64(h1) 162 h2 = fmix64(h2) 163 164 h1 += h2 165 h2 += h1 166 167 return h1, h2 168 } 169 170 func fmix64(k uint64) uint64 { 171 k ^= k >> 33 172 k *= 0xff51afd7ed558ccd 173 k ^= k >> 33 174 k *= 0xc4ceb9fe1a85ec53 175 k ^= k >> 33 176 return k 177 } 178 179 /* 180 func rotl64(x uint64, r byte) uint64 { 181 return (x << r) | (x >> (64 - r)) 182 } 183 */ 184 185 // Sum128 returns the MurmurHash3 sum of data. It is equivalent to the 186 // following sequence (without the extra burden and the extra allocation): 187 // hasher := New128() 188 // hasher.Write(data) 189 // return hasher.Sum128() 190 func Sum128(data []byte) (h1 uint64, h2 uint64) { return Sum128WithSeed(data, 0) } 191 192 // Sum128WithSeed returns the MurmurHash3 sum of data. It is equivalent to the 193 // following sequence (without the extra burden and the extra allocation): 194 // hasher := New128WithSeed(seed) 195 // hasher.Write(data) 196 // return hasher.Sum128() 197 func Sum128WithSeed(data []byte, seed uint32) (h1 uint64, h2 uint64) { 198 d := &digest128{h1: uint64(seed), h2: uint64(seed)} 199 d.seed = seed 200 d.tail = d.bmix(data) 201 d.clen = len(data) 202 return d.Sum128() 203 }