// Written in 2012 by Dmitry Chestnykh. // // To the extent possible under law, the author have dedicated all copyright // and related and neighboring rights to this software to the public domain // worldwide. This software is distributed without any warranty. // http://creativecommons.org/publicdomain/zero/1.0/ // // Package siphash implements SipHash-2-4, a fast short-input PRF // created by Jean-Philippe Aumasson and Daniel J. Bernstein. package bbloom // Hash returns the 64-bit SipHash-2-4 of the given byte slice with two 64-bit // parts of 128-bit key: k0 and k1. func (bl Bloom) sipHash(p []byte) (l, h uint64) { // Initialization. v0 := uint64(8317987320269560794) // k0 ^ 0x736f6d6570736575 v1 := uint64(7237128889637516672) // k1 ^ 0x646f72616e646f6d v2 := uint64(7816392314733513934) // k0 ^ 0x6c7967656e657261 v3 := uint64(8387220255325274014) // k1 ^ 0x7465646279746573 t := uint64(len(p)) << 56 // Compression. for len(p) >= 8 { m := uint64(p[0]) | uint64(p[1])<<8 | uint64(p[2])<<16 | uint64(p[3])<<24 | uint64(p[4])<<32 | uint64(p[5])<<40 | uint64(p[6])<<48 | uint64(p[7])<<56 v3 ^= m // Round 1. v0 += v1 v1 = v1<<13 | v1>>51 v1 ^= v0 v0 = v0<<32 | v0>>32 v2 += v3 v3 = v3<<16 | v3>>48 v3 ^= v2 v0 += v3 v3 = v3<<21 | v3>>43 v3 ^= v0 v2 += v1 v1 = v1<<17 | v1>>47 v1 ^= v2 v2 = v2<<32 | v2>>32 // Round 2. v0 += v1 v1 = v1<<13 | v1>>51 v1 ^= v0 v0 = v0<<32 | v0>>32 v2 += v3 v3 = v3<<16 | v3>>48 v3 ^= v2 v0 += v3 v3 = v3<<21 | v3>>43 v3 ^= v0 v2 += v1 v1 = v1<<17 | v1>>47 v1 ^= v2 v2 = v2<<32 | v2>>32 v0 ^= m p = p[8:] } // Compress last block. switch len(p) { case 7: t |= uint64(p[6]) << 48 fallthrough case 6: t |= uint64(p[5]) << 40 fallthrough case 5: t |= uint64(p[4]) << 32 fallthrough case 4: t |= uint64(p[3]) << 24 fallthrough case 3: t |= uint64(p[2]) << 16 fallthrough case 2: t |= uint64(p[1]) << 8 fallthrough case 1: t |= uint64(p[0]) } v3 ^= t // Round 1. v0 += v1 v1 = v1<<13 | v1>>51 v1 ^= v0 v0 = v0<<32 | v0>>32 v2 += v3 v3 = v3<<16 | v3>>48 v3 ^= v2 v0 += v3 v3 = v3<<21 | v3>>43 v3 ^= v0 v2 += v1 v1 = v1<<17 | v1>>47 v1 ^= v2 v2 = v2<<32 | v2>>32 // Round 2. v0 += v1 v1 = v1<<13 | v1>>51 v1 ^= v0 v0 = v0<<32 | v0>>32 v2 += v3 v3 = v3<<16 | v3>>48 v3 ^= v2 v0 += v3 v3 = v3<<21 | v3>>43 v3 ^= v0 v2 += v1 v1 = v1<<17 | v1>>47 v1 ^= v2 v2 = v2<<32 | v2>>32 v0 ^= t // Finalization. v2 ^= 0xff // Round 1. v0 += v1 v1 = v1<<13 | v1>>51 v1 ^= v0 v0 = v0<<32 | v0>>32 v2 += v3 v3 = v3<<16 | v3>>48 v3 ^= v2 v0 += v3 v3 = v3<<21 | v3>>43 v3 ^= v0 v2 += v1 v1 = v1<<17 | v1>>47 v1 ^= v2 v2 = v2<<32 | v2>>32 // Round 2. v0 += v1 v1 = v1<<13 | v1>>51 v1 ^= v0 v0 = v0<<32 | v0>>32 v2 += v3 v3 = v3<<16 | v3>>48 v3 ^= v2 v0 += v3 v3 = v3<<21 | v3>>43 v3 ^= v0 v2 += v1 v1 = v1<<17 | v1>>47 v1 ^= v2 v2 = v2<<32 | v2>>32 // Round 3. v0 += v1 v1 = v1<<13 | v1>>51 v1 ^= v0 v0 = v0<<32 | v0>>32 v2 += v3 v3 = v3<<16 | v3>>48 v3 ^= v2 v0 += v3 v3 = v3<<21 | v3>>43 v3 ^= v0 v2 += v1 v1 = v1<<17 | v1>>47 v1 ^= v2 v2 = v2<<32 | v2>>32 // Round 4. v0 += v1 v1 = v1<<13 | v1>>51 v1 ^= v0 v0 = v0<<32 | v0>>32 v2 += v3 v3 = v3<<16 | v3>>48 v3 ^= v2 v0 += v3 v3 = v3<<21 | v3>>43 v3 ^= v0 v2 += v1 v1 = v1<<17 | v1>>47 v1 ^= v2 v2 = v2<<32 | v2>>32 // return v0 ^ v1 ^ v2 ^ v3 hash := v0 ^ v1 ^ v2 ^ v3 h = hash >> bl.shift l = hash << bl.shift >> bl.shift return l, h }