forked from sureshsundriyal/murmur3
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmurmur3_32a.go
108 lines (88 loc) · 2.23 KB
/
murmur3_32a.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// Copyright (c) 2013, Suresh Sundriyal. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.
// This is a progressive processing version of the MurmurHash3 family of hash
// functions by Austin Appleby and is a translation of the public domain code
// that can be found here:
// https://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp?r=150
package murmur3
const (
// Constants for x86 32-bit hash function.
c1_32_32 = 0xcc9e2d51
c2_32_32 = 0x1b873593
)
// sum32_32 struct contains variables used in x86 32-bit hash calculations.
type sum32_32 struct {
h1 uint32
k1 uint32
length uint32
offset uint8
}
// New32a returns a Murmur3 32-bit hash.Hash opmtimized for 32-bit architecture.
func New32a(seed uint32) Hash32 {
return &sum32_32{seed, 0, 0, 0}
}
func (s *sum32_32) Clone() HashM3 {
r := new(sum32_32)
*r = *s
return r
}
// Reset resets the hash to one with zero bytes written.
func (s *sum32_32) Reset() {
s.h1, s.k1, s.length, s.offset = 0, 0, 0, 0
}
func (s *sum32_32) ResetAndSetSeed(seed uint32) {
s.Reset()
s.h1 = seed
}
func (s *sum32_32) Write(data []byte) (int, error) {
length := len(data)
if length == 0 {
return 0, nil
}
s.length += uint32(length)
for _, c := range data {
// TODO: Might want to check this for endianness for consistency
// across systems.
if s.offset < 4 {
s.k1 |= uint32(uint32(c) << uint32(s.offset*8))
}
s.offset++
if s.offset == 4 {
s.k1 *= c1_32_32
s.k1 = (s.k1 << 15) | (s.k1 >> (32 - 15))
s.k1 *= c2_32_32
s.h1 ^= s.k1
s.h1 = (s.h1 << 13) | (s.h1 >> (32 - 13))
s.h1 = s.h1*5 + 0xe6546b64
s.k1 = 0
s.offset = 0
}
}
return length, nil
}
func (s *sum32_32) Sum32() uint32 {
var h1 = s.h1
var k1 = s.k1
// tail
if k1 != 0 {
k1 *= c1_32_32
k1 = (k1 << 16) | (k1 >> (32 - 16))
k1 *= c2_32_32
h1 ^= k1
}
// finalization
h1 ^= s.length
h1 ^= h1 >> 16
h1 *= 0x85ebca6b
h1 ^= h1 >> 13
h1 *= 0xc2b2ae35
h1 ^= h1 >> 16
return h1
}
func (s *sum32_32) Sum(in []byte) []byte {
h1 := s.Sum32()
return append(in, byte(h1>>24), byte(h1>>16), byte(h1>>8), byte(h1))
}
func (s *sum32_32) BlockSize() int { return 4 }
func (s *sum32_32) Size() int { return 4 }