...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package hashing
18
19 import (
20 "math/bits"
21 "unsafe"
22
23 "github.com/zeebo/xxh3"
24 )
25
26 func hashInt(val uint64, alg uint64) uint64 {
27
28
29 var multipliers = [2]uint64{11400714785074694791, 14029467366897019727}
30
31
32
33 return bits.ReverseBytes64(multipliers[alg] * val)
34 }
35
36 func hashFloat32(val float32, alg uint64) uint64 {
37
38 bt := *(*[4]byte)(unsafe.Pointer(&val))
39 x := uint64(*(*uint32)(unsafe.Pointer(&bt[0])))
40 hx := hashInt(x, alg)
41 hy := hashInt(x, alg^1)
42 return 4 ^ hx ^ hy
43 }
44
45 func hashFloat64(val float64, alg uint64) uint64 {
46 bt := *(*[8]byte)(unsafe.Pointer(&val))
47 hx := hashInt(uint64(*(*uint32)(unsafe.Pointer(&bt[4]))), alg)
48 hy := hashInt(uint64(*(*uint32)(unsafe.Pointer(&bt[0]))), alg^1)
49 return 8 ^ hx ^ hy
50 }
51
52
53 var exprimes = [2]uint64{1609587929392839161, 9650029242287828579}
54
55
56
57
58 func Hash(b []byte, alg uint64) uint64 {
59 n := uint32(len(b))
60 if n <= 16 {
61 switch {
62 case n > 8:
63
64
65 x := *(*uint64)(unsafe.Pointer(&b[n-8]))
66 y := *(*uint64)(unsafe.Pointer(&b[0]))
67 hx := hashInt(x, alg)
68 hy := hashInt(y, alg^1)
69 return uint64(n) ^ hx ^ hy
70 case n >= 4:
71
72
73
74
75 x := *(*uint32)(unsafe.Pointer(&b[n-4]))
76 y := *(*uint32)(unsafe.Pointer(&b[0]))
77 hx := hashInt(uint64(x), alg)
78 hy := hashInt(uint64(y), alg^1)
79 return uint64(n) ^ hx ^ hy
80 case n > 0:
81 x := uint32((n << 24) ^ (uint32(b[0]) << 16) ^ (uint32(b[n/2]) << 8) ^ uint32(b[n-1]))
82 return hashInt(uint64(x), alg)
83 case n == 0:
84 return 1
85 }
86 }
87
88
89 return xxh3.Hash(b) + exprimes[alg]
90 }
91
View as plain text