BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslh_spookyhashalgorithmimp.h
Go to the documentation of this file.
1/// @file bslh_spookyhashalgorithmimp.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslh_spookyhashalgorithmimp.h -*-C++-*-
8#ifndef INCLUDED_BSLH_SPOOKYHASHALGORITHMIMP
9#define INCLUDED_BSLH_SPOOKYHASHALGORITHMIMP
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslh_spookyhashalgorithmimp bslh_spookyhashalgorithmimp
15/// @brief Provide BDE style encapsulation of 3rd party SpookyHash code.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslh
19/// @{
20/// @addtogroup bslh_spookyhashalgorithmimp
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslh_spookyhashalgorithmimp-purpose"> Purpose</a>
25/// * <a href="#bslh_spookyhashalgorithmimp-classes"> Classes </a>
26/// * <a href="#bslh_spookyhashalgorithmimp-description"> Description </a>
27/// * <a href="#bslh_spookyhashalgorithmimp-usage"> Usage </a>
28/// * <a href="#bslh_spookyhashalgorithmimp-example-creating-128-bit-checksums"> Example: Creating 128-bit checksums </a>
29/// * <a href="#bslh_spookyhashalgorithmimp-changes"> Changes </a>
30/// * <a href="#bslh_spookyhashalgorithmimp-third-party-documentation"> Third-Party Documentation </a>
31///
32/// # Purpose {#bslh_spookyhashalgorithmimp-purpose}
33/// Provide BDE style encapsulation of 3rd party SpookyHash code.
34///
35/// # Classes {#bslh_spookyhashalgorithmimp-classes}
36///
37/// - bslh::SpookyHashAlgorithmImp: encapsulation of 3rd party SpookyHash code
38///
39/// @see bslh_hash, bslh_spookyhashalgorithm
40///
41/// # Description {#bslh_spookyhashalgorithmimp-description}
42/// `bslh::SpookyHashAlgorithmImp` provides BDE style encapsulation
43/// around Bob Jenkins' canonical SpookyHash implementation. SpookyHash
44/// provides a way to hash contiguous data all at once, or discontiguous data in
45/// pieces. More information is available at:
46/// http://burtleburtle.net/bob/hash/spooky.html
47///
48/// ## Usage {#bslh_spookyhashalgorithmimp-usage}
49///
50///
51/// This section illustrates intended usage of this component.
52///
53/// ### Example: Creating 128-bit checksums {#bslh_spookyhashalgorithmimp-example-creating-128-bit-checksums}
54///
55///
56/// Suppose we have a library of 4 billion pieces of data and we want to store
57/// checksums for this data. For a 64-bit hash, there is a 35% chance of two of
58/// these checksums colliding (according to the approximation found here:
59/// http://en.wikipedia.org/wiki/Birthday_problem). We want to avoid checksum
60/// collision, so we will use the 128-bit hashing functionality provided by
61/// `SpookyHashAlgorithmImp`.
62///
63/// First, we will declare a class `CheckedData` which will store some data as
64/// well as the checksum associated with it.
65/// @code
66///
67/// class CheckedData {
68/// // This class holds a pointer to data and provides a way of verifying
69/// // that the data has not changed.
70///
71/// // TYPES
72/// typedef bsls::Types::Uint64 Uint64;
73///
74/// // DATA
75/// size_t d_length;
76/// const char *d_data;
77/// Uint64 d_checksum1;
78/// Uint64 d_checksum2;
79///
80/// public:
81/// CheckedData(const char *data, size_t length);
82/// // Creates an instance of this class having the specified 'length'
83/// // bytes of 'data'. The behavior is undefined unless 'data' is
84/// // initialized with at least 'length' bytes or 'length' is zero,
85/// // and remains valid for the lifetime of this object. Note that
86/// // only a pointer to the data will be maintained, it will not be
87/// // copied.
88///
89/// const char *getData();
90/// // Return a pointer to the data being tracked by this class.
91///
92/// bool isDataValid();
93/// // Return 'true' if the data stored in this class matches the
94/// // stored checksum, and 'false' otherwise.
95/// };
96///
97/// @endcode
98/// Then, we define the `CheckedData` constructor. Here we will use
99/// `SpookyHashImp` to calculate a 128-bit checksum.
100/// @code
101///
102/// CheckedData::CheckedData(const char *data, size_t length)
103/// : d_length(length)
104/// , d_data(data)
105/// , d_checksum1(0)
106/// , d_checksum2(0)
107/// {
108/// BSLS_ASSERT(0 != data || 0 == length);
109///
110/// SpookyHashAlgorithmImp hashAlg(1, 2);
111///
112/// hashAlg.hash128(d_data, d_length, &d_checksum1, &d_checksum2);
113/// }
114///
115/// const char *CheckedData::getData() {
116/// return d_data;
117/// }
118///
119/// @endcode
120/// Next, we define `isDataValid`. We will generate a checksum from the
121/// contained data and then compare it to the checksum we generated when the
122/// class was created. If the two hashes match, then we can be reasonably
123/// certain that the data is still in a valid state (the chance of an accidental
124/// collision is very low). If the checksums do not match, we know that the
125/// data has been corrupted. We will not be able to restore it, but we will
126/// know not to trust it.
127/// @code
128///
129/// bool CheckedData::isDataValid() {
130/// SpookyHashAlgorithmImp hashAlg(1, 2);
131/// Uint64 checksum1 = 0;
132/// Uint64 checksum2 = 0;
133///
134/// hashAlg.hash128(d_data, d_length, &checksum1, &checksum2);
135///
136/// return (d_checksum1 == checksum1) && (d_checksum2 == checksum2);
137/// }
138/// @endcode
139/// Then, we store some data in our `CheckedData` class for safekeeping.
140/// @code
141///
142/// char data[] = "To be, or not to be--that is the question:"
143/// "Whether 'tis nobler in the mind to suffer"
144/// "The slings and arrows of outrageous fortune"
145/// "Or to take arms against a sea of troubles"
146/// "And by opposing end them. To die, to sleep--"
147/// "No more--and by a sleep to say we end"
148/// "The heartache, and the thousand natural shocks"
149/// "That flesh is heir to. 'Tis a consummation"
150/// "Devoutly to be wished. To die, to sleep--"
151/// "To sleep--perchance to dream: ay, there's the rub,"
152/// "For in that sleep of death what dreams may come"
153/// "When we have shuffled off this mortal coil,"
154/// "Must give us pause. There's the respect"
155/// "That makes calamity of so long life."
156/// "For who would bear the whips and scorns of time,"
157/// "Th' oppressor's wrong, the proud man's contumely"
158/// "The pangs of despised love, the law's delay,"
159/// "The insolence of office, and the spurns"
160/// "That patient merit of th' unworthy takes,"
161/// "When he himself might his quietus make"
162/// "With a bare bodkin? Who would fardels bear,"
163/// "To grunt and sweat under a weary life,"
164/// "But that the dread of something after death,"
165/// "The undiscovered country, from whose bourn"
166/// "No traveller returns, puzzles the will,"
167/// "And makes us rather bear those ills we have"
168/// "Than fly to others that we know not of?"
169/// "Thus conscience does make cowards of us all,"
170/// "And thus the native hue of resolution"
171/// "Is sicklied o'er with the pale cast of thought,"
172/// "And enterprise of great pitch and moment"
173/// "With this regard their currents turn awry"
174/// "And lose the name of action. -- Soft you now,"
175/// "The fair Ophelia! -- Nymph, in thy orisons"
176/// "Be all my sins remembered.";
177/// CheckedData checkedData(data, strlen(data));
178///
179/// @endcode
180/// Now, we check that the `CheckedData` recognizes that it is still valid.
181/// @code
182///
183/// ASSERT(checkedData.isDataValid());
184///
185/// @endcode
186/// Finally, we tamper with the data and check that our `CheckedData` class can
187/// detect this.
188/// @code
189/// data[34] = 'z';
190/// ASSERT(!checkedData.isDataValid());
191/// @endcode
192///
193/// ## Changes {#bslh_spookyhashalgorithmimp-changes}
194///
195///
196/// The third party code begins with the "SpookyHash" header below, and
197/// continues until the BloombergLP copyright notice. Changes made to the
198/// original code include:
199///
200/// 1. Added `BloombergLP` and `bslh` namespaces
201/// 2. Renamed `SpookyHash` to `SpookyHashAlgorithmImp`
202/// 3. Removed usage of `stdint.h` (which might not be available on all
203/// platforms) and updated associated `typedef`s
204/// 4. Added `include` guards
205/// 5. Made some methods private
206/// 6. Reformatted comments and added comments
207/// 7. Updated indenting to BDE style
208/// 8. Moved `typedef`s within class
209/// 9. Changed C-style casts to @ref static_cast s
210/// 10. Reordered methods according to BDE style
211/// 11. Added inline to `Hash32` and `Hash64`
212/// 12. Changed static constants to `enum`s to avoid storage overhead
213/// 13. Added constructor in place of `init`
214/// 14. Made function names lower case (had to change `Final` to `finalize` and
215/// `Short` to `shortHash` to avoid using a keyword)
216/// 15. Reformatted comments
217/// 16. Replaced some uses of 'inline' with the new
218/// `BSLH_SPOOKYHASHALGORITHMIMP_INLINE` macro, which forces inlining on GCC
219///
220/// ## Third-Party Documentation {#bslh_spookyhashalgorithmimp-third-party-documentation}
221///
222///
223/// @code
224/// SpookyHash: a 128-bit non cryptographic hash function
225///
226/// By Bob Jenkins, public domain
227/// Oct 31 2010: alpha, framework + SpookyHash::Mix appears right
228/// Oct 31 2011: alpha again, Mix only good to 2^^69 but rest appears right
229/// Dec 31 2011: beta, improved Mix, tested it for 2-bit deltas
230/// Feb 2 2012: production, same bits as beta
231/// Feb 5 2012: adjusted definitions of uint* to be more portable
232/// Mar 30 2012: 3 bytes/cycle, not 4. Alpha was 4 but wasn't thorough enough.
233/// August 5 2012: SpookyV2 (different results)
234///
235/// Up to 3 bytes/cycle for long messages. Reasonably fast for short messages.
236/// All 1 or 2 bit deltas achieve avalanche within 1% bias per output bit.
237///
238/// This was developed for and tested on 64-bit x86-compatible processors. It
239/// assumes the processor is little-endian. There is a macro controlling
240/// whether unaligned reads are allowed (by default they are). This should be
241/// an equally good hash on big-endian machines, but it will compute different
242/// results on them than on little-endian machines.
243///
244/// Google's CityHash has similar specs to SpookyHash, and CityHash is faster on
245/// new Intel boxes. MD4 and MD5 also have similar specs, but they are orders
246/// of magnitude slower. CRCs are two or more times slower, but unlike
247/// SpookyHash, they have nice math for combining the CRCs of pieces to form the
248/// CRCs of wholes. There are also cryptographic hashes, but those are even
249/// slower than MD5.
250/// @endcode
251/// @}
252/** @} */
253/** @} */
254
255/** @addtogroup bsl
256 * @{
257 */
258/** @addtogroup bslh
259 * @{
260 */
261/** @addtogroup bslh_spookyhashalgorithmimp
262 * @{
263 */
264
265#include <bslscm_version.h>
266
267#include <bsls_assert.h>
268#include <bsls_platform.h>
269#include <bsls_types.h>
270
271#include <stddef.h> // 'size_t'
272
273/// See implementation notes for the explanation of this macro.
274#if defined(BSLS_PLATFORM_CMP_GNU)
275#define BSLH_SPOOKYHASHALGORITHMIMP_INLINE \
276 inline __attribute__((always_inline))
277#else
278#define BSLH_SPOOKYHASHALGORITHMIMP_INLINE inline
279#endif
280
281
282
283namespace bslh {
284
285
286/// This class wraps an implementation of Bob Jenkin's "SpookyHash" in a
287/// BDE-style component. For more information, see
288/// http://burtleburtle.net/bob/hash/spooky.html .
289///
290/// See @ref bslh_spookyhashalgorithmimp
292
293 public:
295 typedef unsigned int Uint32;
296 typedef unsigned short Uint16;
297 typedef unsigned char Uint8;
298
299 private:
300 // DATA
301
302 /// Number of 64-bit integers used in the internal state.
303 enum { k_NUM_VARS = 12 };
304
305 /// Size of the internal state, in bytes.
306 enum { k_BLOCK_SIZE = k_NUM_VARS * 8 };
307
308 /// Size of buffer of unhashed data, in bytes.
309 enum { k_BUFFER_SIZE = k_BLOCK_SIZE * 2 };
310
311 // A non-zero, odd, constant that has an irregular distribution of 1's
312 // and 0's to be used in hashing calculations.
313 static const Uint64 sc_const = 0xdeadbeefdeadbeefULL;
314
315 Uint64 m_data[2 * k_NUM_VARS]; // unhashed data, for partial messages
316 Uint64 m_state[k_NUM_VARS]; // internal state of the hash
317 size_t m_length; // total length of the input so far
318 Uint8 m_remainder; // length of unhashed data stashed in m_data
319
320 // PRIVATE CLASS METHODS
321
322 /// Incorporate the first 12 bytes of the specified `data` into `h0`,
323 /// `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `h7`, `h8`, `h9`, `h10`, and
324 /// `h11`, and then mix the inputs together so that `h0` and `h1` are a
325 /// hash of all the inputs. Note that non-BDE-standard passing by
326 /// non-`const` reference is used here to remain consistent with the
327 /// cannonical implementation. The behavior is undefined unless `data`
328 /// points at least 8 bytes of initialized memory.
329 static void end(const Uint64 *data,
330 Uint64 &h0, Uint64 &h1, Uint64 &h2, Uint64 &h3,
331 Uint64 &h4, Uint64 &h5, Uint64 &h6, Uint64 &h7,
332 Uint64 &h8, Uint64 &h9, Uint64 &h10,Uint64 &h11);
333
334 /// Combine the specified `h0`, `h1`, `h2`, `h3`, `h4`, `h5`, `h6`,
335 /// `h7`, `h8`, `h9`, `h10`, and `h11` together so that `h0` and `h1`
336 /// will be a hash of all the inputs. Note that non-BDE-standard
337 /// passing by non-`const` reference is used here to remain consistent
338 /// with the cannonical implementation. The behavior is undefined
339 /// unless `data` points at least 8 bytes of initialized memory.
340 static void endPartial(Uint64 &h0, Uint64 &h1, Uint64 &h2, Uint64 &h3,
341 Uint64 &h4, Uint64 &h5, Uint64 &h6, Uint64 &h7,
342 Uint64 &h8, Uint64 &h9, Uint64 &h10,Uint64 &h11);
343
344 /// Thoroughly mix the first 12 bytes of the specified `data` into `s0`,
345 /// `s1`, `s2`, `s3`, `s4`, `s5`, `s6`, `s7`, `s8`, `s9`, `s10`, and
346 /// `s11`. This method should be used when the input is 96 bytes or
347 /// longer to prevent the loss of entropy, because the internal state of
348 /// `SpookyHashAlgorithmImp` is overwritten every 96 bytes. Note that
349 /// non-BDE-standard passing by non-`const` reference is used here to
350 /// remain consistent with the cannonical implementation. The behavior
351 /// is undefined unless `data` points at least 8 bytes of initialized
352 /// memory.
353 static void mix(const Uint64 *data,
354 Uint64 &s0, Uint64 &s1, Uint64 &s2, Uint64 &s3,
355 Uint64 &s4, Uint64 &s5, Uint64 &s6, Uint64 &s7,
356 Uint64 &s8, Uint64 &s9, Uint64 &s10, Uint64 &s11);
357
358 /// Return the specified `x` left rotated by `k` bits.
359 static Uint64 rot64(Uint64 x, int k);
360
361 /// Hash the specified `length` bytes of `message` using `hash1` and
362 /// `hash2` as seeds. Load the higher order bits of the resulting
363 /// 128-bit hash value into `hash1` and the lower order bits in `hash2`.
364 /// This method is meant to be used for messages less than 192 bytes in
365 /// length because of its lower startup cost. The behavior is undefined
366 /// unless `message` points at least `length` bytes of initialized
367 /// memory or `length` is zero, and both `hash1` and `hash2` point to
368 /// at least 8 bytes of initialized, modifiable, memory.
369 static void shortHash(const void *message,
370 size_t length,
371 Uint64 *hash1,
372 Uint64 *hash2);
373
374 /// Combine the specified `h0`, `h1`, `h2`, and `h3` together so that
375 /// `h0` and `h1` will be a hash of all the inputs. Note that
376 /// non-BDE-standard passing by non-`const` reference is used here to
377 /// remain consistent with the cannonical implementation.
378 static void shortEnd(Uint64 &h0, Uint64 &h1, Uint64 &h2, Uint64 &h3);
379
380 /// Thoroughly mix the specified `h0`, `h1`, `h2`, and `h3` so that each
381 /// bit of input contributes entropy to every bit of the final states of
382 /// `h0`, `h1`, `h2`, and `h3`. Note that non-BDE-standard passing by
383 /// non-`const` reference is used here to remain consistent with the
384 /// cannonical implementation.
385 static void shortMix(Uint64 &h0, Uint64 &h1, Uint64 &h2, Uint64 &h3);
386
387 // NOT IMPLEMENTED
388
389 /// Do not allow copy construction
390 SpookyHashAlgorithmImp(const SpookyHashAlgorithmImp& original);// = delete;
391
392 SpookyHashAlgorithmImp& operator=(const SpookyHashAlgorithmImp& rhs);
393 // = delete;
394 // Do not allow assignment
395
396 public:
397 // PUBLIC CLASS METHODS
398
399 /// Hash the specified `length` bytes of `message` using `seed` as a
400 /// seed. Return the resulting 32-bit hash. The behavior is undefined
401 /// unless `message` points at least `length` bytes of initialized
402 /// memory or `length` is zero.
403 static Uint32 hash32(const void *message,
404 size_t length,
405 Uint32 seed);
406
407 /// Hash the specified `length` bytes of `message` using `seed` as a
408 /// seed. Return the resulting 64-bit hash. The behavior is undefined
409 /// unless `message` points at least `length` bytes of initialized
410 /// memory or `length` is zero.
411 static Uint64 hash64(const void *message,
412 size_t length,
413 Uint64 seed);
414
415 /// Hash the specified `length` bytes of `message` using `hash1` and
416 /// `hash2` as seeds. Load the higher order bits of the resulting
417 /// 128-bit hash value into `hash1` and the lower order bits in `hash2`.
418 /// The behavior is undefined unless `message` points at least `length`
419 /// bytes of initialized memory or `length` is zero, and both `hash1`
420 /// and `hash2` point to at least 8 bytes of initialized, modifiable,
421 /// memory.
422 static void hash128(const void *message,
423 size_t length,
424 Uint64 *hash1,
425 Uint64 *hash2);
426
427 // CREATORS
428
429 /// Create a `bslh::SpookyHashAlgorithmImp`, initializing the internal
430 /// state of the object using the specified `seed1` and `seed2` as seeds
431 /// for the algorithm.
433
435 // Destroy this object.
436
437 // MANIPULATORS
438
439 /// Accumulate the specified `length` bytes of `message` into the
440 /// internal state of the algorithm. Accumulating bytes through
441 /// `Update` will produce the same result as hashing them all at once
442 /// through the `HashXX` static methods. The behavior is undefined
443 /// unless `message` points at least `length` bytes of initialized
444 /// memory or `length` is zero.
445 void update(const void *message, size_t length);
446
447 /// Load the finalized hash into the specified `hash1` and `hash2`.
448 /// `hash1` will contain the higher order bits of the hash and `hash2`
449 /// will contain the lower order bits. The internal state of the
450 /// algorithm will be modified, meaning that calling final multiple
451 /// times will result in different hash values being returned. The
452 /// returned hash will be the same as if `Hash128` had been called will
453 /// all of the accumulated data in one block. The behavior is undefined
454 /// unless both `hash1` and `hash2` point to 8 bytes of modifiable
455 /// memory. Note that a value will be returned even if `update` has not
456 /// been called.
457 void finalize(Uint64 *hash1, Uint64 *hash2);
458};
459
460// ============================================================================
461// INLINE DEFINITIONS
462// ============================================================================
463
464// PUBLIC CLASS METHODS
465inline
467 const void *message,
468 size_t length,
469 Uint32 seed)
470{
471 BSLS_ASSERT(0 != message || 0 == length);
472 Uint64 hash1 = seed, hash2 = seed;
473 hash128(message, length, &hash1, &hash2);
474 return static_cast<Uint32>(hash1);
475}
476
477inline
479 const void *message,
480 size_t length,
481 Uint64 seed)
482{
483 BSLS_ASSERT(0 != message || 0 == length);
484 Uint64 hash1 = seed;
485 hash128(message, length, &hash1, &seed);
486 return hash1;
487}
488
489// CREATORS
490inline
491SpookyHashAlgorithmImp::SpookyHashAlgorithmImp(Uint64 seed1, Uint64 seed2)
492: m_length(0)
493, m_remainder(0)
494{
495 m_state[0] = seed1;
496 m_state[1] = seed2;
497}
498
499// PRIVATE CLASS METHODS
501void SpookyHashAlgorithmImp::end(
502 const Uint64 *data,
503 Uint64 &h0, Uint64 &h1, Uint64 &h2, Uint64 &h3,
504 Uint64 &h4, Uint64 &h5, Uint64 &h6, Uint64 &h7,
505 Uint64 &h8, Uint64 &h9, Uint64 &h10,Uint64 &h11)
506{
507 BSLS_ASSERT(data);
508 h0 += data[0]; h1 += data[1]; h2 += data[2]; h3 += data[3];
509 h4 += data[4]; h5 += data[5]; h6 += data[6]; h7 += data[7];
510 h8 += data[8]; h9 += data[9]; h10 += data[10]; h11 += data[11];
511 endPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
512 endPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
513 endPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
514}
515
517void SpookyHashAlgorithmImp::endPartial(
518 Uint64 &h0, Uint64 &h1, Uint64 &h2, Uint64 &h3,
519 Uint64 &h4, Uint64 &h5, Uint64 &h6, Uint64 &h7,
520 Uint64 &h8, Uint64 &h9, Uint64 &h10,Uint64 &h11)
521{
522 h11+= h1; h2 ^= h11; h1 = rot64(h1,44);
523 h0 += h2; h3 ^= h0; h2 = rot64(h2,15);
524 h1 += h3; h4 ^= h1; h3 = rot64(h3,34);
525 h2 += h4; h5 ^= h2; h4 = rot64(h4,21);
526 h3 += h5; h6 ^= h3; h5 = rot64(h5,38);
527 h4 += h6; h7 ^= h4; h6 = rot64(h6,33);
528 h5 += h7; h8 ^= h5; h7 = rot64(h7,10);
529 h6 += h8; h9 ^= h6; h8 = rot64(h8,13);
530 h7 += h9; h10^= h7; h9 = rot64(h9,38);
531 h8 += h10; h11^= h8; h10= rot64(h10,53);
532 h9 += h11; h0 ^= h9; h11= rot64(h11,42);
533 h10+= h0; h1 ^= h10; h0 = rot64(h0,54);
534}
535
537void SpookyHashAlgorithmImp::mix(
538 const Uint64 *data,
539 Uint64 &s0, Uint64 &s1, Uint64 &s2, Uint64 &s3,
540 Uint64 &s4, Uint64 &s5, Uint64 &s6, Uint64 &s7,
541 Uint64 &s8, Uint64 &s9, Uint64 &s10,Uint64 &s11)
542{
543 BSLS_ASSERT(data);
544 s0 += data[0]; s2 ^= s10; s11 ^= s0; s0 = rot64(s0,11); s11 += s1;
545 s1 += data[1]; s3 ^= s11; s0 ^= s1; s1 = rot64(s1,32); s0 += s2;
546 s2 += data[2]; s4 ^= s0; s1 ^= s2; s2 = rot64(s2,43); s1 += s3;
547 s3 += data[3]; s5 ^= s1; s2 ^= s3; s3 = rot64(s3,31); s2 += s4;
548 s4 += data[4]; s6 ^= s2; s3 ^= s4; s4 = rot64(s4,17); s3 += s5;
549 s5 += data[5]; s7 ^= s3; s4 ^= s5; s5 = rot64(s5,28); s4 += s6;
550 s6 += data[6]; s8 ^= s4; s5 ^= s6; s6 = rot64(s6,39); s5 += s7;
551 s7 += data[7]; s9 ^= s5; s6 ^= s7; s7 = rot64(s7,57); s6 += s8;
552 s8 += data[8]; s10 ^= s6; s7 ^= s8; s8 = rot64(s8,55); s7 += s9;
553 s9 += data[9]; s11 ^= s7; s8 ^= s9; s9 = rot64(s9,54); s8 += s10;
554 s10 += data[10]; s0 ^= s8; s9 ^= s10; s10 = rot64(s10,22); s9 += s11;
555 s11 += data[11]; s1 ^= s9; s10 ^= s11; s11 = rot64(s11,46); s10 += s0;
556}
557
559SpookyHashAlgorithmImp::Uint64 SpookyHashAlgorithmImp::rot64(Uint64 x, int k)
560{
561 return (x << k) | (x >> (64 - k));
562}
563
565void SpookyHashAlgorithmImp::shortEnd(Uint64 &h0,
566 Uint64 &h1,
567 Uint64 &h2,
568 Uint64 &h3)
569{
570 h3 ^= h2; h2 = rot64(h2,15); h3 += h2;
571 h0 ^= h3; h3 = rot64(h3,52); h0 += h3;
572 h1 ^= h0; h0 = rot64(h0,26); h1 += h0;
573 h2 ^= h1; h1 = rot64(h1,51); h2 += h1;
574 h3 ^= h2; h2 = rot64(h2,28); h3 += h2;
575 h0 ^= h3; h3 = rot64(h3,9); h0 += h3;
576 h1 ^= h0; h0 = rot64(h0,47); h1 += h0;
577 h2 ^= h1; h1 = rot64(h1,54); h2 += h1;
578 h3 ^= h2; h2 = rot64(h2,32); h3 += h2;
579 h0 ^= h3; h3 = rot64(h3,25); h0 += h3;
580 h1 ^= h0; h0 = rot64(h0,63); h1 += h0;
581}
582
584void SpookyHashAlgorithmImp::shortMix(Uint64 &h0,
585 Uint64 &h1,
586 Uint64 &h2,
587 Uint64 &h3)
588{
589 h2 = rot64(h2,50); h2 += h3; h0 ^= h2;
590 h3 = rot64(h3,52); h3 += h0; h1 ^= h3;
591 h0 = rot64(h0,30); h0 += h1; h2 ^= h0;
592 h1 = rot64(h1,41); h1 += h2; h3 ^= h1;
593 h2 = rot64(h2,54); h2 += h3; h0 ^= h2;
594 h3 = rot64(h3,48); h3 += h0; h1 ^= h3;
595 h0 = rot64(h0,38); h0 += h1; h2 ^= h0;
596 h1 = rot64(h1,37); h1 += h2; h3 ^= h1;
597 h2 = rot64(h2,62); h2 += h3; h0 ^= h2;
598 h3 = rot64(h3,34); h3 += h0; h1 ^= h3;
599 h0 = rot64(h0,5); h0 += h1; h2 ^= h0;
600 h1 = rot64(h1,36); h1 += h2; h3 ^= h1;
601}
602
603} // close package namespace
604
605
606
607#undef BSLH_SPOOKYHASHALGORITHMIMP_INLINE
608#endif
609
610// ----------------------------------------------------------------------------
611// Copyright 2017 Bloomberg Finance L.P.
612//
613// Licensed under the Apache License, Version 2.0 (the "License");
614// you may not use this file except in compliance with the License.
615// You may obtain a copy of the License at
616//
617// http://www.apache.org/licenses/LICENSE-2.0
618//
619// Unless required by applicable law or agreed to in writing, software
620// distributed under the License is distributed on an "AS IS" BASIS,
621// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
622// See the License for the specific language governing permissions and
623// limitations under the License.
624// ----------------------------- END-OF-FILE ----------------------------------
625
626/** @} */
627/** @} */
628/** @} */
Definition bslh_spookyhashalgorithmimp.h:291
static Uint64 hash64(const void *message, size_t length, Uint64 seed)
Definition bslh_spookyhashalgorithmimp.h:478
unsigned int Uint32
Definition bslh_spookyhashalgorithmimp.h:295
void update(const void *message, size_t length)
bsls::Types::Uint64 Uint64
Definition bslh_spookyhashalgorithmimp.h:294
unsigned char Uint8
Definition bslh_spookyhashalgorithmimp.h:297
static Uint32 hash32(const void *message, size_t length, Uint32 seed)
Definition bslh_spookyhashalgorithmimp.h:466
static void hash128(const void *message, size_t length, Uint64 *hash1, Uint64 *hash2)
unsigned short Uint16
Definition bslh_spookyhashalgorithmimp.h:296
void finalize(Uint64 *hash1, Uint64 *hash2)
#define BSLH_SPOOKYHASHALGORITHMIMP_INLINE
See implementation notes for the explanation of this macro.
Definition bslh_spookyhashalgorithmimp.h:278
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
BSLS_KEYWORD_CONSTEXPR CONTAINER::value_type * data(CONTAINER &container)
Definition bslstl_iterator.h:1231
Definition bslh_defaulthashalgorithm.h:339
unsigned long long Uint64
Definition bsls_types.h:137