SpookyHash64 { public static long hash(byte[] src, int start, int length, long seed) { if (length < SMALLHASH_LIMIT_BYTES) { return smallHash(src, start, length, seed); } long h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11; h0 = h3 = h6 = h9 = seed; h1 = h4 = h7 = h10 = seed; h2 = h5 = h8 = h11 = ARBITRARY_BITS; int remaining = length; int pos = start; while (remaining >= BLOCK_SIZE_BYTES) { h0 += packLong(src, pos); h2 ^= h10; h11 ^= h0; h0 = (h0 << 11) | (h0 >>> 53); h11 += h1; h1 += packLong(src, pos+8); h3 ^= h11; h0 ^= h1; h1 = (h1 << 32) | (h1 >>> 32); h0 += h2; h2 += packLong(src, pos+16); h4 ^= h0; h1 ^= h2; h2 = (h2 << 43) | (h2 >>> 21); h1 += h3; h3 += packLong(src, pos+24); h5 ^= h1; h2 ^= h3; h3 = (h3 << 31) | (h3 >>> 33); h2 += h4; h4 += packLong(src, pos+32); h6 ^= h2; h3 ^= h4; h4 = (h4 << 17) | (h4 >>> 47); h3 += h5; h5 += packLong(src, pos+40); h7 ^= h3; h4 ^= h5; h5 = (h5 << 28) | (h5 >>> 36); h4 += h6; h6 += packLong(src, pos+48); h8 ^= h4; h5 ^= h6; h6 = (h6 << 39) | (h6 >>> 25); h5 += h7; h7 += packLong(src, pos+56); h9 ^= h5; h6 ^= h7; h7 = (h7 << 57) | (h7 >>> 7); h6 += h8; h8 += packLong(src, pos+64); h10 ^= h6; h7 ^= h8; h8 = (h8 << 55) | (h8 >>> 9); h7 += h9; h9 += packLong(src, pos+72); h11 ^= h7; h8 ^= h9; h9 = (h9 << 54) | (h9 >>> 10); h8 += h10; h10 += packLong(src, pos+80); h0 ^= h8; h9 ^= h10; h10 = (h10 << 22) | (h10 >>> 42); h9 += h11; h11 += packLong(src, pos+88); h1 ^= h9; h10 ^= h11; h11 = (h11 << 46) | (h11 >>> 18); h10 += h0; remaining -= BLOCK_SIZE_BYTES; pos += BLOCK_SIZE_BYTES; } int partialSize = remaining & 7; int wholeWords = remaining >>> 3; if (partialSize > 0) { long partial = packPartial(src, pos + (wholeWords << 3), partialSize); switch (wholeWords) { case 0: h0 += partial; break; case 1: h1 += partial; break; case 2: h2 += partial; break; case 3: h3 += partial; break; case 4: h4 += partial; break; case 5: h5 += partial; break; case 6: h6 += partial; break; case 7: h7 += partial; break; case 8: h8 += partial; break; case 9: h9 += partial; break; case 10: h10 += partial; break; case 11: h11 += partial; break; } } switch (wholeWords) { case 11: h10 += packLong(src, pos+80); case 10: h9 += packLong(src, pos+72); case 9: h8 += packLong(src, pos+64); case 8: h7 += packLong(src, pos+56); case 7: h6 += packLong(src, pos+48); case 6: h5 += packLong(src, pos+40); case 5: h4 += packLong(src, pos+32); case 4: h3 += packLong(src, pos+24); case 3: h2 += packLong(src, pos+16); case 2: h1 += packLong(src, pos+8); case 1: h0 += packLong(src, pos); default: break; } h11 += ((long)remaining) << 56; for (int i = 0; i < 3; i++) { h11 += h1; h2 ^= h11; h1 = (h1 << 44) | (h1 >>> 20); h0 += h2; h3 ^= h0; h2 = (h2 << 15) | (h2 >>> 49); h1 += h3; h4 ^= h1; h3 = (h3 << 34) | (h3 >>> 30); h2 += h4; h5 ^= h2; h4 = (h4 << 21) | (h4 >>> 43); h3 += h5; h6 ^= h3; h5 = (h5 << 38) | (h5 >>> 26); h4 += h6; h7 ^= h4; h6 = (h6 << 33) | (h6 >>> 31); h5 += h7; h8 ^= h5; h7 = (h7 << 10) | (h7 >>> 54); h6 += h8; h9 ^= h6; h8 = (h8 << 13) | (h8 >>> 51); h7 += h9; h10 ^= h7; h9 = (h9 << 38) | (h9 >>> 26); h8 += h10; h11 ^= h8; h10 = (h10 << 53) | (h10 >>> 11); h9 += h11; h0 ^= h9; h11 = (h11 << 42) | (h11 >>> 22); h10 += h0; h1 ^= h10; h0 = (h0 << 54) | (h0 >>> 10); } return h0; } SpookyHash64();  SpookyHash64(long seed); static long hash(byte[] src, int start, int length, long seed); static long hash(CharSequence src, int start, int length, long seed); static long hash(long[] src, int start, int length,  long seed); static long hash(byte[] src, long seed); long hash(byte[] src, int start, int length); long hash(byte[] src); static long hash(CharSequence src, long seed); long hash(CharSequence src, int start, int length); long hash(CharSequence src); static long hash(long[] src, long seed); long hash(long[] src, int start, int length); long hash(long[] src);  }
@Test public void testHashByteArrayIntIntLongArray() { for (int i = 0; i < BUF_SIZE; i++) { long lsaw = SpookyHash64.hash(byteBuf, 0, i, 0L); lsaw &= 0x00000000ffffffffL; assertEquals(String.format("results %d: ", i), expected[i], lsaw); } }
@Test public void testHashCharSequenceIntIntLongArray() { for (int i = 0; i < BUF_SIZE; i+=2) { long lsaw =SpookyHash64.hash(charSeqBuf, 0, i/2, 0L); lsaw &= 0x00000000ffffffffL; assertEquals(String.format("results %d: ", i), expected[i], lsaw); } }
@Test public void testHashLongArrayIntIntLongArray() { for (int i = 0; i < BUF_SIZE; i+=8) { long lsaw = SpookyHash64.hash(longBuf, 0, i/8, 0L); lsaw &= 0x00000000ffffffffL; assertEquals(String.format("results %d: ", i), expected[i], lsaw); } }