murmur.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. // Copyright 2013 Hui Chen
  2. // Copyright 2016 ego authors
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License"): you may
  5. // not use this file except in compliance with the License. You may obtain
  6. // a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. // License for the specific language governing permissions and limitations
  14. // under the License.
  15. /* Package murmur Murmur3 32bit hash function based on
  16. http://en.wikipedia.org/wiki/MurmurHash
  17. */
  18. package murmur
  19. const (
  20. c1 = 0xcc9e2d51
  21. c2 = 0x1b873593
  22. c3 = 0x85ebca6b
  23. c4 = 0xc2b2ae35
  24. r1 = 15
  25. r2 = 13
  26. m = 5
  27. n = 0xe6546b64
  28. )
  29. var (
  30. // defaultSeed default murmur seed
  31. defaultSeed = uint32(1)
  32. )
  33. // Sum32 returns a hash from the provided key.
  34. func Sum32(key string, seed ...uint32) (hash uint32) {
  35. if len(seed) > 0 {
  36. return Murmur3([]byte(key), seed[0])
  37. }
  38. return Murmur3([]byte(key))
  39. }
  40. // Murmur3 murmur []byte Hash32
  41. func Murmur3(key []byte, seed ...uint32) (hash uint32) {
  42. hash = defaultSeed
  43. if len(seed) > 0 {
  44. hash = seed[0]
  45. }
  46. iByte := 0
  47. for ; iByte+4 <= len(key); iByte += 4 {
  48. k := uint32(key[iByte]) | uint32(key[iByte+1])<<8 |
  49. uint32(key[iByte+2])<<16 | uint32(key[iByte+3])<<24
  50. k *= c1
  51. k = (k << r1) | (k >> (32 - r1))
  52. k *= c2
  53. hash ^= k
  54. hash = (hash << r2) | (hash >> (32 - r2))
  55. hash = hash*m + n
  56. }
  57. var remainingBytes uint32
  58. switch len(key) - iByte {
  59. case 3:
  60. remainingBytes += uint32(key[iByte+2]) << 16
  61. fallthrough
  62. case 2:
  63. remainingBytes += uint32(key[iByte+1]) << 8
  64. fallthrough
  65. case 1:
  66. remainingBytes += uint32(key[iByte])
  67. remainingBytes *= c1
  68. remainingBytes = (remainingBytes << r1) | (remainingBytes >> (32 - r1))
  69. remainingBytes = remainingBytes * c2
  70. hash ^= remainingBytes
  71. }
  72. hash ^= uint32(len(key))
  73. hash ^= hash >> 16
  74. hash *= c3
  75. hash ^= hash >> 13
  76. hash *= c4
  77. hash ^= hash >> 16
  78. return
  79. }