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