package halfsiphash import "encoding/binary" func rotl(x uint32, b uint) uint32 { return (x << b) | (x >> (32 - b)) } func sipround(v0, v1, v2, v3 *uint32) { *v0 += *v1 *v1 = rotl(*v1, 5) *v1 ^= *v0 *v0 = rotl(*v0, 16) *v2 += *v3 *v3 = rotl(*v3, 8) *v3 ^= *v2 *v0 += *v3 *v3 = rotl(*v3, 7) *v3 ^= *v0 *v2 += *v1 *v1 = rotl(*v1, 13) *v1 ^= *v2 *v2 = rotl(*v2, 16) } // Sum32 computes HalfSipHash-2-4 with an 8-byte key and returns a 4-byte hash. func Sum32(data []byte, key [8]byte) uint32 { k0 := binary.LittleEndian.Uint32(key[0:4]) k1 := binary.LittleEndian.Uint32(key[4:8]) v0 := uint32(0) ^ k0 v1 := uint32(0) ^ k1 v2 := uint32(0x6c796765) ^ k0 v3 := uint32(0x74656462) ^ k1 // Process full 4-byte blocks. nblocks := len(data) / 4 for i := 0; i < nblocks; i++ { m := binary.LittleEndian.Uint32(data[i*4:]) v3 ^= m for j := 0; j < 2; j++ { sipround(&v0, &v1, &v2, &v3) } v0 ^= m } // Process remaining bytes. b := uint32(len(data)) << 24 tail := data[nblocks*4:] switch len(tail) { case 3: b |= uint32(tail[2]) << 16 fallthrough case 2: b |= uint32(tail[1]) << 8 fallthrough case 1: b |= uint32(tail[0]) } v3 ^= b for i := 0; i < 2; i++ { sipround(&v0, &v1, &v2, &v3) } v0 ^= b v2 ^= 0xff for i := 0; i < 4; i++ { sipround(&v0, &v1, &v2, &v3) } return v1 ^ v3 }