Skip to main content

rand_isaac/
isaac.rs

1// Copyright 2018 Developers of the Rand project.
2// Copyright 2013-2018 The Rust Project Developers.
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10//! The ISAAC random number generator.
11
12use core::num::Wrapping as w;
13use core::{convert::Infallible, fmt, slice};
14use rand_core::block::{BlockRng, Generator};
15use rand_core::{Rng, SeedableRng, TryRng, utils};
16#[cfg(feature = "serde")]
17use serde::{Deserialize, Serialize};
18
19#[allow(non_camel_case_types)]
20type w32 = w<u32>;
21
22const RAND_SIZE_LEN: usize = 8;
23const RAND_SIZE: usize = 1 << RAND_SIZE_LEN;
24
25/// A random number generator that uses the ISAAC algorithm.
26///
27/// ISAAC stands for "Indirection, Shift, Accumulate, Add, and Count" which are
28/// the principal bitwise operations employed. It is the most advanced of a
29/// series of array based random number generator designed by Robert Jenkins
30/// in 1996[^1][^2].
31///
32/// ISAAC is notably fast and produces excellent quality random numbers for
33/// non-cryptographic applications.
34///
35/// In spite of being designed with cryptographic security in mind, ISAAC hasn't
36/// been stringently cryptanalyzed and thus cryptographers do not
37/// consensually trust it to be secure. When looking for a secure RNG, prefer
38/// `Hc128Rng` from the [`rand_hc`] crate instead, which, like ISAAC, is an
39/// array-based RNG and one of the stream-ciphers selected by eSTREAM
40///
41/// In 2006 an improvement to ISAAC was suggested by Jean-Philippe Aumasson,
42/// named ISAAC+[^3]. But because the specification is not complete, because
43/// there is no good implementation, and because the suggested bias may not
44/// exist, it is not implemented here.
45///
46/// ## Overview of the ISAAC algorithm:
47/// (in pseudo-code)
48///
49/// ```text
50/// Input: a, b, c, s[256] // state
51/// Output: r[256]         // results
52///
53/// mix(a,i) = a ^ a << 13   if i = 0 mod 4
54///            a ^ a >>  6   if i = 1 mod 4
55///            a ^ a <<  2   if i = 2 mod 4
56///            a ^ a >> 16   if i = 3 mod 4
57///
58/// c = c + 1
59/// b = b + c
60///
61/// for i in 0..256 {
62///     x = s_[i]
63///     a = f(a,i) + s[i+128 mod 256]
64///     y = a + b + s[x>>2 mod 256]
65///     s[i] = y
66///     b = x + s[y>>10 mod 256]
67///     r[i] = b
68/// }
69/// ```
70///
71/// Numbers are generated in blocks of 256. This means the function above only
72/// runs once every 256 times you ask for a next random number. In all other
73/// circumstances the last element of the results array is returned.
74///
75/// ISAAC therefore needs a lot of memory, relative to other non-crypto RNGs.
76/// 2 * 256 * 4 = 2 kb to hold the state and results.
77///
78/// This implementation uses [`BlockRng`] to implement the [`Rng`] methods.
79///
80/// ## References
81/// [^1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number generator*](
82///       http://burtleburtle.net/bob/rand/isaacafa.html)
83///
84/// [^2]: Bob Jenkins, [*ISAAC and RC4*](
85///       http://burtleburtle.net/bob/rand/isaac.html)
86///
87/// [^3]: Jean-Philippe Aumasson, [*On the pseudo-random generator ISAAC*](
88///       https://eprint.iacr.org/2006/438)
89///
90/// [`rand_hc`]: https://docs.rs/rand_hc
91#[derive(Debug, Clone)]
92pub struct IsaacRng(BlockRng<IsaacCore>);
93
94impl TryRng for IsaacRng {
95    type Error = Infallible;
96
97    #[inline]
98    fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
99        Ok(self.0.next_word())
100    }
101
102    #[inline]
103    fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
104        Ok(self.0.next_u64_from_u32())
105    }
106
107    #[inline]
108    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
109        self.0.fill_bytes(dest);
110        Ok(())
111    }
112}
113
114impl SeedableRng for IsaacRng {
115    type Seed = <IsaacCore as SeedableRng>::Seed;
116
117    #[inline]
118    fn from_seed(seed: Self::Seed) -> Self {
119        IsaacRng(BlockRng::new(IsaacCore::from_seed(seed)))
120    }
121
122    /// Create an ISAAC random number generator using an `u64` as seed.
123    /// If `seed == 0` this will produce the same stream of random numbers as
124    /// the reference implementation when used unseeded.
125    #[inline]
126    fn seed_from_u64(seed: u64) -> Self {
127        IsaacRng(BlockRng::new(IsaacCore::seed_from_u64(seed)))
128    }
129
130    #[inline]
131    fn from_rng<R>(rng: &mut R) -> Self
132    where
133        R: Rng + ?Sized,
134    {
135        IsaacRng(BlockRng::new(IsaacCore::from_rng(rng)))
136    }
137
138    #[inline]
139    fn try_from_rng<S>(rng: &mut S) -> Result<Self, S::Error>
140    where
141        S: TryRng + ?Sized,
142    {
143        IsaacCore::try_from_rng(rng).map(|core| IsaacRng(BlockRng::new(core)))
144    }
145}
146
147#[cfg(feature = "serde")]
148mod serde_impls {
149    use super::{IsaacCore, IsaacRng, RAND_SIZE};
150    use core::fmt;
151    use rand_core::block::BlockRng;
152    use serde::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
153    use serde::ser::{Serialize, SerializeStruct, Serializer};
154
155    impl Serialize for IsaacRng {
156        fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
157            let mut state = serializer.serialize_struct("IsaacRng", 2)?;
158            state.serialize_field("core", &self.0.core)?;
159            state.serialize_field("results", self.0.remaining_results())?;
160            state.end()
161        }
162    }
163
164    struct Results {
165        results: [u32; RAND_SIZE],
166        len: usize,
167    }
168    impl Results {
169        fn to_rng(&self, core: IsaacCore) -> IsaacRng {
170            let results = &self.results[..self.len];
171            IsaacRng(BlockRng::reconstruct(core, results).unwrap())
172        }
173    }
174    struct ResultsVisitor;
175    impl<'de> Visitor<'de> for ResultsVisitor {
176        type Value = Results;
177
178        fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
179            write!(formatter, "") // TODO
180        }
181
182        fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
183            let mut results = [0u32; RAND_SIZE];
184            let mut len = 0;
185            while let Some(value) = seq.next_element()? {
186                if len >= results.len() {
187                    return Err(Error::invalid_length(
188                        len + 1,
189                        &("up to 256 elements" as &str),
190                    ));
191                }
192
193                results[len] = value;
194                len += 1;
195            }
196
197            Ok(Results { results, len })
198        }
199    }
200
201    impl<'de> Deserialize<'de> for Results {
202        fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
203            deserializer.deserialize_seq(ResultsVisitor)
204        }
205    }
206
207    #[derive(serde::Deserialize)]
208    #[serde(field_identifier, rename_all = "lowercase")]
209    enum Field {
210        Core,
211        Results,
212    }
213
214    struct IsaacVisitor;
215    impl<'de> Visitor<'de> for IsaacVisitor {
216        type Value = IsaacRng;
217
218        fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
219            write!(formatter, "") // TODO
220        }
221
222        fn visit_seq<V>(self, mut seq: V) -> Result<IsaacRng, V::Error>
223        where
224            V: SeqAccess<'de>,
225        {
226            let core = seq
227                .next_element()?
228                .ok_or_else(|| Error::invalid_length(0, &self))?;
229            let results: Results = seq
230                .next_element()?
231                .ok_or_else(|| Error::invalid_length(1, &self))?;
232
233            Ok(results.to_rng(core))
234        }
235
236        fn visit_map<V>(self, mut map: V) -> Result<IsaacRng, V::Error>
237        where
238            V: MapAccess<'de>,
239        {
240            let mut core = None;
241            let mut results: Option<Results> = None;
242            while let Some(key) = map.next_key()? {
243                match key {
244                    Field::Core => {
245                        if core.is_some() {
246                            return Err(Error::duplicate_field("core"));
247                        }
248                        core = Some(map.next_value()?);
249                    }
250                    Field::Results => {
251                        if results.is_some() {
252                            return Err(Error::duplicate_field("results"));
253                        }
254                        results = Some(map.next_value()?);
255                    }
256                }
257            }
258            let core = core.ok_or_else(|| Error::missing_field("core"))?;
259            let results = results.ok_or_else(|| Error::missing_field("results"))?;
260
261            Ok(results.to_rng(core))
262        }
263    }
264
265    impl<'de> Deserialize<'de> for IsaacRng {
266        fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
267            const FIELDS: &[&str] = &["core", "results"];
268            deserializer.deserialize_struct("IsaacRng", FIELDS, IsaacVisitor)
269        }
270    }
271}
272
273/// The core of [`IsaacRng`], used with [`BlockRng`].
274#[derive(Clone)]
275#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
276pub struct IsaacCore {
277    #[cfg_attr(feature = "serde", serde(with = "serde_arrays"))]
278    mem: [w32; RAND_SIZE],
279    a: w32,
280    b: w32,
281    c: w32,
282}
283
284// Custom Debug implementation that does not expose the internal state
285impl fmt::Debug for IsaacCore {
286    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
287        write!(f, "IsaacCore {{}}")
288    }
289}
290
291// Custom PartialEq implementation as it can't currently be derived from an array of size RAND_SIZE
292impl ::core::cmp::PartialEq for IsaacCore {
293    fn eq(&self, other: &IsaacCore) -> bool {
294        self.mem[..] == other.mem[..] && self.a == other.a && self.b == other.b && self.c == other.c
295    }
296}
297
298// Custom Eq implementation as it can't currently be derived from an array of size RAND_SIZE
299impl ::core::cmp::Eq for IsaacCore {}
300
301impl Generator for IsaacCore {
302    type Output = [u32; RAND_SIZE];
303
304    /// Refills the output buffer, `results`. See also the pseudocode description
305    /// of the algorithm in the `IsaacRng` documentation.
306    ///
307    /// Optimisations used (similar to the reference implementation):
308    ///
309    /// - The loop is unrolled 4 times, once for every constant of mix().
310    /// - The contents of the main loop are moved to a function `rngstep`, to
311    ///   reduce code duplication.
312    /// - We use local variables for a and b, which helps with optimisations.
313    /// - We split the main loop in two, one that operates over 0..128 and one
314    ///   over 128..256. This way we can optimise out the addition and modulus
315    ///   from `s[i+128 mod 256]`.
316    /// - We maintain one index `i` and add `m` or `m2` as base (m2 for the
317    ///   `s[i+128 mod 256]`), relying on the optimizer to turn it into pointer
318    ///   arithmetic.
319    /// - We fill `results` backwards. The reference implementation reads values
320    ///   from `results` in reverse. We read them in the normal direction, to
321    ///   make `fill_bytes` a memcopy. To maintain compatibility we fill in
322    ///   reverse.
323    #[rustfmt::skip]
324    fn generate(&mut self, results: &mut [u32; RAND_SIZE]) {
325        self.c += w(1);
326        // abbreviations
327        let mut a = self.a;
328        let mut b = self.b + self.c;
329        const MIDPOINT: usize = RAND_SIZE / 2;
330
331        #[inline]
332        fn ind(mem: &[w32; RAND_SIZE], v: w32, amount: usize) -> w32 {
333            let index = (v >> amount).0 as usize % RAND_SIZE;
334            mem[index]
335        }
336
337        #[inline]
338        fn rngstep(
339            mem: &mut [w32; RAND_SIZE],
340            results: &mut [u32; RAND_SIZE],
341            mix: w32,
342            a: &mut w32,
343            b: &mut w32,
344            base: usize,
345            m: usize,
346            m2: usize,
347        ) {
348            let x = mem[base + m];
349            *a = mix + mem[base + m2];
350            let y = *a + *b + ind(mem, x, 2);
351            mem[base + m] = y;
352            *b = x + ind(mem, y, 2 + RAND_SIZE_LEN);
353            results[RAND_SIZE - 1 - base - m] = b.0;
354        }
355
356        let mut m = 0;
357        let mut m2 = MIDPOINT;
358        for i in (0..MIDPOINT / 4).map(|i| i * 4) {
359            rngstep(&mut self.mem, results, a ^ (a << 13), &mut a, &mut b, i + 0, m, m2);
360            rngstep(&mut self.mem, results, a ^ (a >> 6 ),  &mut a, &mut b, i + 1, m, m2);
361            rngstep(&mut self.mem, results, a ^ (a << 2 ),  &mut a, &mut b, i + 2, m, m2);
362            rngstep(&mut self.mem, results, a ^ (a >> 16),  &mut a, &mut b, i + 3, m, m2);
363        }
364
365        m = MIDPOINT;
366        m2 = 0;
367        for i in (0..MIDPOINT / 4).map(|i| i * 4) {
368            rngstep(&mut self.mem, results, a ^ (a << 13), &mut a, &mut b, i + 0, m, m2);
369            rngstep(&mut self.mem, results, a ^ (a >> 6 ),  &mut a, &mut b, i + 1, m, m2);
370            rngstep(&mut self.mem, results, a ^ (a << 2 ),  &mut a, &mut b, i + 2, m, m2);
371            rngstep(&mut self.mem, results, a ^ (a >> 16),  &mut a, &mut b, i + 3, m, m2);
372        }
373
374        self.a = a;
375        self.b = b;
376    }
377}
378
379impl IsaacCore {
380    /// Create a new ISAAC random number generator.
381    ///
382    /// The author Bob Jenkins describes how to best initialize ISAAC here:
383    /// <https://rt.cpan.org/Public/Bug/Display.html?id=64324>
384    /// The answer is included here just in case:
385    ///
386    /// "No, you don't need a full 8192 bits of seed data. Normal key sizes will
387    /// do fine, and they should have their expected strength (eg a 40-bit key
388    /// will take as much time to brute force as 40-bit keys usually will). You
389    /// could fill the remainder with 0, but set the last array element to the
390    /// length of the key provided (to distinguish keys that differ only by
391    /// different amounts of 0 padding). You do still need to call `randinit()`
392    /// to make sure the initial state isn't uniform-looking."
393    /// "After publishing ISAAC, I wanted to limit the key to half the size of
394    /// `r[]`, and repeat it twice. That would have made it hard to provide a
395    /// key that sets the whole internal state to anything convenient. But I'd
396    /// already published it."
397    ///
398    /// And his answer to the question "For my code, would repeating the key
399    /// over and over to fill 256 integers be a better solution than
400    /// zero-filling, or would they essentially be the same?":
401    /// "If the seed is under 32 bytes, they're essentially the same, otherwise
402    /// repeating the seed would be stronger. randinit() takes a chunk of 32
403    /// bytes, mixes it, and combines that with the next 32 bytes, et cetera.
404    /// Then loops over all the elements the same way a second time."
405    #[inline]
406    fn init(mut mem: [w32; RAND_SIZE], rounds: u32) -> Self {
407        #[rustfmt::skip]
408        fn mix(a: &mut w32, b: &mut w32, c: &mut w32, d: &mut w32,
409               e: &mut w32, f: &mut w32, g: &mut w32, h: &mut w32) {
410            *a ^= *b << 11; *d += *a; *b += *c;
411            *b ^= *c >> 2;  *e += *b; *c += *d;
412            *c ^= *d << 8;  *f += *c; *d += *e;
413            *d ^= *e >> 16; *g += *d; *e += *f;
414            *e ^= *f << 10; *h += *e; *f += *g;
415            *f ^= *g >> 4;  *a += *f; *g += *h;
416            *g ^= *h << 8;  *b += *g; *h += *a;
417            *h ^= *a >> 9;  *c += *h; *a += *b;
418        }
419
420        // These numbers are the result of initializing a...h with the
421        // fractional part of the golden ratio in binary (0x9e3779b9)
422        // and applying mix() 4 times.
423        let mut a = w(0x1367df5a);
424        let mut b = w(0x95d90059);
425        let mut c = w(0xc3163e4b);
426        let mut d = w(0x0f421ad8);
427        let mut e = w(0xd92a4a78);
428        let mut f = w(0xa51a3c49);
429        let mut g = w(0xc4efea1b);
430        let mut h = w(0x30609119);
431
432        // Normally this should do two passes, to make all of the seed effect
433        // all of `mem`
434        for _ in 0..rounds {
435            for i in (0..RAND_SIZE / 8).map(|i| i * 8) {
436                a += mem[i];
437                b += mem[i + 1];
438                c += mem[i + 2];
439                d += mem[i + 3];
440                e += mem[i + 4];
441                f += mem[i + 5];
442                g += mem[i + 6];
443                h += mem[i + 7];
444                mix(
445                    &mut a, &mut b, &mut c, &mut d, &mut e, &mut f, &mut g, &mut h,
446                );
447                mem[i] = a;
448                mem[i + 1] = b;
449                mem[i + 2] = c;
450                mem[i + 3] = d;
451                mem[i + 4] = e;
452                mem[i + 5] = f;
453                mem[i + 6] = g;
454                mem[i + 7] = h;
455            }
456        }
457
458        Self {
459            mem,
460            a: w(0),
461            b: w(0),
462            c: w(0),
463        }
464    }
465}
466
467impl SeedableRng for IsaacCore {
468    type Seed = [u8; 32];
469
470    fn from_seed(seed: Self::Seed) -> Self {
471        let seed_u32: [u32; 8] = utils::read_words(&seed);
472        // Convert the seed to `Wrapping<u32>` and zero-extend to `RAND_SIZE`.
473        let mut seed_extended = [w(0); RAND_SIZE];
474        for (x, y) in seed_extended.iter_mut().zip(seed_u32.iter()) {
475            *x = w(*y);
476        }
477        Self::init(seed_extended, 2)
478    }
479
480    /// Create an ISAAC random number generator using an `u64` as seed.
481    /// If `seed == 0` this will produce the same stream of random numbers as
482    /// the reference implementation when used unseeded.
483    fn seed_from_u64(seed: u64) -> Self {
484        let mut key = [w(0); RAND_SIZE];
485        key[0] = w(seed as u32);
486        key[1] = w((seed >> 32) as u32);
487        // Initialize with only one pass.
488        // A second pass does not improve the quality here, because all of the
489        // seed was already available in the first round.
490        // Not doing the second pass has the small advantage that if
491        // `seed == 0` this method produces exactly the same state as the
492        // reference implementation when used unseeded.
493        Self::init(key, 1)
494    }
495
496    fn from_rng<R>(rng: &mut R) -> Self
497    where
498        R: Rng + ?Sized,
499    {
500        // Custom `from_rng` implementation that fills a seed with the same size
501        // as the entire state.
502        let mut seed = [w(0u32); RAND_SIZE];
503        unsafe {
504            let ptr = seed.as_mut_ptr() as *mut u8;
505
506            let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE * 4);
507            rng.fill_bytes(slice);
508        }
509        for i in seed.iter_mut() {
510            *i = w(i.0.to_le());
511        }
512
513        Self::init(seed, 2)
514    }
515
516    fn try_from_rng<R>(rng: &mut R) -> Result<Self, R::Error>
517    where
518        R: TryRng + ?Sized,
519    {
520        // Custom `from_rng` implementation that fills a seed with the same size
521        // as the entire state.
522        let mut seed = [w(0u32); RAND_SIZE];
523        unsafe {
524            let ptr = seed.as_mut_ptr() as *mut u8;
525
526            let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE * 4);
527            rng.try_fill_bytes(slice)?;
528        }
529        for i in seed.iter_mut() {
530            *i = w(i.0.to_le());
531        }
532
533        Ok(Self::init(seed, 2))
534    }
535}
536
537#[cfg(test)]
538mod test {
539    use super::IsaacRng;
540    use rand_core::{Rng, SeedableRng};
541
542    #[test]
543    fn test_isaac_construction() {
544        // Test that various construction techniques produce a working RNG.
545        let seed = [
546            1, 0, 0, 0, 23, 0, 0, 0, 200, 1, 0, 0, 210, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
547            0, 0, 0, 0, 0,
548        ];
549        let mut rng1 = IsaacRng::from_seed(seed);
550        assert_eq!(rng1.next_u32(), 2869442790);
551
552        let mut rng2 = IsaacRng::from_rng(&mut rng1);
553        assert_eq!(rng2.next_u32(), 3094074039);
554    }
555
556    #[test]
557    fn test_isaac_true_values_32() {
558        let seed = [
559            1, 0, 0, 0, 23, 0, 0, 0, 200, 1, 0, 0, 210, 30, 0, 0, 57, 48, 0, 0, 0, 0, 0, 0, 0, 0,
560            0, 0, 0, 0, 0, 0,
561        ];
562        let mut rng1 = IsaacRng::from_seed(seed);
563        let mut results = [0u32; 10];
564        for i in results.iter_mut() {
565            *i = rng1.next_u32();
566        }
567        let expected = [
568            2558573138, 873787463, 263499565, 2103644246, 3595684709, 4203127393, 264982119,
569            2765226902, 2737944514, 3900253796,
570        ];
571        assert_eq!(results, expected);
572
573        let seed = [
574            57, 48, 0, 0, 50, 9, 1, 0, 49, 212, 0, 0, 148, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
575            0, 0, 0, 0, 0, 0,
576        ];
577        let mut rng2 = IsaacRng::from_seed(seed);
578        // skip forward to the 10000th number
579        for _ in 0..10000 {
580            rng2.next_u32();
581        }
582
583        for i in results.iter_mut() {
584            *i = rng2.next_u32();
585        }
586        let expected = [
587            3676831399, 3183332890, 2834741178, 3854698763, 2717568474, 1576568959, 3507990155,
588            179069555, 141456972, 2478885421,
589        ];
590        assert_eq!(results, expected);
591    }
592
593    #[test]
594    fn test_isaac_true_values_64() {
595        // As above, using little-endian versions of above values
596        let seed = [
597            1, 0, 0, 0, 23, 0, 0, 0, 200, 1, 0, 0, 210, 30, 0, 0, 57, 48, 0, 0, 0, 0, 0, 0, 0, 0,
598            0, 0, 0, 0, 0, 0,
599        ];
600        let mut rng = IsaacRng::from_seed(seed);
601        let mut results = [0u64; 5];
602        for i in results.iter_mut() {
603            *i = rng.next_u64();
604        }
605        let expected = [
606            3752888579798383186,
607            9035083239252078381,
608            18052294697452424037,
609            11876559110374379111,
610            16751462502657800130,
611        ];
612        assert_eq!(results, expected);
613    }
614
615    #[test]
616    #[rustfmt::skip]
617    fn test_isaac_true_bytes() {
618        let seed = [
619            1, 0, 0, 0, 23, 0, 0, 0, 200, 1, 0, 0, 210, 30, 0, 0, 57, 48, 0, 0, 0, 0, 0, 0, 0, 0,
620            0, 0, 0, 0, 0, 0,
621        ];
622        let mut rng = IsaacRng::from_seed(seed);
623        let mut results = [0u8; 32];
624        rng.fill_bytes(&mut results);
625        // Same as first values in test_isaac_true_values as bytes in LE order
626        let expected = [82, 186, 128, 152, 71, 240, 20, 52,
627                        45, 175, 180, 15, 86, 16, 99, 125,
628                        101, 203, 81, 214, 97, 162, 134, 250,
629                        103, 78, 203, 15, 150, 3, 210, 164];
630        assert_eq!(results, expected);
631    }
632
633    #[test]
634    #[rustfmt::skip]
635    fn test_isaac_new_uninitialized() {
636        // Compare the results from initializing `IsaacRng` with
637        // `seed_from_u64(0)`, to make sure it is the same as the reference
638        // implementation when used uninitialized.
639        // Note: We only test the first 16 integers, not the full 256 of the
640        // first block.
641        let mut rng = IsaacRng::seed_from_u64(0);
642        let mut results = [0u32; 16];
643        for i in results.iter_mut() {
644            *i = rng.next_u32();
645        }
646        let expected: [u32; 16] = [
647            0x71D71FD2, 0xB54ADAE7, 0xD4788559, 0xC36129FA,
648            0x21DC1EA9, 0x3CB879CA, 0xD83B237F, 0xFA3CE5BD,
649            0x8D048509, 0xD82E9489, 0xDB452848, 0xCA20E846,
650            0x500F972E, 0x0EEFF940, 0x00D6B993, 0xBC12C17F];
651        assert_eq!(results, expected);
652    }
653
654    #[test]
655    fn test_isaac_clone() {
656        let seed = [
657            1, 0, 0, 0, 23, 0, 0, 0, 200, 1, 0, 0, 210, 30, 0, 0, 57, 48, 0, 0, 0, 0, 0, 0, 0, 0,
658            0, 0, 0, 0, 0, 0,
659        ];
660        let mut rng1 = IsaacRng::from_seed(seed);
661        let mut rng2 = rng1.clone();
662        for _ in 0..16 {
663            assert_eq!(rng1.next_u32(), rng2.next_u32());
664        }
665    }
666
667    #[test]
668    #[cfg(feature = "serde")]
669    fn test_isaac_serde() {
670        let seed = [
671            1, 0, 0, 0, 23, 0, 0, 0, 200, 1, 0, 0, 210, 30, 0, 0, 57, 48, 0, 0, 0, 0, 0, 0, 0, 0,
672            0, 0, 0, 0, 0, 0,
673        ];
674        let mut rng = IsaacRng::from_seed(seed);
675
676        // discard some results
677        let _ = rng.next_u64();
678        let _ = rng.next_u32();
679
680        let buf = postcard::to_allocvec(&rng).expect("Could not serialize");
681
682        let mut deserialized: IsaacRng = postcard::from_bytes(&buf).expect("Could not deserialize");
683
684        // more than the 256 buffered results
685        for _ in 0..300 {
686            assert_eq!(rng.next_u32(), deserialized.next_u32());
687        }
688    }
689}