1 package xxh3
2
3 import (
4 "encoding/binary"
5 "hash"
6 )
7
8
9 type Hasher struct {
10 acc [8]u64
11 blk u64
12 len u64
13 key ptr
14 buf [_block + _stripe]byte
15 seed u64
16 }
17
18 var (
19 _ hash.Hash = (*Hasher)(nil)
20 _ hash.Hash64 = (*Hasher)(nil)
21 )
22
23
24 func New() *Hasher {
25 return new(Hasher)
26 }
27
28
29 func NewSeed(seed uint64) *Hasher {
30 var h Hasher
31 h.Reset()
32 h.seed = seed
33 h.key = key
34
35
36 if seed != 0 {
37 h.key = ptr(&[secretSize]byte{})
38 initSecret(h.key, seed)
39 }
40 return &h
41 }
42
43
44 func (h *Hasher) Reset() {
45 h.acc = [8]u64{
46 prime32_3, prime64_1, prime64_2, prime64_3,
47 prime64_4, prime32_2, prime64_5, prime32_1,
48 }
49 h.blk = 0
50 h.len = 0
51 }
52
53
54
55
56
57 func (h *Hasher) BlockSize() int { return _stripe }
58
59
60 func (h *Hasher) Size() int { return 8 }
61
62
63
64 func (h *Hasher) Sum(b []byte) []byte {
65 var tmp [8]byte
66 binary.BigEndian.PutUint64(tmp[:], h.Sum64())
67 return append(b, tmp[:]...)
68 }
69
70
71
72 func (h *Hasher) Write(buf []byte) (int, error) {
73 h.update(buf)
74 return len(buf), nil
75 }
76
77
78
79 func (h *Hasher) WriteString(buf string) (int, error) {
80 h.updateString(buf)
81 return len(buf), nil
82 }
83
84 func (h *Hasher) update(buf []byte) {
85
86 h.updateString(*(*string)(ptr(&buf)))
87 }
88
89 func (h *Hasher) updateString(buf string) {
90 if h.key == nil {
91 h.key = key
92 h.Reset()
93 }
94
95
96 for h.len == 0 && len(buf) > len(h.buf) {
97 if hasAVX2 {
98 accumBlockAVX2(&h.acc, *(*ptr)(ptr(&buf)), h.key)
99 } else if hasSSE2 {
100 accumBlockSSE(&h.acc, *(*ptr)(ptr(&buf)), h.key)
101 } else {
102 accumBlockScalar(&h.acc, *(*ptr)(ptr(&buf)), h.key)
103 }
104 buf = buf[_block:]
105 h.blk++
106 }
107
108 for len(buf) > 0 {
109 if h.len < u64(len(h.buf)) {
110 n := copy(h.buf[h.len:], buf)
111 h.len += u64(n)
112 buf = buf[n:]
113 continue
114 }
115
116 if hasAVX2 {
117 accumBlockAVX2(&h.acc, ptr(&h.buf), h.key)
118 } else if hasSSE2 {
119 accumBlockSSE(&h.acc, ptr(&h.buf), h.key)
120 } else {
121 accumBlockScalar(&h.acc, ptr(&h.buf), h.key)
122 }
123
124 h.blk++
125 h.len = _stripe
126 copy(h.buf[:_stripe], h.buf[_block:])
127 }
128 }
129
130
131 func (h *Hasher) Sum64() uint64 {
132 if h.key == nil {
133 h.key = key
134 h.Reset()
135 }
136
137 if h.blk == 0 {
138 if h.seed == 0 {
139 return Hash(h.buf[:h.len])
140 }
141 return HashSeed(h.buf[:h.len], h.seed)
142 }
143
144 l := h.blk*_block + h.len
145 acc := l * prime64_1
146 accs := h.acc
147
148 if h.len > 0 {
149
150 if hasAVX2 {
151 accumAVX2(&accs, ptr(&h.buf[0]), h.key, h.len)
152 } else if hasSSE2 {
153 accumSSE(&accs, ptr(&h.buf[0]), h.key, h.len)
154 } else {
155 accumScalar(&accs, ptr(&h.buf[0]), h.key, h.len)
156 }
157 }
158
159 if h.seed == 0 {
160 acc += mulFold64(accs[0]^key64_011, accs[1]^key64_019)
161 acc += mulFold64(accs[2]^key64_027, accs[3]^key64_035)
162 acc += mulFold64(accs[4]^key64_043, accs[5]^key64_051)
163 acc += mulFold64(accs[6]^key64_059, accs[7]^key64_067)
164 } else {
165 secret := h.key
166 acc += mulFold64(accs[0]^readU64(secret, 11), accs[1]^readU64(secret, 19))
167 acc += mulFold64(accs[2]^readU64(secret, 27), accs[3]^readU64(secret, 35))
168 acc += mulFold64(accs[4]^readU64(secret, 43), accs[5]^readU64(secret, 51))
169 acc += mulFold64(accs[6]^readU64(secret, 59), accs[7]^readU64(secret, 67))
170 }
171
172 acc = xxh3Avalanche(acc)
173
174 return acc
175 }
176
177
178 func (h *Hasher) Sum128() Uint128 {
179 if h.key == nil {
180 h.key = key
181 h.Reset()
182 }
183
184 if h.blk == 0 {
185 if h.seed == 0 {
186 return Hash128(h.buf[:h.len])
187 }
188 return Hash128Seed(h.buf[:h.len], h.seed)
189 }
190
191 l := h.blk*_block + h.len
192 acc := Uint128{Lo: l * prime64_1, Hi: ^(l * prime64_2)}
193 accs := h.acc
194
195 if h.len > 0 {
196
197 if hasAVX2 {
198 accumAVX2(&accs, ptr(&h.buf[0]), h.key, h.len)
199 } else if hasSSE2 {
200 accumSSE(&accs, ptr(&h.buf[0]), h.key, h.len)
201 } else {
202 accumScalar(&accs, ptr(&h.buf[0]), h.key, h.len)
203 }
204 }
205
206 if h.seed == 0 {
207 acc.Lo += mulFold64(accs[0]^key64_011, accs[1]^key64_019)
208 acc.Hi += mulFold64(accs[0]^key64_117, accs[1]^key64_125)
209
210 acc.Lo += mulFold64(accs[2]^key64_027, accs[3]^key64_035)
211 acc.Hi += mulFold64(accs[2]^key64_133, accs[3]^key64_141)
212
213 acc.Lo += mulFold64(accs[4]^key64_043, accs[5]^key64_051)
214 acc.Hi += mulFold64(accs[4]^key64_149, accs[5]^key64_157)
215
216 acc.Lo += mulFold64(accs[6]^key64_059, accs[7]^key64_067)
217 acc.Hi += mulFold64(accs[6]^key64_165, accs[7]^key64_173)
218 } else {
219 secret := h.key
220 const hi_off = 117 - 11
221
222 acc.Lo += mulFold64(accs[0]^readU64(secret, 11), accs[1]^readU64(secret, 19))
223 acc.Hi += mulFold64(accs[0]^readU64(secret, 11+hi_off), accs[1]^readU64(secret, 19+hi_off))
224
225 acc.Lo += mulFold64(accs[2]^readU64(secret, 27), accs[3]^readU64(secret, 35))
226 acc.Hi += mulFold64(accs[2]^readU64(secret, 27+hi_off), accs[3]^readU64(secret, 35+hi_off))
227
228 acc.Lo += mulFold64(accs[4]^readU64(secret, 43), accs[5]^readU64(secret, 51))
229 acc.Hi += mulFold64(accs[4]^readU64(secret, 43+hi_off), accs[5]^readU64(secret, 51+hi_off))
230
231 acc.Lo += mulFold64(accs[6]^readU64(secret, 59), accs[7]^readU64(secret, 67))
232 acc.Hi += mulFold64(accs[6]^readU64(secret, 59+hi_off), accs[7]^readU64(secret, 67+hi_off))
233 }
234
235 acc.Lo = xxh3Avalanche(acc.Lo)
236 acc.Hi = xxh3Avalanche(acc.Hi)
237
238 return acc
239 }
240
View as plain text