LCOV - code coverage report
Current view: top level - cmdline - spooky2.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 20 20 100.0 %
Date: 2026-04-29 15:04:44 Functions: 1 1 100.0 %

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

Generated by: LCOV version 1.0