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