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: 2017-11-06 22:14:04 Functions: 1 1 100.0 %

          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             : 

Generated by: LCOV version 1.13