├── README.md ├── license.txt ├── murmur_test.go └── murmur.go /README.md: -------------------------------------------------------------------------------- 1 | murmur 2 | ====== 3 | 4 | Go Murmur3 hash implementation 5 | 6 | Based on 7 | 8 | http://en.wikipedia.org/wiki/MurmurHash 9 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright 2013 Hui Chen 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 | -------------------------------------------------------------------------------- /murmur_test.go: -------------------------------------------------------------------------------- 1 | package murmur 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestMurmur3(t *testing.T) { 8 | text1 := []byte("The quick brown fox jumps over the lazy dog") 9 | expectedHash1 := uint32(0x78e69e27) 10 | actualHash1 := Murmur3(text1) 11 | if expectedHash1 != actualHash1 { 12 | t.Errorf("Expected hash value: %d, got %d", expectedHash1, actualHash1) 13 | } 14 | 15 | text2 := []byte("The quick brown fox jumps over the lazy cog") 16 | expectedHash2 := uint32(0xd5ece287) 17 | actualHash2 := Murmur3(text2) 18 | if expectedHash2 != actualHash2 { 19 | t.Errorf("Expected hash value: %d, got %d", expectedHash2, actualHash2) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /murmur.go: -------------------------------------------------------------------------------- 1 | // Murmur3 32bit hash function based on 2 | // http://en.wikipedia.org/wiki/MurmurHash 3 | package murmur 4 | 5 | const ( 6 | c1 = 0xcc9e2d51 7 | c2 = 0x1b873593 8 | c3 = 0x85ebca6b 9 | c4 = 0xc2b2ae35 10 | r1 = 15 11 | r2 = 13 12 | m = 5 13 | n = 0xe6546b64 14 | ) 15 | 16 | var ( 17 | Seed = uint32(1) 18 | ) 19 | 20 | func Murmur3(key []byte) (hash uint32) { 21 | hash = Seed 22 | iByte := 0 23 | for ; iByte+4 <= len(key); iByte += 4 { 24 | k := uint32(key[iByte]) | uint32(key[iByte+1])<<8 | uint32(key[iByte+2])<<16 | uint32(key[iByte+3])<<24 25 | k *= c1 26 | k = (k << r1) | (k >> (32 - r1)) 27 | k *= c2 28 | hash ^= k 29 | hash = (hash << r2) | (hash >> (32 - r2)) 30 | hash = hash*m + n 31 | } 32 | 33 | var remainingBytes uint32 34 | switch len(key) - iByte { 35 | case 3: 36 | remainingBytes += uint32(key[iByte+2]) << 16 37 | fallthrough 38 | case 2: 39 | remainingBytes += uint32(key[iByte+1]) << 8 40 | fallthrough 41 | case 1: 42 | remainingBytes += uint32(key[iByte]) 43 | remainingBytes *= c1 44 | remainingBytes = (remainingBytes << r1) | (remainingBytes >> (32 - r1)) 45 | remainingBytes = remainingBytes * c2 46 | hash ^= remainingBytes 47 | } 48 | 49 | hash ^= uint32(len(key)) 50 | hash ^= hash >> 16 51 | hash *= c3 52 | hash ^= hash >> 13 53 | hash *= c4 54 | hash ^= hash >> 16 55 | 56 | // 出发吧,狗嬷嬷! 57 | return 58 | } 59 | --------------------------------------------------------------------------------