github.com/XiaoMi/Gaea@v1.2.5/util/murmur.go (about) 1 // Copyright 2019 The Gaea Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package util 16 17 const ( 18 c1 = 0xcc9e2d51 19 c2 = 0x1b873593 20 ) 21 22 // MurmurHash copy from guava Murmur3_32HashFunction 23 type MurmurHash struct { 24 seed int 25 } 26 27 // NewMurmurHash constructor of MurmurHash 28 func NewMurmurHash(seed int) *MurmurHash { 29 return &MurmurHash{ 30 seed: seed, 31 } 32 } 33 34 // HashUnencodedChars check if has unencoded chars 35 func (m *MurmurHash) HashUnencodedChars(inputStr string) int { 36 input := []rune(inputStr) 37 h1 := int32(m.seed) 38 39 for i := 1; i < len(input); i += 2 { 40 k1 := int32(input[i-1] | (input[i] << 16)) 41 k1 = mixK1(k1) 42 h1 = mixH1(h1, k1) 43 } 44 45 if len(input)&1 == 1 { 46 k1 := int32(input[len(input)-1]) 47 k1 = mixK1(k1) 48 h1 ^= k1 49 } 50 51 return int(fmix(h1, int32(2*len(input)))) 52 } 53 54 func mixK1(k1 int32) int32 { 55 k1_64 := int64(k1) 56 k1_64 *= c1 57 k1 = int32(k1_64) 58 k1 = rotateLeft(k1, 15) 59 k1_64 = int64(k1) 60 k1_64 *= c2 61 return int32(k1_64) 62 } 63 64 func mixH1(h1, k1 int32) int32 { 65 h1 ^= k1 66 h1 = rotateLeft(h1, 13) 67 h1_64 := int64(h1) 68 h1_64 = h1_64*5 + 0xe6546b64 69 return int32(h1_64) 70 } 71 72 func fmix(h1, length int32) int32 { 73 uh1 := uint32(h1) 74 ulength := uint32(length) 75 uh1 ^= ulength 76 uh1 ^= uh1 >> 16 77 uh1 *= 0x85ebca6b 78 uh1 ^= uh1 >> 13 79 uh1 *= 0xc2b2ae35 80 uh1 ^= uh1 >> 16 81 return int32(uh1) 82 } 83 84 func rotateLeft(i, distance int32) int32 { 85 ui := uint32(i) 86 udistance := uint32(distance) 87 a1 := ui << udistance 88 b1 := ui >> (32 - udistance) 89 return int32(a1 | b1) 90 }