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