]> git.proxmox.com Git - rustc.git/blob - src/librand/isaac.rs
New upstream version 1.22.1+dfsg1
[rustc.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 /// Initializes `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 /// Initializes `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(https://github.com/rust-lang/rfcs/issues/628)
547 // having next_u32 like this should be unnecessary
548 #[inline]
549 fn next_u32(&mut self) -> u32 {
550 self.next_u64() as u32
551 }
552
553 #[inline]
554 fn next_u64(&mut self) -> u64 {
555 if self.cnt == 0 {
556 // make some more numbers
557 self.isaac64();
558 }
559 self.cnt -= 1;
560
561 // See corresponding location in IsaacRng.next_u32 for
562 // explanation.
563 debug_assert!(self.cnt < RAND_SIZE_64);
564 self.rsl[(self.cnt % RAND_SIZE_64) as usize].0
565 }
566 }
567
568 impl<'a> SeedableRng<&'a [u64]> for Isaac64Rng {
569 fn reseed(&mut self, seed: &'a [u64]) {
570 // make the seed into [seed[0], seed[1], ..., seed[seed.len()
571 // - 1], 0, 0, ...], to fill rng.rsl.
572 let seed_iter = seed.iter().cloned().chain(repeat(0));
573
574 for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) {
575 *rsl_elem = w(seed_elem);
576 }
577 self.cnt = 0;
578 self.a = w(0);
579 self.b = w(0);
580 self.c = w(0);
581
582 self.init(true);
583 }
584
585 /// Create an ISAAC random number generator with a seed. This can
586 /// be any length, although the maximum number of elements used is
587 /// 256 and any more will be silently ignored. A generator
588 /// constructed with a given seed will generate the same sequence
589 /// of values as all other generators constructed with that seed.
590 fn from_seed(seed: &'a [u64]) -> Isaac64Rng {
591 let mut rng = EMPTY_64;
592 rng.reseed(seed);
593 rng
594 }
595 }
596
597 impl Rand for Isaac64Rng {
598 fn rand<R: Rng>(other: &mut R) -> Isaac64Rng {
599 let mut ret = EMPTY_64;
600 unsafe {
601 let ptr = ret.rsl.as_mut_ptr() as *mut u8;
602
603 let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE_64 * 8);
604 other.fill_bytes(slice);
605 }
606 ret.cnt = 0;
607 ret.a = w(0);
608 ret.b = w(0);
609 ret.c = w(0);
610
611 ret.init(true);
612 return ret;
613 }
614 }
615
616
617 #[cfg(test)]
618 mod tests {
619 use std::prelude::v1::*;
620
621 use {Rng, SeedableRng};
622 use super::{Isaac64Rng, IsaacRng};
623
624 #[test]
625 fn test_rng_32_rand_seeded() {
626 let s = ::test::rng().gen_iter::<u32>().take(256).collect::<Vec<u32>>();
627 let mut ra: IsaacRng = SeedableRng::from_seed(&s[..]);
628 let mut rb: IsaacRng = SeedableRng::from_seed(&s[..]);
629 assert!(ra.gen_ascii_chars()
630 .take(100)
631 .eq(rb.gen_ascii_chars().take(100)));
632 }
633 #[test]
634 fn test_rng_64_rand_seeded() {
635 let s = ::test::rng().gen_iter::<u64>().take(256).collect::<Vec<u64>>();
636 let mut ra: Isaac64Rng = SeedableRng::from_seed(&s[..]);
637 let mut rb: Isaac64Rng = SeedableRng::from_seed(&s[..]);
638 assert!(ra.gen_ascii_chars()
639 .take(100)
640 .eq(rb.gen_ascii_chars().take(100)));
641 }
642
643 #[test]
644 fn test_rng_32_seeded() {
645 let seed: &[_] = &[1, 23, 456, 7890, 12345];
646 let mut ra: IsaacRng = SeedableRng::from_seed(seed);
647 let mut rb: IsaacRng = SeedableRng::from_seed(seed);
648 assert!(ra.gen_ascii_chars()
649 .take(100)
650 .eq(rb.gen_ascii_chars().take(100)));
651 }
652 #[test]
653 fn test_rng_64_seeded() {
654 let seed: &[_] = &[1, 23, 456, 7890, 12345];
655 let mut ra: Isaac64Rng = SeedableRng::from_seed(seed);
656 let mut rb: Isaac64Rng = SeedableRng::from_seed(seed);
657 assert!(ra.gen_ascii_chars()
658 .take(100)
659 .eq(rb.gen_ascii_chars().take(100)));
660 }
661
662 #[test]
663 fn test_rng_32_reseed() {
664 let s = ::test::rng().gen_iter::<u32>().take(256).collect::<Vec<u32>>();
665 let mut r: IsaacRng = SeedableRng::from_seed(&s[..]);
666 let string1: String = r.gen_ascii_chars().take(100).collect();
667
668 r.reseed(&s);
669
670 let string2: String = r.gen_ascii_chars().take(100).collect();
671 assert_eq!(string1, string2);
672 }
673 #[test]
674 fn test_rng_64_reseed() {
675 let s = ::test::rng().gen_iter::<u64>().take(256).collect::<Vec<u64>>();
676 let mut r: Isaac64Rng = SeedableRng::from_seed(&s[..]);
677 let string1: String = r.gen_ascii_chars().take(100).collect();
678
679 r.reseed(&s);
680
681 let string2: String = r.gen_ascii_chars().take(100).collect();
682 assert_eq!(string1, string2);
683 }
684
685 #[test]
686 #[rustfmt_skip]
687 fn test_rng_32_true_values() {
688 let seed: &[_] = &[1, 23, 456, 7890, 12345];
689 let mut ra: IsaacRng = SeedableRng::from_seed(seed);
690 // Regression test that isaac is actually using the above vector
691 let v = (0..10).map(|_| ra.next_u32()).collect::<Vec<_>>();
692 assert_eq!(v,
693 vec![2558573138, 873787463, 263499565, 2103644246, 3595684709,
694 4203127393, 264982119, 2765226902, 2737944514, 3900253796]);
695
696 let seed: &[_] = &[12345, 67890, 54321, 9876];
697 let mut rb: IsaacRng = SeedableRng::from_seed(seed);
698 // skip forward to the 10000th number
699 for _ in 0..10000 {
700 rb.next_u32();
701 }
702
703 let v = (0..10).map(|_| rb.next_u32()).collect::<Vec<_>>();
704 assert_eq!(v,
705 vec![3676831399, 3183332890, 2834741178, 3854698763, 2717568474,
706 1576568959, 3507990155, 179069555, 141456972, 2478885421]);
707 }
708 #[test]
709 #[rustfmt_skip]
710 fn test_rng_64_true_values() {
711 let seed: &[_] = &[1, 23, 456, 7890, 12345];
712 let mut ra: Isaac64Rng = SeedableRng::from_seed(seed);
713 // Regression test that isaac is actually using the above vector
714 let v = (0..10).map(|_| ra.next_u64()).collect::<Vec<_>>();
715 assert_eq!(v,
716 vec![547121783600835980, 14377643087320773276, 17351601304698403469,
717 1238879483818134882, 11952566807690396487, 13970131091560099343,
718 4469761996653280935, 15552757044682284409, 6860251611068737823,
719 13722198873481261842]);
720
721 let seed: &[_] = &[12345, 67890, 54321, 9876];
722 let mut rb: Isaac64Rng = SeedableRng::from_seed(seed);
723 // skip forward to the 10000th number
724 for _ in 0..10000 {
725 rb.next_u64();
726 }
727
728 let v = (0..10).map(|_| rb.next_u64()).collect::<Vec<_>>();
729 assert_eq!(v,
730 vec![18143823860592706164, 8491801882678285927, 2699425367717515619,
731 17196852593171130876, 2606123525235546165, 15790932315217671084,
732 596345674630742204, 9947027391921273664, 11788097613744130851,
733 10391409374914919106]);
734
735 }
736
737 #[test]
738 fn test_rng_clone() {
739 let seed: &[_] = &[1, 23, 456, 7890, 12345];
740 let mut rng: Isaac64Rng = SeedableRng::from_seed(seed);
741 let mut clone = rng.clone();
742 for _ in 0..16 {
743 assert_eq!(rng.next_u64(), clone.next_u64());
744 }
745 }
746 }