Line data Source code
1 : /*
2 : * Copyright (C) 2013 Andrea Mazzoleni
3 : *
4 : * This program is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 3 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * This program is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : /*
19 : * Derivative work from SpookyV2.cpp/h
20 : *
21 : * WARNING!!!! Note that this implementation doesn't use the short hash optimization
22 : * resulting in different hashes for any length shorter than 192 bytes
23 : *
24 : * SpookyHash
25 : * http://burtleburtle.net/bob/hash/spooky.html
26 : *
27 : * Exact source used as reference:
28 : * http://burtleburtle.net/bob/c/SpookyV2.h
29 : * http://burtleburtle.net/bob/c/SpookyV2.cpp
30 : */
31 :
32 : // Spooky Hash
33 : // A 128-bit noncryptographic hash, for checksums and table lookup
34 : // By Bob Jenkins. Public domain.
35 : // Oct 31 2010: published framework, disclaimer ShortHash isn't right
36 : // Nov 7 2010: disabled ShortHash
37 : // Oct 31 2011: replace End, ShortMix, ShortEnd, enable ShortHash again
38 : // April 10 2012: buffer overflow on platforms without unaligned reads
39 : // July 12 2012: was passing out variables in final to in/out in short
40 : // July 30 2012: I reintroduced the buffer overflow
41 : // August 5 2012: SpookyV2: d = should be d += in short hash, and remove extra mix from long hash
42 : //
43 : // Up to 3 bytes/cycle for long messages. Reasonably fast for short messages.
44 : // All 1 or 2 bit deltas achieve avalanche within 1% bias per output bit.
45 : //
46 : // This was developed for and tested on 64-bit x86-compatible processors.
47 : // It assumes the processor is little-endian. There is a macro
48 : // controlling whether unaligned reads are allowed (by default they are).
49 : // This should be an equally good hash on big-endian machines, but it will
50 : // compute different results on them than on little-endian machines.
51 : //
52 : // Google's CityHash has similar specs to SpookyHash, and CityHash is faster
53 : // on new Intel boxes. MD4 and MD5 also have similar specs, but they are orders
54 : // of magnitude slower. CRCs are two or more times slower, but unlike
55 : // SpookyHash, they have nice math for combining the CRCs of pieces to form
56 : // the CRCs of wholes. There are also cryptographic hashes, but those are even
57 : // slower than MD5.
58 : //
59 :
60 : #define Mix(data, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11) \
61 : s0 += data[0]; s2 ^= s10; s11 ^= s0; s0 = util_rotl64(s0, 11); s11 += s1; \
62 : s1 += data[1]; s3 ^= s11; s0 ^= s1; s1 = util_rotl64(s1, 32); s0 += s2; \
63 : s2 += data[2]; s4 ^= s0; s1 ^= s2; s2 = util_rotl64(s2, 43); s1 += s3; \
64 : s3 += data[3]; s5 ^= s1; s2 ^= s3; s3 = util_rotl64(s3, 31); s2 += s4; \
65 : s4 += data[4]; s6 ^= s2; s3 ^= s4; s4 = util_rotl64(s4, 17); s3 += s5; \
66 : s5 += data[5]; s7 ^= s3; s4 ^= s5; s5 = util_rotl64(s5, 28); s4 += s6; \
67 : s6 += data[6]; s8 ^= s4; s5 ^= s6; s6 = util_rotl64(s6, 39); s5 += s7; \
68 : s7 += data[7]; s9 ^= s5; s6 ^= s7; s7 = util_rotl64(s7, 57); s6 += s8; \
69 : s8 += data[8]; s10 ^= s6; s7 ^= s8; s8 = util_rotl64(s8, 55); s7 += s9; \
70 : s9 += data[9]; s11 ^= s7; s8 ^= s9; s9 = util_rotl64(s9, 54); s8 += s10; \
71 : s10 += data[10]; s0 ^= s8; s9 ^= s10; s10 = util_rotl64(s10, 22); s9 += s11; \
72 : s11 += data[11]; s1 ^= s9; s10 ^= s11; s11 = util_rotl64(s11, 46); s10 += s0;
73 :
74 : #define EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11) \
75 : h11 += h1; h2 ^= h11; h1 = util_rotl64(h1, 44); \
76 : h0 += h2; h3 ^= h0; h2 = util_rotl64(h2, 15); \
77 : h1 += h3; h4 ^= h1; h3 = util_rotl64(h3, 34); \
78 : h2 += h4; h5 ^= h2; h4 = util_rotl64(h4, 21); \
79 : h3 += h5; h6 ^= h3; h5 = util_rotl64(h5, 38); \
80 : h4 += h6; h7 ^= h4; h6 = util_rotl64(h6, 33); \
81 : h5 += h7; h8 ^= h5; h7 = util_rotl64(h7, 10); \
82 : h6 += h8; h9 ^= h6; h8 = util_rotl64(h8, 13); \
83 : h7 += h9; h10 ^= h7; h9 = util_rotl64(h9, 38); \
84 : h8 += h10; h11 ^= h8; h10 = util_rotl64(h10, 53); \
85 : h9 += h11; h0 ^= h9; h11 = util_rotl64(h11, 42); \
86 : h10 += h0; h1 ^= h10; h0 = util_rotl64(h0, 54);
87 :
88 : #define End(data, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11) \
89 : h0 += data[0]; h1 += data[1]; h2 += data[2]; h3 += data[3]; \
90 : h4 += data[4]; h5 += data[5]; h6 += data[6]; h7 += data[7]; \
91 : h8 += data[8]; h9 += data[9]; h10 += data[10]; h11 += data[11]; \
92 : EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); \
93 : EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); \
94 : EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
95 :
96 : // number of uint64_t's in internal state
97 : #define sc_numVars 12
98 :
99 : // size of the internal state
100 : #define sc_blockSize (sc_numVars * 8)
101 :
102 : //
103 : // sc_const: a constant which:
104 : // * is not zero
105 : // * is odd
106 : // * is a not-very-regular mix of 1's and 0's
107 : // * does not need any other special mathematical properties
108 : //
109 : #define sc_const 0xdeadbeefdeadbeefLL
110 :
111 3893007 : void SpookyHash128(const void* data, size_t size, const uint8_t* seed, uint8_t* digest)
112 : {
113 : uint64_t h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11;
114 : uint64_t buf[sc_numVars];
115 : size_t nblocks;
116 : const uint64_t* blocks;
117 : const uint64_t* end;
118 : size_t size_remainder;
119 : #if WORDS_BIGENDIAN
120 : unsigned i;
121 : #endif
122 :
123 3893007 : h9 = util_read64(seed + 0);
124 3893007 : h10 = util_read64(seed + 8);
125 :
126 3893007 : h0 = h3 = h6 = h9;
127 3893007 : h1 = h4 = h7 = h10;
128 3893007 : h2 = h5 = h8 = h11 = sc_const;
129 :
130 3893007 : nblocks = size / sc_blockSize;
131 3893007 : blocks = data;
132 3893007 : end = blocks + nblocks * sc_numVars;
133 :
134 : /* body */
135 39095232 : while (blocks < end) {
136 : #if WORDS_BIGENDIAN
137 : for (i = 0; i < sc_numVars; ++i)
138 : buf[i] = util_swap64(blocks[i]);
139 : Mix(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
140 : #else
141 31309218 : Mix(blocks, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
142 : #endif
143 31309218 : blocks += sc_numVars;
144 : }
145 :
146 : /* tail */
147 3893007 : size_remainder = (size - ((const uint8_t*)end - (const uint8_t*)data));
148 3893007 : memcpy(buf, end, size_remainder);
149 3893007 : memset(((uint8_t*)buf) + size_remainder, 0, sc_blockSize - size_remainder);
150 3893007 : ((uint8_t*)buf)[sc_blockSize - 1] = size_remainder;
151 :
152 : /* finalization */
153 : #if WORDS_BIGENDIAN
154 : for (i = 0; i < sc_numVars; ++i)
155 : buf[i] = util_swap64(buf[i]);
156 : #endif
157 3893007 : End(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
158 :
159 3893007 : util_write64(digest + 0, h0);
160 3893007 : util_write64(digest + 8, h1);
161 3893007 : }
162 :
|