]> git.lizzy.rs Git - rust.git/blob - src/librand/isaac.rs
rustfmt src/librand
[rust.git] / src / librand / isaac.rs
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! The ISAAC random number generator.
12
13 #![allow(non_camel_case_types)]
14
15 use core::slice;
16 use core::iter::repeat;
17 use core::num::Wrapping as w;
18
19 use {Rng, SeedableRng, Rand};
20
21 type w32 = w<u32>;
22 type w64 = w<u64>;
23
24 const RAND_SIZE_LEN: usize = 8;
25 const RAND_SIZE: u32 = 1 << RAND_SIZE_LEN;
26 const RAND_SIZE_USIZE: usize = 1 << RAND_SIZE_LEN;
27
28 /// A random number generator that uses the ISAAC algorithm[1].
29 ///
30 /// The ISAAC algorithm is generally accepted as suitable for
31 /// cryptographic purposes, but this implementation has not be
32 /// verified as such. Prefer a generator like `OsRng` that defers to
33 /// the operating system for cases that need high security.
34 ///
35 /// [1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number
36 /// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html)
37 #[derive(Copy)]
38 pub struct IsaacRng {
39     cnt: u32,
40     rsl: [w32; RAND_SIZE_USIZE],
41     mem: [w32; RAND_SIZE_USIZE],
42     a: w32,
43     b: w32,
44     c: w32,
45 }
46
47 static EMPTY: IsaacRng = IsaacRng {
48     cnt: 0,
49     rsl: [w(0); RAND_SIZE_USIZE],
50     mem: [w(0); RAND_SIZE_USIZE],
51     a: w(0),
52     b: w(0),
53     c: w(0),
54 };
55
56 impl IsaacRng {
57
58     /// Create an ISAAC random number generator using the default
59     /// fixed seed.
60     pub fn new_unseeded() -> IsaacRng {
61         let mut rng = EMPTY;
62         rng.init(false);
63         rng
64     }
65
66     /// Initialises `self`. If `use_rsl` is true, then use the current value
67     /// of `rsl` as a seed, otherwise construct one algorithmically (not
68     /// randomly).
69     fn init(&mut self, use_rsl: bool) {
70         let mut a = w(0x9e3779b9);
71         let mut b = a;
72         let mut c = a;
73         let mut d = a;
74         let mut e = a;
75         let mut f = a;
76         let mut g = a;
77         let mut h = a;
78
79         macro_rules! mix {
80             () => {{
81                 a=a^(b<<11); d=d+a; b=b+c;
82                 b=b^(c>>2);  e=e+b; c=c+d;
83                 c=c^(d<<8);  f=f+c; d=d+e;
84                 d=d^(e>>16); g=g+d; e=e+f;
85                 e=e^(f<<10); h=h+e; f=f+g;
86                 f=f^(g>>4);  a=a+f; g=g+h;
87                 g=g^(h<<8);  b=b+g; h=h+a;
88                 h=h^(a>>9);  c=c+h; a=a+b;
89             }}
90         }
91
92         for _ in 0..4 {
93             mix!();
94         }
95
96         if use_rsl {
97             macro_rules! memloop {
98                 ($arr:expr) => {{
99                     for i in (0..RAND_SIZE_USIZE).step_by(8) {
100                         a=a+$arr[i  ]; b=b+$arr[i+1];
101                         c=c+$arr[i+2]; d=d+$arr[i+3];
102                         e=e+$arr[i+4]; f=f+$arr[i+5];
103                         g=g+$arr[i+6]; h=h+$arr[i+7];
104                         mix!();
105                         self.mem[i  ]=a; self.mem[i+1]=b;
106                         self.mem[i+2]=c; self.mem[i+3]=d;
107                         self.mem[i+4]=e; self.mem[i+5]=f;
108                         self.mem[i+6]=g; self.mem[i+7]=h;
109                     }
110                 }}
111             }
112
113             memloop!(self.rsl);
114             memloop!(self.mem);
115         } else {
116             for i in (0..RAND_SIZE_USIZE).step_by(8) {
117                 mix!();
118                 self.mem[i] = a;
119                 self.mem[i + 1] = b;
120                 self.mem[i + 2] = c;
121                 self.mem[i + 3] = d;
122                 self.mem[i + 4] = e;
123                 self.mem[i + 5] = f;
124                 self.mem[i + 6] = g;
125                 self.mem[i + 7] = h;
126             }
127         }
128
129         self.isaac();
130     }
131
132     /// Refills the output buffer (`self.rsl`)
133     #[inline]
134     fn isaac(&mut self) {
135         self.c = self.c + w(1);
136         // abbreviations
137         let mut a = self.a;
138         let mut b = self.b + self.c;
139
140         const MIDPOINT: usize = RAND_SIZE_USIZE / 2;
141
142         macro_rules! ind {
143             ($x:expr) => (self.mem[($x >> 2).0 as usize & (RAND_SIZE_USIZE - 1)] )
144         }
145
146         let r = [(0, MIDPOINT), (MIDPOINT, 0)];
147         for &(mr_offset, m2_offset) in &r {
148
149             macro_rules! rngstepp {
150                 ($j:expr, $shift:expr) => {{
151                     let base = $j;
152                     let mix = a << $shift;
153
154                     let x = self.mem[base  + mr_offset];
155                     a = (a ^ mix) + self.mem[base + m2_offset];
156                     let y = ind!(x) + a + b;
157                     self.mem[base + mr_offset] = y;
158
159                     b = ind!(y >> RAND_SIZE_LEN) + x;
160                     self.rsl[base + mr_offset] = b;
161                 }}
162             }
163
164             macro_rules! rngstepn {
165                 ($j:expr, $shift:expr) => {{
166                     let base = $j;
167                     let mix = a >> $shift;
168
169                     let x = self.mem[base  + mr_offset];
170                     a = (a ^ mix) + self.mem[base + m2_offset];
171                     let y = ind!(x) + a + b;
172                     self.mem[base + mr_offset] = y;
173
174                     b = ind!(y >> RAND_SIZE_LEN) + x;
175                     self.rsl[base + mr_offset] = b;
176                 }}
177             }
178
179             for i in (0..MIDPOINT).step_by(4) {
180                 rngstepp!(i + 0, 13);
181                 rngstepn!(i + 1, 6);
182                 rngstepp!(i + 2, 2);
183                 rngstepn!(i + 3, 16);
184             }
185         }
186
187         self.a = a;
188         self.b = b;
189         self.cnt = RAND_SIZE;
190     }
191 }
192
193 // Cannot be derived because [u32; 256] does not implement Clone
194 impl Clone for IsaacRng {
195     fn clone(&self) -> IsaacRng {
196         *self
197     }
198 }
199
200 impl Rng for IsaacRng {
201     #[inline]
202     fn next_u32(&mut self) -> u32 {
203         if self.cnt == 0 {
204             // make some more numbers
205             self.isaac();
206         }
207         self.cnt -= 1;
208
209         // self.cnt is at most RAND_SIZE, but that is before the
210         // subtraction above. We want to index without bounds
211         // checking, but this could lead to incorrect code if someone
212         // misrefactors, so we check, sometimes.
213         //
214         // (Changes here should be reflected in Isaac64Rng.next_u64.)
215         debug_assert!(self.cnt < RAND_SIZE);
216
217         // (the % is cheaply telling the optimiser that we're always
218         // in bounds, without unsafe. NB. this is a power of two, so
219         // it optimises to a bitwise mask).
220         self.rsl[(self.cnt % RAND_SIZE) as usize].0
221     }
222 }
223
224 impl<'a> SeedableRng<&'a [u32]> for IsaacRng {
225     fn reseed(&mut self, seed: &'a [u32]) {
226         // make the seed into [seed[0], seed[1], ..., seed[seed.len()
227         // - 1], 0, 0, ...], to fill rng.rsl.
228         let seed_iter = seed.iter().cloned().chain(repeat(0));
229
230         for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) {
231             *rsl_elem = w(seed_elem);
232         }
233         self.cnt = 0;
234         self.a = w(0);
235         self.b = w(0);
236         self.c = w(0);
237
238         self.init(true);
239     }
240
241     /// Create an ISAAC random number generator with a seed. This can
242     /// be any length, although the maximum number of elements used is
243     /// 256 and any more will be silently ignored. A generator
244     /// constructed with a given seed will generate the same sequence
245     /// of values as all other generators constructed with that seed.
246     fn from_seed(seed: &'a [u32]) -> IsaacRng {
247         let mut rng = EMPTY;
248         rng.reseed(seed);
249         rng
250     }
251 }
252
253 impl Rand for IsaacRng {
254     fn rand<R: Rng>(other: &mut R) -> IsaacRng {
255         let mut ret = EMPTY;
256         unsafe {
257             let ptr = ret.rsl.as_mut_ptr() as *mut u8;
258
259             let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE_USIZE * 4);
260             other.fill_bytes(slice);
261         }
262         ret.cnt = 0;
263         ret.a = w(0);
264         ret.b = w(0);
265         ret.c = w(0);
266
267         ret.init(true);
268         return ret;
269     }
270 }
271
272 const RAND_SIZE_64_LEN: usize = 8;
273 const RAND_SIZE_64: usize = 1 << RAND_SIZE_64_LEN;
274
275 /// A random number generator that uses ISAAC-64[1], the 64-bit
276 /// variant of the ISAAC algorithm.
277 ///
278 /// The ISAAC algorithm is generally accepted as suitable for
279 /// cryptographic purposes, but this implementation has not be
280 /// verified as such. Prefer a generator like `OsRng` that defers to
281 /// the operating system for cases that need high security.
282 ///
283 /// [1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number
284 /// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html)
285 #[derive(Copy)]
286 pub struct Isaac64Rng {
287     cnt: usize,
288     rsl: [w64; RAND_SIZE_64],
289     mem: [w64; RAND_SIZE_64],
290     a: w64,
291     b: w64,
292     c: w64,
293 }
294
295 static EMPTY_64: Isaac64Rng = Isaac64Rng {
296     cnt: 0,
297     rsl: [w(0); RAND_SIZE_64],
298     mem: [w(0); RAND_SIZE_64],
299     a: w(0),
300     b: w(0),
301     c: w(0),
302 };
303
304 impl Isaac64Rng {
305     /// Create a 64-bit ISAAC random number generator using the
306     /// default fixed seed.
307     pub fn new_unseeded() -> Isaac64Rng {
308         let mut rng = EMPTY_64;
309         rng.init(false);
310         rng
311     }
312
313     /// Initialises `self`. If `use_rsl` is true, then use the current value
314     /// of `rsl` as a seed, otherwise construct one algorithmically (not
315     /// randomly).
316     fn init(&mut self, use_rsl: bool) {
317         macro_rules! init {
318             ($var:ident) => (
319                 let mut $var = w(0x9e3779b97f4a7c13);
320             )
321         }
322         init!(a);
323         init!(b);
324         init!(c);
325         init!(d);
326         init!(e);
327         init!(f);
328         init!(g);
329         init!(h);
330
331         macro_rules! mix {
332             () => {{
333                 a=a-e; f=f^(h>>9);  h=h+a;
334                 b=b-f; g=g^(a<<9);  a=a+b;
335                 c=c-g; h=h^(b>>23); b=b+c;
336                 d=d-h; a=a^(c<<15); c=c+d;
337                 e=e-a; b=b^(d>>14); d=d+e;
338                 f=f-b; c=c^(e<<20); e=e+f;
339                 g=g-c; d=d^(f>>17); f=f+g;
340                 h=h-d; e=e^(g<<14); g=g+h;
341             }}
342         }
343
344         for _ in 0..4 {
345             mix!();
346         }
347
348         if use_rsl {
349             macro_rules! memloop {
350                 ($arr:expr) => {{
351                     for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) {
352                         a=a+$arr[i  ]; b=b+$arr[i+1];
353                         c=c+$arr[i+2]; d=d+$arr[i+3];
354                         e=e+$arr[i+4]; f=f+$arr[i+5];
355                         g=g+$arr[i+6]; h=h+$arr[i+7];
356                         mix!();
357                         self.mem[i  ]=a; self.mem[i+1]=b;
358                         self.mem[i+2]=c; self.mem[i+3]=d;
359                         self.mem[i+4]=e; self.mem[i+5]=f;
360                         self.mem[i+6]=g; self.mem[i+7]=h;
361                     }
362                 }}
363             }
364
365             memloop!(self.rsl);
366             memloop!(self.mem);
367         } else {
368             for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) {
369                 mix!();
370                 self.mem[i] = a;
371                 self.mem[i + 1] = b;
372                 self.mem[i + 2] = c;
373                 self.mem[i + 3] = d;
374                 self.mem[i + 4] = e;
375                 self.mem[i + 5] = f;
376                 self.mem[i + 6] = g;
377                 self.mem[i + 7] = h;
378             }
379         }
380
381         self.isaac64();
382     }
383
384     /// Refills the output buffer (`self.rsl`)
385     fn isaac64(&mut self) {
386         self.c = self.c + w(1);
387         // abbreviations
388         let mut a = self.a;
389         let mut b = self.b + self.c;
390         const MIDPOINT: usize =  RAND_SIZE_64 / 2;
391         const MP_VEC: [(usize, usize); 2] = [(0, MIDPOINT), (MIDPOINT, 0)];
392         macro_rules! ind {
393             ($x:expr) => {
394                 *self.mem.get_unchecked((($x >> 3).0 as usize) & (RAND_SIZE_64 - 1))
395             }
396         }
397
398         for &(mr_offset, m2_offset) in &MP_VEC {
399             for base in (0..MIDPOINT / 4).map(|i| i * 4) {
400
401                 macro_rules! rngstepp {
402                     ($j:expr, $shift:expr) => {{
403                         let base = base + $j;
404                         let mix = a ^ (a << $shift);
405                         let mix = if $j == 0 {!mix} else {mix};
406
407                         unsafe {
408                             let x = *self.mem.get_unchecked(base + mr_offset);
409                             a = mix + *self.mem.get_unchecked(base + m2_offset);
410                             let y = ind!(x) + a + b;
411                             *self.mem.get_unchecked_mut(base + mr_offset) = y;
412
413                             b = ind!(y >> RAND_SIZE_64_LEN) + x;
414                             *self.rsl.get_unchecked_mut(base + mr_offset) = b;
415                         }
416                     }}
417                 }
418
419                 macro_rules! rngstepn {
420                     ($j:expr, $shift:expr) => {{
421                         let base = base + $j;
422                         let mix = a ^ (a >> $shift);
423                         let mix = if $j == 0 {!mix} else {mix};
424
425                         unsafe {
426                             let x = *self.mem.get_unchecked(base + mr_offset);
427                             a = mix + *self.mem.get_unchecked(base + m2_offset);
428                             let y = ind!(x) + a + b;
429                             *self.mem.get_unchecked_mut(base + mr_offset) = y;
430
431                             b = ind!(y >> RAND_SIZE_64_LEN) + x;
432                             *self.rsl.get_unchecked_mut(base + mr_offset) = b;
433                         }
434                     }}
435                 }
436
437                 rngstepp!(0, 21);
438                 rngstepn!(1, 5);
439                 rngstepp!(2, 12);
440                 rngstepn!(3, 33);
441             }
442         }
443
444         self.a = a;
445         self.b = b;
446         self.cnt = RAND_SIZE_64;
447     }
448 }
449
450 // Cannot be derived because [u32; 256] does not implement Clone
451 impl Clone for Isaac64Rng {
452     fn clone(&self) -> Isaac64Rng {
453         *self
454     }
455 }
456
457 impl Rng for Isaac64Rng {
458     // FIXME #7771: having next_u32 like this should be unnecessary
459     #[inline]
460     fn next_u32(&mut self) -> u32 {
461         self.next_u64() as u32
462     }
463
464     #[inline]
465     fn next_u64(&mut self) -> u64 {
466         if self.cnt == 0 {
467             // make some more numbers
468             self.isaac64();
469         }
470         self.cnt -= 1;
471
472         // See corresponding location in IsaacRng.next_u32 for
473         // explanation.
474         debug_assert!(self.cnt < RAND_SIZE_64);
475         self.rsl[(self.cnt % RAND_SIZE_64) as usize].0
476     }
477 }
478
479 impl<'a> SeedableRng<&'a [u64]> for Isaac64Rng {
480     fn reseed(&mut self, seed: &'a [u64]) {
481         // make the seed into [seed[0], seed[1], ..., seed[seed.len()
482         // - 1], 0, 0, ...], to fill rng.rsl.
483         let seed_iter = seed.iter().cloned().chain(repeat(0));
484
485         for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) {
486             *rsl_elem = w(seed_elem);
487         }
488         self.cnt = 0;
489         self.a = w(0);
490         self.b = w(0);
491         self.c = w(0);
492
493         self.init(true);
494     }
495
496     /// Create an ISAAC random number generator with a seed. This can
497     /// be any length, although the maximum number of elements used is
498     /// 256 and any more will be silently ignored. A generator
499     /// constructed with a given seed will generate the same sequence
500     /// of values as all other generators constructed with that seed.
501     fn from_seed(seed: &'a [u64]) -> Isaac64Rng {
502         let mut rng = EMPTY_64;
503         rng.reseed(seed);
504         rng
505     }
506 }
507
508 impl Rand for Isaac64Rng {
509     fn rand<R: Rng>(other: &mut R) -> Isaac64Rng {
510         let mut ret = EMPTY_64;
511         unsafe {
512             let ptr = ret.rsl.as_mut_ptr() as *mut u8;
513
514             let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE_64 * 8);
515             other.fill_bytes(slice);
516         }
517         ret.cnt = 0;
518         ret.a = w(0);
519         ret.b = w(0);
520         ret.c = w(0);
521
522         ret.init(true);
523         return ret;
524     }
525 }
526
527
528 #[cfg(test)]
529 mod tests {
530     use std::prelude::v1::*;
531
532     use core::iter::order;
533     use {Rng, SeedableRng};
534     use super::{IsaacRng, Isaac64Rng};
535
536     #[test]
537     fn test_rng_32_rand_seeded() {
538         let s = ::test::rng().gen_iter::<u32>().take(256).collect::<Vec<u32>>();
539         let mut ra: IsaacRng = SeedableRng::from_seed(&s[..]);
540         let mut rb: IsaacRng = SeedableRng::from_seed(&s[..]);
541         assert!(order::equals(ra.gen_ascii_chars().take(100),
542                               rb.gen_ascii_chars().take(100)));
543     }
544     #[test]
545     fn test_rng_64_rand_seeded() {
546         let s = ::test::rng().gen_iter::<u64>().take(256).collect::<Vec<u64>>();
547         let mut ra: Isaac64Rng = SeedableRng::from_seed(&s[..]);
548         let mut rb: Isaac64Rng = SeedableRng::from_seed(&s[..]);
549         assert!(order::equals(ra.gen_ascii_chars().take(100),
550                               rb.gen_ascii_chars().take(100)));
551     }
552
553     #[test]
554     fn test_rng_32_seeded() {
555         let seed: &[_] = &[1, 23, 456, 7890, 12345];
556         let mut ra: IsaacRng = SeedableRng::from_seed(seed);
557         let mut rb: IsaacRng = SeedableRng::from_seed(seed);
558         assert!(order::equals(ra.gen_ascii_chars().take(100),
559                               rb.gen_ascii_chars().take(100)));
560     }
561     #[test]
562     fn test_rng_64_seeded() {
563         let seed: &[_] = &[1, 23, 456, 7890, 12345];
564         let mut ra: Isaac64Rng = SeedableRng::from_seed(seed);
565         let mut rb: Isaac64Rng = SeedableRng::from_seed(seed);
566         assert!(order::equals(ra.gen_ascii_chars().take(100),
567                               rb.gen_ascii_chars().take(100)));
568     }
569
570     #[test]
571     fn test_rng_32_reseed() {
572         let s = ::test::rng().gen_iter::<u32>().take(256).collect::<Vec<u32>>();
573         let mut r: IsaacRng = SeedableRng::from_seed(&s[..]);
574         let string1: String = r.gen_ascii_chars().take(100).collect();
575
576         r.reseed(&s);
577
578         let string2: String = r.gen_ascii_chars().take(100).collect();
579         assert_eq!(string1, string2);
580     }
581     #[test]
582     fn test_rng_64_reseed() {
583         let s = ::test::rng().gen_iter::<u64>().take(256).collect::<Vec<u64>>();
584         let mut r: Isaac64Rng = SeedableRng::from_seed(&s[..]);
585         let string1: String = r.gen_ascii_chars().take(100).collect();
586
587         r.reseed(&s);
588
589         let string2: String = r.gen_ascii_chars().take(100).collect();
590         assert_eq!(string1, string2);
591     }
592
593     #[test]
594     fn test_rng_32_true_values() {
595         let seed: &[_] = &[1, 23, 456, 7890, 12345];
596         let mut ra: IsaacRng = SeedableRng::from_seed(seed);
597         // Regression test that isaac is actually using the above vector
598         let v = (0..10).map(|_| ra.next_u32()).collect::<Vec<_>>();
599         assert_eq!(v,
600                    vec!(2558573138,
601                         873787463,
602                         263499565,
603                         2103644246,
604                         3595684709,
605                         4203127393,
606                         264982119,
607                         2765226902,
608                         2737944514,
609                         3900253796));
610
611         let seed: &[_] = &[12345, 67890, 54321, 9876];
612         let mut rb: IsaacRng = SeedableRng::from_seed(seed);
613         // skip forward to the 10000th number
614         for _ in 0..10000 {
615             rb.next_u32();
616         }
617
618         let v = (0..10).map(|_| rb.next_u32()).collect::<Vec<_>>();
619         assert_eq!(v,
620                    vec!(3676831399,
621                         3183332890,
622                         2834741178,
623                         3854698763,
624                         2717568474,
625                         1576568959,
626                         3507990155,
627                         179069555,
628                         141456972,
629                         2478885421));
630     }
631     #[test]
632     fn test_rng_64_true_values() {
633         let seed: &[_] = &[1, 23, 456, 7890, 12345];
634         let mut ra: Isaac64Rng = SeedableRng::from_seed(seed);
635         // Regression test that isaac is actually using the above vector
636         let v = (0..10).map(|_| ra.next_u64()).collect::<Vec<_>>();
637         assert_eq!(v,
638                    vec!(547121783600835980,
639                         14377643087320773276,
640                         17351601304698403469,
641                         1238879483818134882,
642                         11952566807690396487,
643                         13970131091560099343,
644                         4469761996653280935,
645                         15552757044682284409,
646                         6860251611068737823,
647                         13722198873481261842));
648
649         let seed: &[_] = &[12345, 67890, 54321, 9876];
650         let mut rb: Isaac64Rng = SeedableRng::from_seed(seed);
651         // skip forward to the 10000th number
652         for _ in 0..10000 {
653             rb.next_u64();
654         }
655
656         let v = (0..10).map(|_| rb.next_u64()).collect::<Vec<_>>();
657         assert_eq!(v,
658                    vec!(18143823860592706164,
659                         8491801882678285927,
660                         2699425367717515619,
661                         17196852593171130876,
662                         2606123525235546165,
663                         15790932315217671084,
664                         596345674630742204,
665                         9947027391921273664,
666                         11788097613744130851,
667                         10391409374914919106));
668     }
669
670     #[test]
671     fn test_rng_clone() {
672         let seed: &[_] = &[1, 23, 456, 7890, 12345];
673         let mut rng: Isaac64Rng = SeedableRng::from_seed(seed);
674         let mut clone = rng.clone();
675         for _ in 0..16 {
676             assert_eq!(rng.next_u64(), clone.next_u64());
677         }
678     }
679 }