1package xxhash 2 3import "hash" 4 5const ( 6 prime32x1 uint32 = 2654435761 7 prime32x2 uint32 = 2246822519 8 prime32x3 uint32 = 3266489917 9 prime32x4 uint32 = 668265263 10 prime32x5 uint32 = 374761393 11 12 prime64x1 uint64 = 11400714785074694791 13 prime64x2 uint64 = 14029467366897019727 14 prime64x3 uint64 = 1609587929392839161 15 prime64x4 uint64 = 9650029242287828579 16 prime64x5 uint64 = 2870177450012600261 17 18 maxInt32 int32 = (1<<31 - 1) 19 20 // precomputed zero Vs for seed 0 21 zero64x1 = 0x60ea27eeadc0b5d6 22 zero64x2 = 0xc2b2ae3d27d4eb4f 23 zero64x3 = 0x0 24 zero64x4 = 0x61c8864e7a143579 25) 26 27func NewHash32() hash.Hash { return New32() } 28func NewHash64() hash.Hash { return New64() } 29 30// Checksum32 returns the checksum of the input data with the seed set to 0. 31func Checksum32(in []byte) uint32 { 32 return Checksum32S(in, 0) 33} 34 35// ChecksumString32 returns the checksum of the input data, without creating a copy, with the seed set to 0. 36func ChecksumString32(s string) uint32 { 37 return ChecksumString32S(s, 0) 38} 39 40type XXHash32 struct { 41 mem [16]byte 42 ln, memIdx int32 43 v1, v2, v3, v4 uint32 44 seed uint32 45} 46 47// Size returns the number of bytes Sum will return. 48func (xx *XXHash32) Size() int { 49 return 4 50} 51 52// BlockSize returns the hash's underlying block size. 53// The Write method must be able to accept any amount 54// of data, but it may operate more efficiently if all writes 55// are a multiple of the block size. 56func (xx *XXHash32) BlockSize() int { 57 return 16 58} 59 60// NewS32 creates a new hash.Hash32 computing the 32bit xxHash checksum starting with the specific seed. 61func NewS32(seed uint32) (xx *XXHash32) { 62 xx = &XXHash32{ 63 seed: seed, 64 } 65 xx.Reset() 66 return 67} 68 69// New32 creates a new hash.Hash32 computing the 32bit xxHash checksum starting with the seed set to 0. 70func New32() *XXHash32 { 71 return NewS32(0) 72} 73 74func (xx *XXHash32) Reset() { 75 xx.v1 = xx.seed + prime32x1 + prime32x2 76 xx.v2 = xx.seed + prime32x2 77 xx.v3 = xx.seed 78 xx.v4 = xx.seed - prime32x1 79 xx.ln, xx.memIdx = 0, 0 80} 81 82// Sum appends the current hash to b and returns the resulting slice. 83// It does not change the underlying hash state. 84func (xx *XXHash32) Sum(in []byte) []byte { 85 s := xx.Sum32() 86 return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s)) 87} 88 89// Checksum64 an alias for Checksum64S(in, 0) 90func Checksum64(in []byte) uint64 { 91 return Checksum64S(in, 0) 92} 93 94// ChecksumString64 returns the checksum of the input data, without creating a copy, with the seed set to 0. 95func ChecksumString64(s string) uint64 { 96 return ChecksumString64S(s, 0) 97} 98 99type XXHash64 struct { 100 v1, v2, v3, v4 uint64 101 seed uint64 102 ln uint64 103 mem [32]byte 104 memIdx int8 105} 106 107// Size returns the number of bytes Sum will return. 108func (xx *XXHash64) Size() int { 109 return 8 110} 111 112// BlockSize returns the hash's underlying block size. 113// The Write method must be able to accept any amount 114// of data, but it may operate more efficiently if all writes 115// are a multiple of the block size. 116func (xx *XXHash64) BlockSize() int { 117 return 32 118} 119 120// NewS64 creates a new hash.Hash64 computing the 64bit xxHash checksum starting with the specific seed. 121func NewS64(seed uint64) (xx *XXHash64) { 122 xx = &XXHash64{ 123 seed: seed, 124 } 125 xx.Reset() 126 return 127} 128 129// New64 creates a new hash.Hash64 computing the 64bit xxHash checksum starting with the seed set to 0x0. 130func New64() *XXHash64 { 131 return NewS64(0) 132} 133 134func (xx *XXHash64) Reset() { 135 xx.ln, xx.memIdx = 0, 0 136 xx.v1, xx.v2, xx.v3, xx.v4 = resetVs64(xx.seed) 137} 138 139// Sum appends the current hash to b and returns the resulting slice. 140// It does not change the underlying hash state. 141func (xx *XXHash64) Sum(in []byte) []byte { 142 s := xx.Sum64() 143 return append(in, byte(s>>56), byte(s>>48), byte(s>>40), byte(s>>32), byte(s>>24), byte(s>>16), byte(s>>8), byte(s)) 144} 145 146// force the compiler to use ROTL instructions 147 148func rotl32_1(x uint32) uint32 { return (x << 1) | (x >> (32 - 1)) } 149func rotl32_7(x uint32) uint32 { return (x << 7) | (x >> (32 - 7)) } 150func rotl32_11(x uint32) uint32 { return (x << 11) | (x >> (32 - 11)) } 151func rotl32_12(x uint32) uint32 { return (x << 12) | (x >> (32 - 12)) } 152func rotl32_13(x uint32) uint32 { return (x << 13) | (x >> (32 - 13)) } 153func rotl32_17(x uint32) uint32 { return (x << 17) | (x >> (32 - 17)) } 154func rotl32_18(x uint32) uint32 { return (x << 18) | (x >> (32 - 18)) } 155 156func rotl64_1(x uint64) uint64 { return (x << 1) | (x >> (64 - 1)) } 157func rotl64_7(x uint64) uint64 { return (x << 7) | (x >> (64 - 7)) } 158func rotl64_11(x uint64) uint64 { return (x << 11) | (x >> (64 - 11)) } 159func rotl64_12(x uint64) uint64 { return (x << 12) | (x >> (64 - 12)) } 160func rotl64_18(x uint64) uint64 { return (x << 18) | (x >> (64 - 18)) } 161func rotl64_23(x uint64) uint64 { return (x << 23) | (x >> (64 - 23)) } 162func rotl64_27(x uint64) uint64 { return (x << 27) | (x >> (64 - 27)) } 163func rotl64_31(x uint64) uint64 { return (x << 31) | (x >> (64 - 31)) } 164 165func mix64(h uint64) uint64 { 166 h ^= h >> 33 167 h *= prime64x2 168 h ^= h >> 29 169 h *= prime64x3 170 h ^= h >> 32 171 return h 172} 173 174func resetVs64(seed uint64) (v1, v2, v3, v4 uint64) { 175 if seed == 0 { 176 return zero64x1, zero64x2, zero64x3, zero64x4 177 } 178 return (seed + prime64x1 + prime64x2), (seed + prime64x2), (seed), (seed - prime64x1) 179} 180 181// borrowed from cespare 182func round64(h, v uint64) uint64 { 183 h += v * prime64x2 184 h = rotl64_31(h) 185 h *= prime64x1 186 return h 187} 188 189func mergeRound64(h, v uint64) uint64 { 190 v = round64(0, v) 191 h ^= v 192 h = h*prime64x1 + prime64x4 193 return h 194} 195