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