tile38/vendor/github.com/pierrec/xxHash/xxHash32/xxHash32.go

206 lines
5.4 KiB
Go
Raw Permalink Normal View History

// Package xxHash32 implements the very fast xxHash hashing algorithm (32 bits version).
// (https://github.com/Cyan4973/xxHash/)
package xxHash32
import "hash"
const (
prime32_1 = 2654435761
prime32_2 = 2246822519
prime32_3 = 3266489917
prime32_4 = 668265263
prime32_5 = 374761393
)
type xxHash struct {
seed uint32
v1 uint32
v2 uint32
v3 uint32
v4 uint32
totalLen uint64
buf [16]byte
bufused int
}
// New returns a new Hash32 instance.
func New(seed uint32) hash.Hash32 {
xxh := &xxHash{seed: seed}
xxh.Reset()
return xxh
}
// Sum appends the current hash to b and returns the resulting slice.
// It does not change the underlying hash state.
func (xxh xxHash) Sum(b []byte) []byte {
h32 := xxh.Sum32()
return append(b, byte(h32), byte(h32>>8), byte(h32>>16), byte(h32>>24))
}
// Reset resets the Hash to its initial state.
func (xxh *xxHash) Reset() {
xxh.v1 = xxh.seed + prime32_1 + prime32_2
xxh.v2 = xxh.seed + prime32_2
xxh.v3 = xxh.seed
xxh.v4 = xxh.seed - prime32_1
xxh.totalLen = 0
xxh.bufused = 0
}
// Size returns the number of bytes returned by Sum().
func (xxh *xxHash) Size() int {
return 4
}
// BlockSize gives the minimum number of bytes accepted by Write().
func (xxh *xxHash) BlockSize() int {
return 1
}
// Write adds input bytes to the Hash.
// It never returns an error.
func (xxh *xxHash) Write(input []byte) (int, error) {
n := len(input)
m := xxh.bufused
xxh.totalLen += uint64(n)
r := len(xxh.buf) - m
if n < r {
copy(xxh.buf[m:], input)
xxh.bufused += len(input)
return n, nil
}
p := 0
if m > 0 {
// some data left from previous update
copy(xxh.buf[xxh.bufused:], input[:r])
xxh.bufused += len(input) - r
// fast rotl(13)
p32 := xxh.v1 + (uint32(xxh.buf[p+3])<<24|uint32(xxh.buf[p+2])<<16|uint32(xxh.buf[p+1])<<8|uint32(xxh.buf[p]))*prime32_2
xxh.v1 = (p32<<13 | p32>>19) * prime32_1
p += 4
p32 = xxh.v2 + (uint32(xxh.buf[p+3])<<24|uint32(xxh.buf[p+2])<<16|uint32(xxh.buf[p+1])<<8|uint32(xxh.buf[p]))*prime32_2
xxh.v2 = (p32<<13 | p32>>19) * prime32_1
p += 4
p32 = xxh.v3 + (uint32(xxh.buf[p+3])<<24|uint32(xxh.buf[p+2])<<16|uint32(xxh.buf[p+1])<<8|uint32(xxh.buf[p]))*prime32_2
xxh.v3 = (p32<<13 | p32>>19) * prime32_1
p += 4
p32 = xxh.v4 + (uint32(xxh.buf[p+3])<<24|uint32(xxh.buf[p+2])<<16|uint32(xxh.buf[p+1])<<8|uint32(xxh.buf[p]))*prime32_2
xxh.v4 = (p32<<13 | p32>>19) * prime32_1
p = r
xxh.bufused = 0
}
for n := n - 16; p <= n; {
p32 := xxh.v1 + (uint32(input[p+3])<<24|uint32(input[p+2])<<16|uint32(input[p+1])<<8|uint32(input[p]))*prime32_2
xxh.v1 = (p32<<13 | p32>>19) * prime32_1
p += 4
p32 = xxh.v2 + (uint32(input[p+3])<<24|uint32(input[p+2])<<16|uint32(input[p+1])<<8|uint32(input[p]))*prime32_2
xxh.v2 = (p32<<13 | p32>>19) * prime32_1
p += 4
p32 = xxh.v3 + (uint32(input[p+3])<<24|uint32(input[p+2])<<16|uint32(input[p+1])<<8|uint32(input[p]))*prime32_2
xxh.v3 = (p32<<13 | p32>>19) * prime32_1
p += 4
p32 = xxh.v4 + (uint32(input[p+3])<<24|uint32(input[p+2])<<16|uint32(input[p+1])<<8|uint32(input[p]))*prime32_2
xxh.v4 = (p32<<13 | p32>>19) * prime32_1
p += 4
}
copy(xxh.buf[xxh.bufused:], input[p:])
xxh.bufused += len(input) - p
return n, nil
}
// Sum32 returns the 32 bits Hash value.
func (xxh *xxHash) Sum32() uint32 {
h32 := uint32(xxh.totalLen)
if xxh.totalLen >= 16 {
h32 += ((xxh.v1 << 1) | (xxh.v1 >> 31)) +
((xxh.v2 << 7) | (xxh.v2 >> 25)) +
((xxh.v3 << 12) | (xxh.v3 >> 20)) +
((xxh.v4 << 18) | (xxh.v4 >> 14))
} else {
h32 += xxh.seed + prime32_5
}
p := 0
n := xxh.bufused
for n := n - 4; p <= n; p += 4 {
h32 += (uint32(xxh.buf[p+3])<<24 | uint32(xxh.buf[p+2])<<16 | uint32(xxh.buf[p+1])<<8 | uint32(xxh.buf[p])) * prime32_3
h32 = ((h32 << 17) | (h32 >> 15)) * prime32_4
}
for ; p < n; p++ {
h32 += uint32(xxh.buf[p]) * prime32_5
h32 = ((h32 << 11) | (h32 >> 21)) * prime32_1
}
h32 ^= h32 >> 15
h32 *= prime32_2
h32 ^= h32 >> 13
h32 *= prime32_3
h32 ^= h32 >> 16
return h32
}
// Checksum returns the 32bits Hash value.
func Checksum(input []byte, seed uint32) uint32 {
n := len(input)
h32 := uint32(n)
if n < 16 {
h32 += seed + prime32_5
} else {
v1 := seed + prime32_1 + prime32_2
v2 := seed + prime32_2
v3 := seed
v4 := seed - prime32_1
p := 0
for p <= n-16 {
v1 += (uint32(input[p+3])<<24 | uint32(input[p+2])<<16 | uint32(input[p+1])<<8 | uint32(input[p])) * prime32_2
v1 = (v1<<13 | v1>>19) * prime32_1
p += 4
v2 += (uint32(input[p+3])<<24 | uint32(input[p+2])<<16 | uint32(input[p+1])<<8 | uint32(input[p])) * prime32_2
v2 = (v2<<13 | v2>>19) * prime32_1
p += 4
v3 += (uint32(input[p+3])<<24 | uint32(input[p+2])<<16 | uint32(input[p+1])<<8 | uint32(input[p])) * prime32_2
v3 = (v3<<13 | v3>>19) * prime32_1
p += 4
v4 += (uint32(input[p+3])<<24 | uint32(input[p+2])<<16 | uint32(input[p+1])<<8 | uint32(input[p])) * prime32_2
v4 = (v4<<13 | v4>>19) * prime32_1
p += 4
}
input = input[p:]
n -= p
h32 += ((v1 << 1) | (v1 >> 31)) +
((v2 << 7) | (v2 >> 25)) +
((v3 << 12) | (v3 >> 20)) +
((v4 << 18) | (v4 >> 14))
}
p := 0
for p <= n-4 {
h32 += (uint32(input[p+3])<<24 | uint32(input[p+2])<<16 | uint32(input[p+1])<<8 | uint32(input[p])) * prime32_3
h32 = ((h32 << 17) | (h32 >> 15)) * prime32_4
p += 4
}
for p < n {
h32 += uint32(input[p]) * prime32_5
h32 = ((h32 << 11) | (h32 >> 21)) * prime32_1
p++
}
h32 ^= h32 >> 15
h32 *= prime32_2
h32 ^= h32 >> 13
h32 *= prime32_3
h32 ^= h32 >> 16
return h32
}