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