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