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