github.com/cilium/cilium@v1.16.2/pkg/murmur3/murmur3.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package murmur3 5 6 import ( 7 "unsafe" 8 ) 9 10 // Hash128 calculates a 128 bits hash for the given data. It returns different 11 // results when running on big-endian and little-endian machines. 12 // 13 // The code is intended to be as close as possible to the reference implementation 14 // https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp. 15 func Hash128(data []byte, seed uint32) (uint64, uint64) { 16 const ( 17 c1 = uint64(0x87c37b91114253d5) 18 c2 = uint64(0x4cf5ad432745937f) 19 ) 20 21 nblocks := len(data) / 16 22 23 h1 := uint64(seed) 24 h2 := uint64(seed) 25 26 for i := 0; i < nblocks; i++ { 27 tmp := (*[2]uint64)(unsafe.Pointer(&data[i*16])) 28 k1 := tmp[0] 29 k2 := tmp[1] 30 31 k1 *= c1 32 k1 = rotl64(k1, 31) 33 k1 *= c2 34 h1 ^= k1 35 h1 = rotl64(h1, 27) 36 h1 += h2 37 h1 = h1*5 + 0x52dce729 38 k2 *= c2 39 k2 = rotl64(k2, 33) 40 k2 *= c1 41 h2 ^= k2 42 h2 = rotl64(h2, 31) 43 h2 += h1 44 h2 = h2*5 + 0x38495ab5 45 } 46 47 k1 := uint64(0) 48 k2 := uint64(0) 49 50 tail := data[nblocks*16:] 51 52 switch len(tail) & 15 { 53 case 15: 54 k2 ^= uint64(tail[14]) << 48 55 fallthrough 56 case 14: 57 k2 ^= uint64(tail[13]) << 40 58 fallthrough 59 case 13: 60 k2 ^= uint64(tail[12]) << 32 61 fallthrough 62 case 12: 63 k2 ^= uint64(tail[11]) << 24 64 fallthrough 65 case 11: 66 k2 ^= uint64(tail[10]) << 16 67 fallthrough 68 case 10: 69 k2 ^= uint64(tail[9]) << 8 70 fallthrough 71 case 9: 72 k2 ^= uint64(tail[8]) << 0 73 k2 *= c2 74 k2 = rotl64(k2, 33) 75 k2 *= c1 76 h2 ^= k2 77 fallthrough 78 case 8: 79 k1 ^= uint64(tail[7]) << 56 80 fallthrough 81 case 7: 82 k1 ^= uint64(tail[6]) << 48 83 fallthrough 84 case 6: 85 k1 ^= uint64(tail[5]) << 40 86 fallthrough 87 case 5: 88 k1 ^= uint64(tail[4]) << 32 89 fallthrough 90 case 4: 91 k1 ^= uint64(tail[3]) << 24 92 fallthrough 93 case 3: 94 k1 ^= uint64(tail[2]) << 16 95 fallthrough 96 case 2: 97 k1 ^= uint64(tail[1]) << 8 98 fallthrough 99 case 1: 100 k1 ^= uint64(tail[0]) << 0 101 k1 *= c1 102 k1 = rotl64(k1, 31) 103 k1 *= c2 104 h1 ^= k1 105 } 106 107 h1 ^= uint64(len(data)) 108 h2 ^= uint64(len(data)) 109 h1 += h2 110 h2 += h1 111 h1 = fmix64(h1) 112 h2 = fmix64(h2) 113 h1 += h2 114 h2 += h1 115 116 return h1, h2 117 } 118 119 func rotl64(x uint64, r int8) uint64 { 120 return (x << r) | (x >> (64 - r)) 121 } 122 123 func fmix64(k uint64) uint64 { 124 k ^= k >> 33 125 k *= 0xff51afd7ed558ccd 126 k ^= k >> 33 127 k *= 0xc4ceb9fe1a85ec53 128 k ^= k >> 33 129 130 return k 131 }