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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
pub mod keccak;
use random::PI;
use memory::AnchoredRange;
pub fn hash_64(x: u64, byte_count: u32) -> u32 {
let y = x << 8 | (byte_count as u64);
let (a, b) = hash_raw_256(x, 0, 0, y);
a as u32
}
pub fn hash_128(x: u64, y: u64, byte_count: u32) -> u32 {
let z = y << 8 | (byte_count as u64);
let (a, b) = hash_raw_256(x, y, 0, z);
a as u32
}
pub fn hash_192(x: u64, y: u64, z: u64, byte_count: u32) -> u32 {
let w = x << 8 | (byte_count as u64);
let (a, b) = hash_raw_256(x, y, z, w);
a as u32
}
pub fn hash_256(x: u64, y: u64, z: u64, w: u64, byte_count: u32) -> u32 {
let v = w << 8 | (byte_count as u64);
let (a, b) = hash_raw_256(x, y, z, v);
a as u32
}
pub fn hash_raw_256(mut a: u64, mut b: u64, mut c: u64, mut d: u64) -> (u64, u64) {
a = a.wrapping_add(PI[0]); b = b.wrapping_add(PI[1]);
c = c.wrapping_add(PI[2]); d = d.wrapping_add(PI[3]);
let (e, f, g, h) = mix(a, b, c, d);
end(e, f, g, h)
}
pub fn mix(mut a: u64, mut b: u64, mut c: u64, mut d: u64) -> (u64, u64, u64, u64) {
c = c.rotate_left(50); c = c.wrapping_add(d); a ^= c;
d = d.rotate_left(52); d = d.wrapping_add(a); b ^= d;
a = a.rotate_left(30); a = a.wrapping_add(b); c ^= a;
b = b.rotate_left(41); b = b.wrapping_add(c); d ^= b;
c = c.rotate_left(54); c = c.wrapping_add(d); a ^= c;
d = d.rotate_left(48); d = d.wrapping_add(a); b ^= d;
a = a.rotate_left(38); a = a.wrapping_add(b); c ^= a;
b = b.rotate_left(37); b = b.wrapping_add(c); d ^= b;
c = c.rotate_left(62); c = c.wrapping_add(d); a ^= c;
d = d.rotate_left(34); d = d.wrapping_add(a); b ^= d;
a = a.rotate_left(5); a = a.wrapping_add(b); c ^= a;
b = b.rotate_left(36); b = b.wrapping_add(c); d ^= b;
(a, b, c, d)
}
pub fn end(mut a: u64, mut b: u64, mut c: u64, mut d: u64) -> (u64, u64) {
d ^= c; c = c.rotate_left(15); d = d.wrapping_add(c);
a ^= d; d = d.rotate_left(52); a = a.wrapping_add(d);
b ^= a; a = a.rotate_left(26); b = b.wrapping_add(a);
c ^= b; b = b.rotate_left(51); c = c.wrapping_add(b);
d ^= c; c = c.rotate_left(28); d = d.wrapping_add(c);
a ^= d; d = d.rotate_left(9); a = a.wrapping_add(d);
b ^= a; a = a.rotate_left(47); b = b.wrapping_add(a);
c ^= b; b = b.rotate_left(54); c = c.wrapping_add(b);
d ^= c; c = c.rotate_left(32); d = d.wrapping_add(c);
a ^= d; d = d.rotate_left(25); a = a.wrapping_add(d);
b ^= a; a = a.rotate_left(63); b = b.wrapping_add(a);
(a, b)
}
pub fn mix_range(units: AnchoredRange, state: (u64, u64, u64, u64)) -> (u64, u64, u64, u64) {
let u = units.anchored_line();
let unit_count = units.span() as i32;
let mut remain = unit_count;
let mut a: (u64, u64, u64, u64) = state;
let units_per_mix = if cfg!(target_pointer_width = "64") { 4 } else { 8 };
while remain > units_per_mix {
let idx = unit_count - remain;
if cfg!(target_pointer_width = "64") {
a.0 ^= u[idx + 0].u64();
a.1 ^= u[idx + 1].u64();
a.2 ^= u[idx + 2].u64();
a.3 ^= u[idx + 3].u64();
} else {
a.0 ^= (u[idx + 1].u64() << 32) | u[idx + 0].u64();
a.1 ^= (u[idx + 3].u64() << 32) | u[idx + 2].u64();
a.2 ^= (u[idx + 5].u64() << 32) | u[idx + 4].u64();
a.3 ^= (u[idx + 7].u64() << 32) | u[idx + 6].u64();
}
a = mix(a.0, a.1, a.2, a.3);
remain -= units_per_mix;
}
let idx = unit_count - remain;
if cfg!(target_pointer_width = "64") {
if remain > 0 { a.0 ^= u[idx + 0].u64(); }
if remain > 1 { a.1 ^= u[idx + 1].u64(); }
if remain > 2 { a.2 ^= u[idx + 2].u64(); }
if remain > 3 { a.3 ^= u[idx + 3].u64(); }
} else {
if remain > 0 { a.0 ^= u[idx + 0].u64(); }
if remain > 1 { a.0 ^= u[idx + 1].u64() << 32; }
if remain > 2 { a.1 ^= u[idx + 2].u64(); }
if remain > 3 { a.1 ^= u[idx + 3].u64() << 32; }
if remain > 4 { a.2 ^= u[idx + 4].u64(); }
if remain > 5 { a.2 ^= u[idx + 5].u64() << 32; }
if remain > 6 { a.3 ^= u[idx + 6].u64(); }
if remain > 7 { a.3 ^= u[idx + 7].u64() << 32; }
}
a = mix(a.0, a.1, a.2, a.3);
a
}