-
Notifications
You must be signed in to change notification settings - Fork 0
/
marvin.go
78 lines (59 loc) · 1.66 KB
/
marvin.go
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
//go:build !amd64 || noasm || purego
package marvin32
import "math/bits"
func Sum32(seed uint64, data []byte) uint32 {
lo := uint32(seed)
hi := uint32(seed >> 32)
for len(data) >= 8 {
k1 := uint32(data[0]) | uint32(data[1])<<8 | uint32(data[2])<<16 | uint32(data[3])<<24
lo += k1
hi ^= lo
lo = bits.RotateLeft32(lo, 20) + hi
hi = bits.RotateLeft32(hi, 9) ^ lo
lo = bits.RotateLeft32(lo, 27) + hi
hi = bits.RotateLeft32(hi, 19)
k1 = uint32(data[4]) | uint32(data[5])<<8 | uint32(data[6])<<16 | uint32(data[7])<<24
lo += k1
hi ^= lo
lo = bits.RotateLeft32(lo, 20) + hi
hi = bits.RotateLeft32(hi, 9) ^ lo
lo = bits.RotateLeft32(lo, 27) + hi
hi = bits.RotateLeft32(hi, 19)
data = data[8:]
}
if len(data) >= 4 {
k1 := uint32(data[0]) | uint32(data[1])<<8 | uint32(data[2])<<16 | uint32(data[3])<<24
lo += k1
hi ^= lo
lo = bits.RotateLeft32(lo, 20) + hi
hi = bits.RotateLeft32(hi, 9) ^ lo
lo = bits.RotateLeft32(lo, 27) + hi
hi = bits.RotateLeft32(hi, 19)
data = data[4:]
}
/* pad the final 0-3 bytes with 0x80 */
var final uint32
switch len(data) {
case 3:
final = (0x80 << 24) | uint32(data[2])<<16 | uint32(data[1])<<8 | uint32(data[0])
case 2:
final = (0x80 << 16) | uint32(data[1])<<8 | uint32(data[0])
case 1:
final = (0x80 << 8) | uint32(data[0])
case 0:
final = 0x80
}
lo += final
hi ^= lo
lo = bits.RotateLeft32(lo, 20) + hi
hi = bits.RotateLeft32(hi, 9) ^ lo
lo = bits.RotateLeft32(lo, 27) + hi
hi = bits.RotateLeft32(hi, 19)
lo += 0
hi ^= lo
lo = bits.RotateLeft32(lo, 20) + hi
hi = bits.RotateLeft32(hi, 9) ^ lo
lo = bits.RotateLeft32(lo, 27) + hi
hi = bits.RotateLeft32(hi, 19)
return lo ^ hi
}