226 lines
3.5 KiB
Go
226 lines
3.5 KiB
Go
// 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
|
|
|
|
}
|