use core::num::Wrapping as w;
use core::{convert::Infallible, fmt, slice};
use rand_core::block::{BlockRng, Generator};
use rand_core::{Rng, SeedableRng, TryRng, utils};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[allow(non_camel_case_types)]
type w32 = w<u32>;
const RAND_SIZE_LEN: usize = 8;
const RAND_SIZE: usize = 1 << RAND_SIZE_LEN;
#[derive(Debug, Clone)]
pub struct IsaacRng(BlockRng<IsaacCore>);
impl TryRng for IsaacRng {
type Error = Infallible;
#[inline]
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
Ok(self.0.next_word())
}
#[inline]
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
Ok(self.0.next_u64_from_u32())
}
#[inline]
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
self.0.fill_bytes(dest);
Ok(())
}
}
impl SeedableRng for IsaacRng {
type Seed = <IsaacCore as SeedableRng>::Seed;
#[inline]
fn from_seed(seed: Self::Seed) -> Self {
IsaacRng(BlockRng::new(IsaacCore::from_seed(seed)))
}
#[inline]
fn seed_from_u64(seed: u64) -> Self {
IsaacRng(BlockRng::new(IsaacCore::seed_from_u64(seed)))
}
#[inline]
fn from_rng<R>(rng: &mut R) -> Self
where
R: Rng + ?Sized,
{
IsaacRng(BlockRng::new(IsaacCore::from_rng(rng)))
}
#[inline]
fn try_from_rng<S>(rng: &mut S) -> Result<Self, S::Error>
where
S: TryRng + ?Sized,
{
IsaacCore::try_from_rng(rng).map(|core| IsaacRng(BlockRng::new(core)))
}
}
#[cfg(feature = "serde")]
mod serde_impls {
use super::{IsaacCore, IsaacRng, RAND_SIZE};
use core::fmt;
use rand_core::block::BlockRng;
use serde::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
use serde::ser::{Serialize, SerializeStruct, Serializer};
impl Serialize for IsaacRng {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut state = serializer.serialize_struct("IsaacRng", 2)?;
state.serialize_field("core", &self.0.core)?;
state.serialize_field("results", self.0.remaining_results())?;
state.end()
}
}
struct Results {
results: [u32; RAND_SIZE],
len: usize,
}
impl Results {
fn to_rng(&self, core: IsaacCore) -> IsaacRng {
let results = &self.results[..self.len];
IsaacRng(BlockRng::reconstruct(core, results).unwrap())
}
}
struct ResultsVisitor;
impl<'de> Visitor<'de> for ResultsVisitor {
type Value = Results;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "") }
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let mut results = [0u32; RAND_SIZE];
let mut len = 0;
while let Some(value) = seq.next_element()? {
if len >= results.len() {
return Err(Error::invalid_length(
len + 1,
&("up to 256 elements" as &str),
));
}
results[len] = value;
len += 1;
}
Ok(Results { results, len })
}
}
impl<'de> Deserialize<'de> for Results {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
deserializer.deserialize_seq(ResultsVisitor)
}
}
#[derive(serde::Deserialize)]
#[serde(field_identifier, rename_all = "lowercase")]
enum Field {
Core,
Results,
}
struct IsaacVisitor;
impl<'de> Visitor<'de> for IsaacVisitor {
type Value = IsaacRng;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "") }
fn visit_seq<V>(self, mut seq: V) -> Result<IsaacRng, V::Error>
where
V: SeqAccess<'de>,
{
let core = seq
.next_element()?
.ok_or_else(|| Error::invalid_length(0, &self))?;
let results: Results = seq
.next_element()?
.ok_or_else(|| Error::invalid_length(1, &self))?;
Ok(results.to_rng(core))
}
fn visit_map<V>(self, mut map: V) -> Result<IsaacRng, V::Error>
where
V: MapAccess<'de>,
{
let mut core = None;
let mut results: Option<Results> = None;
while let Some(key) = map.next_key()? {
match key {
Field::Core => {
if core.is_some() {
return Err(Error::duplicate_field("core"));
}
core = Some(map.next_value()?);
}
Field::Results => {
if results.is_some() {
return Err(Error::duplicate_field("results"));
}
results = Some(map.next_value()?);
}
}
}
let core = core.ok_or_else(|| Error::missing_field("core"))?;
let results = results.ok_or_else(|| Error::missing_field("results"))?;
Ok(results.to_rng(core))
}
}
impl<'de> Deserialize<'de> for IsaacRng {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
const FIELDS: &[&str] = &["core", "results"];
deserializer.deserialize_struct("IsaacRng", FIELDS, IsaacVisitor)
}
}
}
#[derive(Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct IsaacCore {
#[cfg_attr(feature = "serde", serde(with = "serde_arrays"))]
mem: [w32; RAND_SIZE],
a: w32,
b: w32,
c: w32,
}
impl fmt::Debug for IsaacCore {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "IsaacCore {{}}")
}
}
impl ::core::cmp::PartialEq for IsaacCore {
fn eq(&self, other: &IsaacCore) -> bool {
self.mem[..] == other.mem[..] && self.a == other.a && self.b == other.b && self.c == other.c
}
}
impl ::core::cmp::Eq for IsaacCore {}
impl Generator for IsaacCore {
type Output = [u32; RAND_SIZE];
#[rustfmt::skip]
fn generate(&mut self, results: &mut [u32; RAND_SIZE]) {
self.c += w(1);
let mut a = self.a;
let mut b = self.b + self.c;
const MIDPOINT: usize = RAND_SIZE / 2;
#[inline]
fn ind(mem: &[w32; RAND_SIZE], v: w32, amount: usize) -> w32 {
let index = (v >> amount).0 as usize % RAND_SIZE;
mem[index]
}
#[inline]
fn rngstep(
mem: &mut [w32; RAND_SIZE],
results: &mut [u32; RAND_SIZE],
mix: w32,
a: &mut w32,
b: &mut w32,
base: usize,
m: usize,
m2: usize,
) {
let x = mem[base + m];
*a = mix + mem[base + m2];
let y = *a + *b + ind(mem, x, 2);
mem[base + m] = y;
*b = x + ind(mem, y, 2 + RAND_SIZE_LEN);
results[RAND_SIZE - 1 - base - m] = b.0;
}
let mut m = 0;
let mut m2 = MIDPOINT;
for i in (0..MIDPOINT / 4).map(|i| i * 4) {
rngstep(&mut self.mem, results, a ^ (a << 13), &mut a, &mut b, i + 0, m, m2);
rngstep(&mut self.mem, results, a ^ (a >> 6 ), &mut a, &mut b, i + 1, m, m2);
rngstep(&mut self.mem, results, a ^ (a << 2 ), &mut a, &mut b, i + 2, m, m2);
rngstep(&mut self.mem, results, a ^ (a >> 16), &mut a, &mut b, i + 3, m, m2);
}
m = MIDPOINT;
m2 = 0;
for i in (0..MIDPOINT / 4).map(|i| i * 4) {
rngstep(&mut self.mem, results, a ^ (a << 13), &mut a, &mut b, i + 0, m, m2);
rngstep(&mut self.mem, results, a ^ (a >> 6 ), &mut a, &mut b, i + 1, m, m2);
rngstep(&mut self.mem, results, a ^ (a << 2 ), &mut a, &mut b, i + 2, m, m2);
rngstep(&mut self.mem, results, a ^ (a >> 16), &mut a, &mut b, i + 3, m, m2);
}
self.a = a;
self.b = b;
}
}
impl IsaacCore {
#[inline]
fn init(mut mem: [w32; RAND_SIZE], rounds: u32) -> Self {
#[rustfmt::skip]
fn mix(a: &mut w32, b: &mut w32, c: &mut w32, d: &mut w32,
e: &mut w32, f: &mut w32, g: &mut w32, h: &mut w32) {
*a ^= *b << 11; *d += *a; *b += *c;
*b ^= *c >> 2; *e += *b; *c += *d;
*c ^= *d << 8; *f += *c; *d += *e;
*d ^= *e >> 16; *g += *d; *e += *f;
*e ^= *f << 10; *h += *e; *f += *g;
*f ^= *g >> 4; *a += *f; *g += *h;
*g ^= *h << 8; *b += *g; *h += *a;
*h ^= *a >> 9; *c += *h; *a += *b;
}
let mut a = w(0x1367df5a);
let mut b = w(0x95d90059);
let mut c = w(0xc3163e4b);
let mut d = w(0x0f421ad8);
let mut e = w(0xd92a4a78);
let mut f = w(0xa51a3c49);
let mut g = w(0xc4efea1b);
let mut h = w(0x30609119);
for _ in 0..rounds {
for i in (0..RAND_SIZE / 8).map(|i| i * 8) {
a += mem[i];
b += mem[i + 1];
c += mem[i + 2];
d += mem[i + 3];
e += mem[i + 4];
f += mem[i + 5];
g += mem[i + 6];
h += mem[i + 7];
mix(
&mut a, &mut b, &mut c, &mut d, &mut e, &mut f, &mut g, &mut h,
);
mem[i] = a;
mem[i + 1] = b;
mem[i + 2] = c;
mem[i + 3] = d;
mem[i + 4] = e;
mem[i + 5] = f;
mem[i + 6] = g;
mem[i + 7] = h;
}
}
Self {
mem,
a: w(0),
b: w(0),
c: w(0),
}
}
}
impl SeedableRng for IsaacCore {
type Seed = [u8; 32];
fn from_seed(seed: Self::Seed) -> Self {
let seed_u32: [u32; 8] = utils::read_words(&seed);
let mut seed_extended = [w(0); RAND_SIZE];
for (x, y) in seed_extended.iter_mut().zip(seed_u32.iter()) {
*x = w(*y);
}
Self::init(seed_extended, 2)
}
fn seed_from_u64(seed: u64) -> Self {
let mut key = [w(0); RAND_SIZE];
key[0] = w(seed as u32);
key[1] = w((seed >> 32) as u32);
Self::init(key, 1)
}
fn from_rng<R>(rng: &mut R) -> Self
where
R: Rng + ?Sized,
{
let mut seed = [w(0u32); RAND_SIZE];
unsafe {
let ptr = seed.as_mut_ptr() as *mut u8;
let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE * 4);
rng.fill_bytes(slice);
}
for i in seed.iter_mut() {
*i = w(i.0.to_le());
}
Self::init(seed, 2)
}
fn try_from_rng<R>(rng: &mut R) -> Result<Self, R::Error>
where
R: TryRng + ?Sized,
{
let mut seed = [w(0u32); RAND_SIZE];
unsafe {
let ptr = seed.as_mut_ptr() as *mut u8;
let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE * 4);
rng.try_fill_bytes(slice)?;
}
for i in seed.iter_mut() {
*i = w(i.0.to_le());
}
Ok(Self::init(seed, 2))
}
}
#[cfg(test)]
mod test {
use super::IsaacRng;
use rand_core::{Rng, SeedableRng};
#[test]
fn test_isaac_construction() {
let seed = [
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,
0, 0, 0, 0, 0,
];
let mut rng1 = IsaacRng::from_seed(seed);
assert_eq!(rng1.next_u32(), 2869442790);
let mut rng2 = IsaacRng::from_rng(&mut rng1);
assert_eq!(rng2.next_u32(), 3094074039);
}
#[test]
fn test_isaac_true_values_32() {
let seed = [
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,
0, 0, 0, 0, 0, 0,
];
let mut rng1 = IsaacRng::from_seed(seed);
let mut results = [0u32; 10];
for i in results.iter_mut() {
*i = rng1.next_u32();
}
let expected = [
2558573138, 873787463, 263499565, 2103644246, 3595684709, 4203127393, 264982119,
2765226902, 2737944514, 3900253796,
];
assert_eq!(results, expected);
let seed = [
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,
0, 0, 0, 0, 0, 0,
];
let mut rng2 = IsaacRng::from_seed(seed);
for _ in 0..10000 {
rng2.next_u32();
}
for i in results.iter_mut() {
*i = rng2.next_u32();
}
let expected = [
3676831399, 3183332890, 2834741178, 3854698763, 2717568474, 1576568959, 3507990155,
179069555, 141456972, 2478885421,
];
assert_eq!(results, expected);
}
#[test]
fn test_isaac_true_values_64() {
let seed = [
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,
0, 0, 0, 0, 0, 0,
];
let mut rng = IsaacRng::from_seed(seed);
let mut results = [0u64; 5];
for i in results.iter_mut() {
*i = rng.next_u64();
}
let expected = [
3752888579798383186,
9035083239252078381,
18052294697452424037,
11876559110374379111,
16751462502657800130,
];
assert_eq!(results, expected);
}
#[test]
#[rustfmt::skip]
fn test_isaac_true_bytes() {
let seed = [
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,
0, 0, 0, 0, 0, 0,
];
let mut rng = IsaacRng::from_seed(seed);
let mut results = [0u8; 32];
rng.fill_bytes(&mut results);
let expected = [82, 186, 128, 152, 71, 240, 20, 52,
45, 175, 180, 15, 86, 16, 99, 125,
101, 203, 81, 214, 97, 162, 134, 250,
103, 78, 203, 15, 150, 3, 210, 164];
assert_eq!(results, expected);
}
#[test]
#[rustfmt::skip]
fn test_isaac_new_uninitialized() {
let mut rng = IsaacRng::seed_from_u64(0);
let mut results = [0u32; 16];
for i in results.iter_mut() {
*i = rng.next_u32();
}
let expected: [u32; 16] = [
0x71D71FD2, 0xB54ADAE7, 0xD4788559, 0xC36129FA,
0x21DC1EA9, 0x3CB879CA, 0xD83B237F, 0xFA3CE5BD,
0x8D048509, 0xD82E9489, 0xDB452848, 0xCA20E846,
0x500F972E, 0x0EEFF940, 0x00D6B993, 0xBC12C17F];
assert_eq!(results, expected);
}
#[test]
fn test_isaac_clone() {
let seed = [
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,
0, 0, 0, 0, 0, 0,
];
let mut rng1 = IsaacRng::from_seed(seed);
let mut rng2 = rng1.clone();
for _ in 0..16 {
assert_eq!(rng1.next_u32(), rng2.next_u32());
}
}
#[test]
#[cfg(feature = "serde")]
fn test_isaac_serde() {
let seed = [
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,
0, 0, 0, 0, 0, 0,
];
let mut rng = IsaacRng::from_seed(seed);
let _ = rng.next_u64();
let _ = rng.next_u32();
let buf = postcard::to_allocvec(&rng).expect("Could not serialize");
let mut deserialized: IsaacRng = postcard::from_bytes(&buf).expect("Could not deserialize");
for _ in 0..300 {
assert_eq!(rng.next_u32(), deserialized.next_u32());
}
}
}