1#[derive(Default, Debug)]
26pub struct PerfectRng {
27 range: u64,
28 seed: u64,
29 rounds: usize,
30 a_bits: u32,
31 a_mask: u64,
32 b_mask: u64,
33}
34
35#[derive(Default, Debug)]
36pub struct PerfectRng32 {
37 range: u32,
38 seed: u32,
39 rounds: usize,
40 a_bits: u32,
41 a_mask: u32,
42 b_mask: u32,
43}
44
45fn count_bits(num: u64) -> u32 {
46 let mut bits = 0;
47 while (num >> bits) != 0 {
48 bits += 1;
49 }
50 bits
51}
52
53#[inline]
54fn sipround(mut v0: u64, mut v1: u64, mut v2: u64, mut v3: u64) -> (u64, u64, u64, u64) {
55 v0 = v0.wrapping_add(v1);
56 v2 = v2.wrapping_add(v3);
57 v1 = v1.rotate_left(13) ^ v0;
58 v3 = v3.rotate_left(16) ^ v2;
59 v0 = v0.rotate_left(32);
60
61 v2 = v2.wrapping_add(v1);
62 v0 = v0.wrapping_add(v3);
63 v1 = v1.rotate_left(17) ^ v2;
64 v3 = v3.rotate_left(21) ^ v0;
65 v2 = v2.rotate_left(32);
66
67 (v0, v1, v2, v3)
68}
69
70#[inline]
71fn sipround32(mut v0: u32, mut v1: u32, mut v2: u32, mut v3: u32) -> (u32, u32, u32, u32) {
72 v0 = v0.wrapping_add(v1);
73 v2 = v2.wrapping_add(v3);
74 v1 = v1.rotate_left(5) ^ v0;
75 v3 = v3.rotate_left(8) ^ v2;
76 v0 = v0.rotate_left(16);
77
78 v2 = v2.wrapping_add(v1);
79 v0 = v0.wrapping_add(v3);
80 v1 = v1.rotate_left(13) ^ v2;
81 v3 = v3.rotate_left(17) ^ v0;
82 v2 = v2.rotate_left(16);
83
84 (v0, v1, v2, v3)
85}
86
87impl PerfectRng {
88 #[must_use]
104 #[inline]
105 pub fn new(range: u64, seed: u64, rounds: usize) -> Self {
106 assert_ne!(range, 0);
107
108 let bits = count_bits(range - 1);
109 let b = bits / 2;
110 let a = bits - b;
112
113 PerfectRng {
114 range,
115 seed,
116 rounds,
117 a_bits: a,
118 a_mask: (1 << a) - 1,
119 b_mask: (1 << b) - 1,
120 }
121 }
122
123 #[must_use]
130 pub fn from_range(range: u64) -> Self {
131 Self::new(range, rand::random(), 4)
132 }
133
134 #[inline]
135 fn round(&self, j: usize, right: u64) -> u64 {
136 let v0 = self.seed;
137 let v1 = j as u64;
138 let v2 = right;
139 let v3: u64 = 0xf3016d19bc9ad940;
142
143 let (v0, v1, v2, v3) = sipround(v0, v1, v2, v3);
144 let (v0, v1, v2, v3) = sipround(v0, v1, v2, v3);
145 let (v0, v1, v2, v3) = sipround(v0, v1, v2, v3);
146 let (v0, _, _, _) = sipround(v0, v1, v2, v3);
147
148 v0
149 }
150
151 #[inline]
152 fn encrypt(&self, m: u64) -> u64 {
153 let mut left = m & self.a_mask;
154 let mut right = m >> self.a_bits;
155
156 let mut j = 1;
157 while j <= self.rounds {
158 if j % 2 != 0 {
159 let tmp = (left + self.round(j, right)) & self.a_mask;
160 left = right;
161 right = tmp;
162 j += 1;
163 } else {
164 let tmp = (left + self.round(j, right)) & self.b_mask;
165 left = right;
166 right = tmp;
167 j += 1;
168 }
169 }
170
171 if self.rounds % 2 != 0 {
172 (left << self.a_bits) + right
173 } else {
174 (right << self.a_bits) + left
175 }
176 }
177
178 #[must_use]
190 #[inline]
191 pub fn shuffle(&self, m: u64) -> u64 {
192 assert!(m < self.range);
193
194 let mut c = self.encrypt(m);
195 while c >= self.range {
196 c = self.encrypt(c);
197 }
198 c
199 }
200}
201
202impl PerfectRng32 {
203 #[must_use]
219 #[inline]
220 pub fn new(range: u32, seed: u32, rounds: usize) -> Self {
221 assert_ne!(range, 0);
222
223 let bits = count_bits((range - 1) as u64);
224 let b = bits / 2;
225 let a = bits - b;
227
228 PerfectRng32 {
229 range,
230 seed,
231 rounds,
232 a_bits: a,
233 a_mask: (1 << a) - 1,
234 b_mask: (1 << b) - 1,
235 }
236 }
237
238 #[must_use]
245 pub fn from_range(range: u32) -> Self {
246 Self::new(range, rand::random(), 4)
247 }
248
249 #[inline]
250 fn round(&self, j: usize, right: u32) -> u32 {
251 let v0 = self.seed;
252 let v1 = j as u32;
253 let v2 = right;
254 let v3: u32 = 0xbc9ad940;
257
258 let (v0, v1, v2, v3) = sipround32(v0, v1, v2, v3);
259 let (v0, v1, v2, v3) = sipround32(v0, v1, v2, v3);
260 let (v0, v1, v2, v3) = sipround32(v0, v1, v2, v3);
261 let (v0, _, _, _) = sipround32(v0, v1, v2, v3);
262
263 v0
264 }
265
266 #[inline]
267 fn encrypt(&self, m: u32) -> u32 {
268 let mut left = m & self.a_mask;
269 let mut right = m >> self.a_bits;
270
271 let mut j = 1;
272 while j <= self.rounds {
273 if j % 2 != 0 {
274 let tmp = (left + self.round(j, right)) & self.a_mask;
275 left = right;
276 right = tmp;
277 j += 1;
278 } else {
279 let tmp = (left + self.round(j, right)) & self.b_mask;
280 left = right;
281 right = tmp;
282 j += 1;
283 }
284 }
285
286 if self.rounds % 2 != 0 {
287 (left << self.a_bits) + right
288 } else {
289 (right << self.a_bits) + left
290 }
291 }
292
293 #[must_use]
305 #[inline]
306 pub fn shuffle(&self, m: u32) -> u32 {
307 assert!(m < self.range);
308
309 let mut c = self.encrypt(m);
310 while c >= self.range {
311 c = self.encrypt(c);
312 }
313 c
314 }
315}
316
317#[cfg(test)]
318mod tests {
319 use ntest::timeout;
320
321 use super::PerfectRng;
322
323 fn verify(range: u64, seed: u64, rounds: usize) {
324 let randomizer = PerfectRng::new(range, seed, rounds);
325 println!("randomizer: {randomizer:?}");
326
327 let mut list = vec![0; range as usize];
329 for i in 0..range {
330 let x = randomizer.shuffle(i) as usize;
331 list[x] += 1;
332 }
333
334 for (i, number) in list.into_iter().enumerate() {
335 assert_eq!(number, 1, "Index: {i}, range: {range:?}");
336 }
337 }
338
339 #[test]
340 #[timeout(1250)]
341 fn verify_ranges() {
342 let mut range = 3015 * 3;
343
344 for i in 0..5 {
345 range += 11 + i;
346 range *= 1 + i;
347
348 verify(range, 0, 6);
349 }
350
351 verify(10, 0, 4);
352 verify(100, 0, 4);
353 }
354
355 #[test]
356 #[timeout(100)]
357 fn dont_get_stuck() {
358 for range in [10, 100] {
359 for seed in 0..100 {
360 let randomizer = PerfectRng::new(range, seed, 4);
361
362 for i in 0..range {
363 let _ = randomizer.shuffle(i);
364 }
365 }
366 }
367 }
368
369 #[test]
370 fn sufficiently_random() {
371 let randomizer = PerfectRng::new(65536, 0, 4);
372 let mut inc = 0_u32;
373 let mut dec = 0_u32;
374 let mut prev = 0;
375
376 for i in 0..65535 {
377 let shuffled_i = randomizer.shuffle(i);
378 if shuffled_i > prev {
379 inc += 1;
380 } else {
381 dec += 1;
382 }
383 prev = shuffled_i;
384 }
385
386 assert!(
388 inc.abs_diff(dec) < 512,
389 "insufficiently random (inc: {inc}, dec: {dec})"
390 );
391 }
392}