Fix copyright lines
[folly.git] / folly / hash / SpookyHashV2.cpp
1 /*
2  * Copyright 2017-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain 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,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 // Spooky Hash
18 // A 128-bit noncryptographic hash, for checksums and table lookup
19 // By Bob Jenkins.  Public domain.
20 //   Oct 31 2010: published framework, disclaimer ShortHash isn't right
21 //   Nov 7 2010: disabled ShortHash
22 //   Oct 31 2011: replace End, ShortMix, ShortEnd, enable ShortHash again
23 //   April 10 2012: buffer overflow on platforms without unaligned reads
24 //   July 12 2012: was passing out variables in final to in/out in short
25 //   July 30 2012: I reintroduced the buffer overflow
26 //   August 5 2012: SpookyV2: d = should be d += in short hash, and remove
27 //                  extra mix from long hash
28
29 #include <folly/hash/SpookyHashV2.h>
30
31 #include <folly/CppAttributes.h>
32 #include <folly/Portability.h>
33
34 #include <cstring>
35
36 namespace folly {
37 namespace hash {
38
39 //
40 // short hash ... it could be used on any message,
41 // but it's used by Spooky just for short messages.
42 //
43 void SpookyHashV2::Short(
44     const void *message,
45     size_t length,
46     uint64_t *hash1,
47     uint64_t *hash2)
48 {
49     uint64_t buf[2*sc_numVars];
50     union
51     {
52         const uint8_t *p8;
53         uint32_t *p32;
54         uint64_t *p64;
55         size_t i;
56     } u;
57
58     u.p8 = (const uint8_t *)message;
59
60     if (!kHasUnalignedAccess && (u.i & 0x7))
61     {
62         memcpy(buf, message, length);
63         u.p64 = buf;
64     }
65
66     size_t remainder = length%32;
67     uint64_t a=*hash1;
68     uint64_t b=*hash2;
69     uint64_t c=sc_const;
70     uint64_t d=sc_const;
71
72     if (length > 15)
73     {
74         const uint64_t *end = u.p64 + (length/32)*4;
75
76         // handle all complete sets of 32 bytes
77         for (; u.p64 < end; u.p64 += 4)
78         {
79             c += u.p64[0];
80             d += u.p64[1];
81             ShortMix(a,b,c,d);
82             a += u.p64[2];
83             b += u.p64[3];
84         }
85
86         //Handle the case of 16+ remaining bytes.
87         if (remainder >= 16)
88         {
89             c += u.p64[0];
90             d += u.p64[1];
91             ShortMix(a,b,c,d);
92             u.p64 += 2;
93             remainder -= 16;
94         }
95     }
96
97     // Handle the last 0..15 bytes, and its length
98     d += ((uint64_t)length) << 56;
99     switch (remainder)
100     {
101     case 15:
102         d += ((uint64_t)u.p8[14]) << 48;
103         FOLLY_FALLTHROUGH;
104     case 14:
105         d += ((uint64_t)u.p8[13]) << 40;
106         FOLLY_FALLTHROUGH;
107     case 13:
108         d += ((uint64_t)u.p8[12]) << 32;
109         FOLLY_FALLTHROUGH;
110     case 12:
111         d += u.p32[2];
112         c += u.p64[0];
113         break;
114     case 11:
115         d += ((uint64_t)u.p8[10]) << 16;
116         FOLLY_FALLTHROUGH;
117     case 10:
118         d += ((uint64_t)u.p8[9]) << 8;
119         FOLLY_FALLTHROUGH;
120     case 9:
121         d += (uint64_t)u.p8[8];
122         FOLLY_FALLTHROUGH;
123     case 8:
124         c += u.p64[0];
125         break;
126     case 7:
127         c += ((uint64_t)u.p8[6]) << 48;
128         FOLLY_FALLTHROUGH;
129     case 6:
130         c += ((uint64_t)u.p8[5]) << 40;
131         FOLLY_FALLTHROUGH;
132     case 5:
133         c += ((uint64_t)u.p8[4]) << 32;
134         FOLLY_FALLTHROUGH;
135     case 4:
136         c += u.p32[0];
137         break;
138     case 3:
139         c += ((uint64_t)u.p8[2]) << 16;
140         FOLLY_FALLTHROUGH;
141     case 2:
142         c += ((uint64_t)u.p8[1]) << 8;
143         FOLLY_FALLTHROUGH;
144     case 1:
145         c += (uint64_t)u.p8[0];
146         break;
147     case 0:
148         c += sc_const;
149         d += sc_const;
150     }
151     ShortEnd(a,b,c,d);
152     *hash1 = a;
153     *hash2 = b;
154 }
155
156
157
158
159 // do the whole hash in one call
160 void SpookyHashV2::Hash128(
161     const void *message,
162     size_t length,
163     uint64_t *hash1,
164     uint64_t *hash2)
165 {
166     if (length < sc_bufSize)
167     {
168         Short(message, length, hash1, hash2);
169         return;
170     }
171
172     uint64_t h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11;
173     uint64_t buf[sc_numVars];
174     uint64_t *end;
175     union
176     {
177         const uint8_t *p8;
178         uint64_t *p64;
179         size_t i;
180     } u;
181     size_t remainder;
182
183     h0=h3=h6=h9  = *hash1;
184     h1=h4=h7=h10 = *hash2;
185     h2=h5=h8=h11 = sc_const;
186
187     u.p8 = (const uint8_t *)message;
188     end = u.p64 + (length/sc_blockSize)*sc_numVars;
189
190     // handle all whole sc_blockSize blocks of bytes
191     if (kHasUnalignedAccess || ((u.i & 0x7) == 0))
192     {
193         while (u.p64 < end)
194         {
195             Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
196             u.p64 += sc_numVars;
197         }
198     }
199     else
200     {
201         while (u.p64 < end)
202         {
203             memcpy(buf, u.p64, sc_blockSize);
204             Mix(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
205             u.p64 += sc_numVars;
206         }
207     }
208
209     // handle the last partial block of sc_blockSize bytes
210     remainder = (length - ((const uint8_t *)end-(const uint8_t *)message));
211     memcpy(buf, end, remainder);
212     memset(((uint8_t *)buf)+remainder, 0, sc_blockSize-remainder);
213     ((uint8_t*)buf)[sc_blockSize - 1] = uint8_t(remainder);
214
215     // do some final mixing
216     End(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
217     *hash1 = h0;
218     *hash2 = h1;
219 }
220
221
222
223 // init spooky state
224 void SpookyHashV2::Init(uint64_t seed1, uint64_t seed2)
225 {
226     m_length = 0;
227     m_remainder = 0;
228     m_state[0] = seed1;
229     m_state[1] = seed2;
230 }
231
232
233 // add a message fragment to the state
234 void SpookyHashV2::Update(const void *message, size_t length)
235 {
236     uint64_t h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11;
237     size_t newLength = length + m_remainder;
238     uint8_t  remainder;
239     union
240     {
241         const uint8_t *p8;
242         uint64_t *p64;
243         size_t i;
244     } u;
245     const uint64_t *end;
246
247     // Is this message fragment too short?  If it is, stuff it away.
248     if (newLength < sc_bufSize)
249     {
250         memcpy(&((uint8_t *)m_data)[m_remainder], message, length);
251         m_length = length + m_length;
252         m_remainder = (uint8_t)newLength;
253         return;
254     }
255
256     // init the variables
257     if (m_length < sc_bufSize)
258     {
259         h0=h3=h6=h9  = m_state[0];
260         h1=h4=h7=h10 = m_state[1];
261         h2=h5=h8=h11 = sc_const;
262     }
263     else
264     {
265         h0 = m_state[0];
266         h1 = m_state[1];
267         h2 = m_state[2];
268         h3 = m_state[3];
269         h4 = m_state[4];
270         h5 = m_state[5];
271         h6 = m_state[6];
272         h7 = m_state[7];
273         h8 = m_state[8];
274         h9 = m_state[9];
275         h10 = m_state[10];
276         h11 = m_state[11];
277     }
278     m_length = length + m_length;
279
280     // if we've got anything stuffed away, use it now
281     if (m_remainder)
282     {
283         uint8_t prefix = sc_bufSize-m_remainder;
284         memcpy(&(((uint8_t *)m_data)[m_remainder]), message, prefix);
285         u.p64 = m_data;
286         Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
287         Mix(&u.p64[sc_numVars], h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
288         u.p8 = ((const uint8_t *)message) + prefix;
289         length -= prefix;
290     }
291     else
292     {
293         u.p8 = (const uint8_t *)message;
294     }
295
296     // handle all whole blocks of sc_blockSize bytes
297     end = u.p64 + (length/sc_blockSize)*sc_numVars;
298     remainder = (uint8_t)(length-((const uint8_t *)end-u.p8));
299     if (kHasUnalignedAccess || (u.i & 0x7) == 0)
300     {
301         while (u.p64 < end)
302         {
303             Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
304             u.p64 += sc_numVars;
305         }
306     }
307     else
308     {
309         while (u.p64 < end)
310         {
311             memcpy(m_data, u.p8, sc_blockSize);
312             Mix(m_data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
313             u.p64 += sc_numVars;
314         }
315     }
316
317     // stuff away the last few bytes
318     m_remainder = remainder;
319     memcpy(m_data, end, remainder);
320
321     // stuff away the variables
322     m_state[0] = h0;
323     m_state[1] = h1;
324     m_state[2] = h2;
325     m_state[3] = h3;
326     m_state[4] = h4;
327     m_state[5] = h5;
328     m_state[6] = h6;
329     m_state[7] = h7;
330     m_state[8] = h8;
331     m_state[9] = h9;
332     m_state[10] = h10;
333     m_state[11] = h11;
334 }
335
336
337 // report the hash for the concatenation of all message fragments so far
338 void SpookyHashV2::Final(uint64_t *hash1, uint64_t *hash2) const
339 {
340     // init the variables
341     if (m_length < sc_bufSize)
342     {
343         *hash1 = m_state[0];
344         *hash2 = m_state[1];
345         Short( m_data, m_length, hash1, hash2);
346         return;
347     }
348
349     uint64_t buf[2*sc_numVars];
350     memcpy(buf, m_data, sizeof(buf));
351     uint64_t *data = buf;
352     uint8_t remainder = m_remainder;
353
354     uint64_t h0 = m_state[0];
355     uint64_t h1 = m_state[1];
356     uint64_t h2 = m_state[2];
357     uint64_t h3 = m_state[3];
358     uint64_t h4 = m_state[4];
359     uint64_t h5 = m_state[5];
360     uint64_t h6 = m_state[6];
361     uint64_t h7 = m_state[7];
362     uint64_t h8 = m_state[8];
363     uint64_t h9 = m_state[9];
364     uint64_t h10 = m_state[10];
365     uint64_t h11 = m_state[11];
366
367     if (remainder >= sc_blockSize)
368     {
369         // m_data can contain two blocks; handle any whole first block
370         Mix(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
371         data += sc_numVars;
372         remainder -= sc_blockSize;
373     }
374
375     // mix in the last partial block, and the length mod sc_blockSize
376     memset(&((uint8_t *)data)[remainder], 0, (sc_blockSize-remainder));
377
378     ((uint8_t *)data)[sc_blockSize-1] = remainder;
379
380     // do some final mixing
381     End(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
382
383     *hash1 = h0;
384     *hash2 = h1;
385 }
386
387 } // namespace hash
388 } // namespace folly