File: farmhashxo.go

package info (click to toggle)
golang-github-dgryski-go-farm 0.0~git20240924.3414d57-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental, forky, sid
  • size: 188 kB
  • sloc: asm: 871; makefile: 114
file content (104 lines) | stat: -rw-r--r-- 2,667 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package farm

import (
	"encoding/binary"
	"math/bits"
)

func h32(s []byte, mul uint64) uint64 {
	slen := len(s)
	a := binary.LittleEndian.Uint64(s[0:0+8]) * k1
	b := binary.LittleEndian.Uint64(s[8 : 8+8])
	c := binary.LittleEndian.Uint64(s[slen-8:slen-8+8]) * mul
	d := binary.LittleEndian.Uint64(s[slen-16:slen-16+8]) * k2
	u := bits.RotateLeft64(a+b, -43) + bits.RotateLeft64(c, -30) + d
	v := a + bits.RotateLeft64(b+k2, -18) + c
	a = shiftMix((u ^ v) * mul)
	b = shiftMix((v ^ a) * mul)
	return b
}

func h32Seeds(s []byte, mul, seed0, seed1 uint64) uint64 {
	slen := len(s)
	a := binary.LittleEndian.Uint64(s[0:0+8]) * k1
	b := binary.LittleEndian.Uint64(s[8 : 8+8])
	c := binary.LittleEndian.Uint64(s[slen-8:slen-8+8]) * mul
	d := binary.LittleEndian.Uint64(s[slen-16:slen-16+8]) * k2
	u := bits.RotateLeft64(a+b, -43) + bits.RotateLeft64(c, -30) + d + seed0
	v := a + bits.RotateLeft64(b+k2, -18) + c + seed1
	a = shiftMix((u ^ v) * mul)
	b = shiftMix((v ^ a) * mul)
	return b
}

func xohashLen33to64(s []byte) uint64 {
	slen := len(s)
	mul0 := k2 - 30
	mul1 := k2 - 30 + 2*uint64(slen)

	var h0 uint64
	{
		s := s[0:32]
		mul := mul0
		slen := len(s)
		a := binary.LittleEndian.Uint64(s[0:0+8]) * k1
		b := binary.LittleEndian.Uint64(s[8 : 8+8])
		c := binary.LittleEndian.Uint64(s[slen-8:slen-8+8]) * mul
		d := binary.LittleEndian.Uint64(s[slen-16:slen-16+8]) * k2
		u := bits.RotateLeft64(a+b, -43) + bits.RotateLeft64(c, -30) + d
		v := a + bits.RotateLeft64(b+k2, -18) + c
		a = shiftMix((u ^ v) * mul)
		b = shiftMix((v ^ a) * mul)
		h0 = b
	}

	var h1 uint64
	{
		s := s[slen-32:]
		mul := mul1
		slen := len(s)
		a := binary.LittleEndian.Uint64(s[0:0+8]) * k1
		b := binary.LittleEndian.Uint64(s[8 : 8+8])
		c := binary.LittleEndian.Uint64(s[slen-8:slen-8+8]) * mul
		d := binary.LittleEndian.Uint64(s[slen-16:slen-16+8]) * k2
		u := bits.RotateLeft64(a+b, -43) + bits.RotateLeft64(c, -30) + d
		v := a + bits.RotateLeft64(b+k2, -18) + c
		a = shiftMix((u ^ v) * mul)
		b = shiftMix((v ^ a) * mul)
		h1 = b
	}

	r := ((h1 * mul1) + h0) * mul1
	return r
}

func xohashLen65to96(s []byte) uint64 {
	slen := len(s)

	mul0 := k2 - 114
	mul1 := k2 - 114 + 2*uint64(slen)
	h0 := h32(s[:32], mul0)
	h1 := h32(s[32:64], mul1)
	h2 := h32Seeds(s[slen-32:], mul1, h0, h1)
	return (h2*9 + (h0 >> 17) + (h1 >> 21)) * mul1
}

func Hash64(s []byte) uint64 {
	slen := len(s)

	if slen <= 32 {
		if slen <= 16 {
			return hashLen0to16(s)
		} else {
			return hashLen17to32(s)
		}
	} else if slen <= 64 {
		return xohashLen33to64(s)
	} else if slen <= 96 {
		return xohashLen65to96(s)
	} else if slen <= 256 {
		return naHash64(s)
	} else {
		return uoHash64(s)
	}
}