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