SipHashInline { public static long hash24_palindromic(long k0, long k1, byte[] data, int offset, int len) { long v0 = 0x736f6d6570736575L ^ k0; long v1 = 0x646f72616e646f6dL ^ k1; long v2 = 0x6c7967656e657261L ^ k0; long v3 = 0x7465646279746573L ^ k1; long m; int last = (2 * len) / 8 * 8; int idx = 0; int offset2 = offset + len + len - 1; int len8 = len - (len % 8); if (last > 0) { while (idx < len8) { m = UNSAFE.getLong(data, base + offset + idx); idx += 8; v3 ^= m; v0 += v1; v2 += v3; v1 = (v1 << 13) | v1 >>> 51; v3 = (v3 << 16) | v3 >>> 48; v1 ^= v0; v3 ^= v2; v0 = (v0 << 32) | v0 >>> 32; v2 += v1; v0 += v3; v1 = (v1 << 17) | v1 >>> 47; v3 = (v3 << 21) | v3 >>> 43; v1 ^= v2; v3 ^= v0; v2 = (v2 << 32) | v2 >>> 32; v0 += v1; v2 += v3; v1 = (v1 << 13) | v1 >>> 51; v3 = (v3 << 16) | v3 >>> 48; v1 ^= v0; v3 ^= v2; v0 = (v0 << 32) | v0 >>> 32; v2 += v1; v0 += v3; v1 = (v1 << 17) | v1 >>> 47; v3 = (v3 << 21) | v3 >>> 43; v1 ^= v2; v3 ^= v0; v2 = (v2 << 32) | v2 >>> 32; v0 ^= m; } { m = (data[offset + (idx >= len ? (len - 1 - (idx % len)) : idx)] & 0xffL); idx++; m |= (data[offset + (idx >= len ? (len - 1 - (idx % len)) : idx)] & 0xffL) << 8; idx++; m |= (data[offset + (idx >= len ? (len - 1 - (idx % len)) : idx)] & 0xffL) << 16; idx++; m |= (data[offset + (idx >= len ? (len - 1 - (idx % len)) : idx)] & 0xffL) << 24; idx++; m |= (data[offset + (idx >= len ? (len - 1 - (idx % len)) : idx)] & 0xffL) << 32; idx++; m |= (data[offset + (idx >= len ? (len - 1 - (idx % len)) : idx)] & 0xffL) << 40; idx++; m |= (data[offset + (idx >= len ? (len - 1 - (idx % len)) : idx)] & 0xffL) << 48; idx++; m |= (data[offset + (idx >= len ? (len - 1 - (idx % len)) : idx)] & 0xffL) << 56; idx++; v3 ^= m; v0 += v1; v2 += v3; v1 = (v1 << 13) | v1 >>> 51; v3 = (v3 << 16) | v3 >>> 48; v1 ^= v0; v3 ^= v2; v0 = (v0 << 32) | v0 >>> 32; v2 += v1; v0 += v3; v1 = (v1 << 17) | v1 >>> 47; v3 = (v3 << 21) | v3 >>> 43; v1 ^= v2; v3 ^= v0; v2 = (v2 << 32) | v2 >>> 32; v0 += v1; v2 += v3; v1 = (v1 << 13) | v1 >>> 51; v3 = (v3 << 16) | v3 >>> 48; v1 ^= v0; v3 ^= v2; v0 = (v0 << 32) | v0 >>> 32; v2 += v1; v0 += v3; v1 = (v1 << 17) | v1 >>> 47; v3 = (v3 << 21) | v3 >>> 43; v1 ^= v2; v3 ^= v0; v2 = (v2 << 32) | v2 >>> 32; v0 ^= m; } while (idx < last) { m = Long.reverseBytes(UNSAFE.getLong(data, base + offset2 - (idx + 7))); idx += 8; v3 ^= m; v0 += v1; v2 += v3; v1 = (v1 << 13) | v1 >>> 51; v3 = (v3 << 16) | v3 >>> 48; v1 ^= v0; v3 ^= v2; v0 = (v0 << 32) | v0 >>> 32; v2 += v1; v0 += v3; v1 = (v1 << 17) | v1 >>> 47; v3 = (v3 << 21) | v3 >>> 43; v1 ^= v2; v3 ^= v0; v2 = (v2 << 32) | v2 >>> 32; v0 += v1; v2 += v3; v1 = (v1 << 13) | v1 >>> 51; v3 = (v3 << 16) | v3 >>> 48; v1 ^= v0; v3 ^= v2; v0 = (v0 << 32) | v0 >>> 32; v2 += v1; v0 += v3; v1 = (v1 << 17) | v1 >>> 47; v3 = (v3 << 21) | v3 >>> 43; v1 ^= v2; v3 ^= v0; v2 = (v2 << 32) | v2 >>> 32; v0 ^= m; } } m = 0; if (0 != idx) { int i = 0; while (i < (len * 2 - idx)) { m <<= 8; m |= data[offset + i] & 0xffL; i++; } } else { for (int i = 0; i < len * 2; i++) { m <<= 8; m |= data[offset + (i >= len ? (len - 1 - (i % len)) : i)] & 0xffL; } } m |= (long) (len * 2) << 56; v3 ^= m; v0 += v1; v2 += v3; v1 = (v1 << 13) | v1 >>> 51; v3 = (v3 << 16) | v3 >>> 48; v1 ^= v0; v3 ^= v2; v0 = (v0 << 32) | v0 >>> 32; v2 += v1; v0 += v3; v1 = (v1 << 17) | v1 >>> 47; v3 = (v3 << 21) | v3 >>> 43; v1 ^= v2; v3 ^= v0; v2 = (v2 << 32) | v2 >>> 32; v0 += v1; v2 += v3; v1 = (v1 << 13) | v1 >>> 51; v3 = (v3 << 16) | v3 >>> 48; v1 ^= v0; v3 ^= v2; v0 = (v0 << 32) | v0 >>> 32; v2 += v1; v0 += v3; v1 = (v1 << 17) | v1 >>> 47; v3 = (v3 << 21) | v3 >>> 43; v1 ^= v2; v3 ^= v0; v2 = (v2 << 32) | v2 >>> 32; v0 ^= m; v2 ^= 0xff; v0 += v1; v2 += v3; v1 = (v1 << 13) | v1 >>> 51; v3 = (v3 << 16) | v3 >>> 48; v1 ^= v0; v3 ^= v2; v0 = (v0 << 32) | v0 >>> 32; v2 += v1; v0 += v3; v1 = (v1 << 17) | v1 >>> 47; v3 = (v3 << 21) | v3 >>> 43; v1 ^= v2; v3 ^= v0; v2 = (v2 << 32) | v2 >>> 32; v0 += v1; v2 += v3; v1 = (v1 << 13) | v1 >>> 51; v3 = (v3 << 16) | v3 >>> 48; v1 ^= v0; v3 ^= v2; v0 = (v0 << 32) | v0 >>> 32; v2 += v1; v0 += v3; v1 = (v1 << 17) | v1 >>> 47; v3 = (v3 << 21) | v3 >>> 43; v1 ^= v2; v3 ^= v0; v2 = (v2 << 32) | v2 >>> 32; v0 += v1; v2 += v3; v1 = (v1 << 13) | v1 >>> 51; v3 = (v3 << 16) | v3 >>> 48; v1 ^= v0; v3 ^= v2; v0 = (v0 << 32) | v0 >>> 32; v2 += v1; v0 += v3; v1 = (v1 << 17) | v1 >>> 47; v3 = (v3 << 21) | v3 >>> 43; v1 ^= v2; v3 ^= v0; v2 = (v2 << 32) | v2 >>> 32; v0 += v1; v2 += v3; v1 = (v1 << 13) | v1 >>> 51; v3 = (v3 << 16) | v3 >>> 48; v1 ^= v0; v3 ^= v2; v0 = (v0 << 32) | v0 >>> 32; v2 += v1; v0 += v3; v1 = (v1 << 17) | v1 >>> 47; v3 = (v3 << 21) | v3 >>> 43; v1 ^= v2; v3 ^= v0; v2 = (v2 << 32) | v2 >>> 32; return v0 ^ v1 ^ v2 ^ v3; }  static long hash24(byte[] key, byte[] data, int offset, int len); static long hash24(byte[] key, byte[] data, int offset, int len, boolean reversed); static long hash24(byte[] key, byte[] data); static long hash24(long k0, long k1, byte[] data, int offset, int len); static long hash24(long k0, long k1, byte[] data, int offset, int len, boolean reversed); static long hash24_palindromic(long k0, long k1, byte[] data, int offset, int len); static long hash24_palindromic(byte[] key, byte[] data, int offset, int len); static long hash24_palindromic(long k0, long k1, byte[] data); static long hash24_palindromic(byte[] key, byte[] data); static long[] getKey(byte[] key);  }
@Test public void testHash24_palindromic() { Random r = new Random(); int from = 1; int n = 100; int offset = 10; byte[] data = new byte[n + offset]; r.nextBytes(data); byte[] dblbuf = new byte[2 * n]; long k0 = r.nextLong(); long k1 = r.nextLong(); for (int i = from; i <= n; i++) { r.nextBytes(data); long palindromic = SipHashInline.hash24_palindromic(k0, k1, data, offset, i); for (int j = 0; j < i; j++) { dblbuf[j] = data[offset + j]; dblbuf[i + j] = data[offset + (i - 1) - j]; } long hash = SipHashInline.hash24(k0, k1, dblbuf, 0, i * 2); Assert.assertEquals(palindromic, hash); } }
@Test public void testHash24_palindromic_perf() { Random r = new Random(); byte[] data = new byte[100]; r.nextBytes(data); long k0 = r.nextLong(); long k1 = r.nextLong(); long nano = System.nanoTime(); for (int i = 0; i < 10000000; i++) { long hash = SipHashInline.hash24_palindromic(k0, k1, data, 0, data.length); } System.out.println((System.nanoTime() - nano) / 1000000.0D); }