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 w64 = w<u64>;
const RAND_SIZE_LEN: usize = 8;
const RAND_SIZE: usize = 1 << RAND_SIZE_LEN;
#[derive(Debug, Clone)]
pub struct Isaac64Rng(BlockRng<Isaac64Core>);
impl TryRng for Isaac64Rng {
type Error = Infallible;
#[inline]
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
Ok(self.0.next_word() as u32)
}
#[inline]
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
Ok(self.0.next_word())
}
#[inline]
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
self.0.fill_bytes(dest);
Ok(())
}
}
impl SeedableRng for Isaac64Rng {
type Seed = <Isaac64Core as SeedableRng>::Seed;
#[inline]
fn from_seed(seed: Self::Seed) -> Self {
Isaac64Rng(BlockRng::new(Isaac64Core::from_seed(seed)))
}
#[inline]
fn seed_from_u64(seed: u64) -> Self {
Isaac64Rng(BlockRng::new(Isaac64Core::seed_from_u64(seed)))
}
#[inline]
fn from_rng<R>(rng: &mut R) -> Self
where
R: Rng + ?Sized,
{
Isaac64Rng(BlockRng::new(Isaac64Core::from_rng(rng)))
}
#[inline]
fn try_from_rng<S>(rng: &mut S) -> Result<Self, S::Error>
where
S: TryRng + ?Sized,
{
Isaac64Core::try_from_rng(rng).map(|core| Isaac64Rng(BlockRng::new(core)))
}
}
#[cfg(feature = "serde")]
mod serde_impls {
use super::{Isaac64Core, Isaac64Rng, 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 Isaac64Rng {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut state = serializer.serialize_struct("Isaac64Rng", 2)?;
state.serialize_field("core", &self.0.core)?;
state.serialize_field("results", self.0.remaining_results())?;
state.end()
}
}
struct Results {
results: [u64; RAND_SIZE],
len: usize,
}
impl Results {
fn to_rng(&self, core: Isaac64Core) -> Isaac64Rng {
let results = &self.results[..self.len];
Isaac64Rng(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 = [0u64; 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 = Isaac64Rng;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "") }
fn visit_seq<V>(self, mut seq: V) -> Result<Isaac64Rng, 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<Isaac64Rng, 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 Isaac64Rng {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
const FIELDS: &[&str] = &["core", "results"];
deserializer.deserialize_struct("Isaac64Rng", FIELDS, IsaacVisitor)
}
}
}
#[derive(Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Isaac64Core {
#[cfg_attr(feature = "serde", serde(with = "serde_arrays"))]
mem: [w64; RAND_SIZE],
a: w64,
b: w64,
c: w64,
}
impl fmt::Debug for Isaac64Core {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Isaac64Core {{}}")
}
}
impl ::core::cmp::PartialEq for Isaac64Core {
fn eq(&self, other: &Isaac64Core) -> bool {
self.mem[..] == other.mem[..] && self.a == other.a && self.b == other.b && self.c == other.c
}
}
impl ::core::cmp::Eq for Isaac64Core {}
impl Generator for Isaac64Core {
type Output = [u64; RAND_SIZE];
#[rustfmt::skip]
fn generate(&mut self, results: &mut [u64; 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: &[w64; RAND_SIZE], v: w64, amount: usize) -> w64 {
let index = (v >> amount).0 as usize % RAND_SIZE;
mem[index]
}
#[inline]
fn rngstep(
mem: &mut [w64; RAND_SIZE],
results: &mut [u64; RAND_SIZE],
mix: w64,
a: &mut w64,
b: &mut w64,
base: usize,
m: usize,
m2: usize,
) {
let x = mem[base + m];
*a = mix + mem[base + m2];
let y = *a + *b + ind(mem, x, 3);
mem[base + m] = y;
*b = x + ind(mem, y, 3 + 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 << 21)), &mut a, &mut b, i + 0, m, m2);
rngstep(&mut self.mem, results, a ^ (a >> 5 ), &mut a, &mut b, i + 1, m, m2);
rngstep(&mut self.mem, results, a ^ (a << 12), &mut a, &mut b, i + 2, m, m2);
rngstep(&mut self.mem, results, a ^ (a >> 33), &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 << 21)), &mut a, &mut b, i + 0, m, m2);
rngstep(&mut self.mem, results, a ^ (a >> 5 ), &mut a, &mut b, i + 1, m, m2);
rngstep(&mut self.mem, results, a ^ (a << 12), &mut a, &mut b, i + 2, m, m2);
rngstep(&mut self.mem, results, a ^ (a >> 33), &mut a, &mut b, i + 3, m, m2);
}
self.a = a;
self.b = b;
}
}
impl Isaac64Core {
fn init(mut mem: [w64; RAND_SIZE], rounds: u32) -> Self {
#[rustfmt::skip]
fn mix(a: &mut w64, b: &mut w64, c: &mut w64, d: &mut w64,
e: &mut w64, f: &mut w64, g: &mut w64, h: &mut w64) {
*a -= *e; *f ^= *h >> 9; *h += *a;
*b -= *f; *g ^= *a << 9; *a += *b;
*c -= *g; *h ^= *b >> 23; *b += *c;
*d -= *h; *a ^= *c << 15; *c += *d;
*e -= *a; *b ^= *d >> 14; *d += *e;
*f -= *b; *c ^= *e << 20; *e += *f;
*g -= *c; *d ^= *f >> 17; *f += *g;
*h -= *d; *e ^= *g << 14; *g += *h;
}
let mut a = w(0x647c4677a2884b7c);
let mut b = w(0xb9f8b322c73ac862);
let mut c = w(0x8c0ea5053d4712a0);
let mut d = w(0xb29b2e824a595524);
let mut e = w(0x82f053db8355e0ce);
let mut f = w(0x48fe4a0fa5a09315);
let mut g = w(0xae985bf2cbfc89ed);
let mut h = w(0x98f5704f6c44c0ab);
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 Isaac64Core {
type Seed = [u8; 32];
fn from_seed(seed: Self::Seed) -> Self {
let seed_u64: [u64; 4] = utils::read_words(&seed);
let mut seed_extended = [w(0); RAND_SIZE];
for (x, y) in seed_extended.iter_mut().zip(seed_u64.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);
Self::init(key, 1)
}
fn from_rng<R>(rng: &mut R) -> Self
where
R: Rng + ?Sized,
{
let mut seed = [w(0u64); RAND_SIZE];
unsafe {
let ptr = seed.as_mut_ptr() as *mut u8;
let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE * 8);
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(0u64); RAND_SIZE];
unsafe {
let ptr = seed.as_mut_ptr() as *mut u8;
let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE * 8);
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::Isaac64Rng;
use rand_core::{Rng, SeedableRng};
#[test]
fn test_isaac64_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 = Isaac64Rng::from_seed(seed);
assert_eq!(rng1.next_u64(), 14964555543728284049);
let mut rng2 = Isaac64Rng::from_rng(&mut rng1);
assert_eq!(rng2.next_u64(), 919595328260451758);
}
#[test]
fn test_isaac64_true_values_64() {
let seed = [
1, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 200, 1, 0, 0, 0, 0, 0, 0, 210, 30, 0,
0, 0, 0, 0, 0,
];
let mut rng1 = Isaac64Rng::from_seed(seed);
let mut results = [0u64; 10];
for i in results.iter_mut() {
*i = rng1.next_u64();
}
let expected = [
15071495833797886820,
7720185633435529318,
10836773366498097981,
5414053799617603544,
12890513357046278984,
17001051845652595546,
9240803642279356310,
12558996012687158051,
14673053937227185542,
1677046725350116783,
];
assert_eq!(results, expected);
let seed = [
57, 48, 0, 0, 0, 0, 0, 0, 50, 9, 1, 0, 0, 0, 0, 0, 49, 212, 0, 0, 0, 0, 0, 0, 148, 38,
0, 0, 0, 0, 0, 0,
];
let mut rng2 = Isaac64Rng::from_seed(seed);
for _ in 0..10000 {
rng2.next_u64();
}
for i in results.iter_mut() {
*i = rng2.next_u64();
}
let expected = [
18143823860592706164,
8491801882678285927,
2699425367717515619,
17196852593171130876,
2606123525235546165,
15790932315217671084,
596345674630742204,
9947027391921273664,
11788097613744130851,
10391409374914919106,
];
assert_eq!(results, expected);
}
#[test]
fn test_isaac64_true_values_32() {
let seed = [
1, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 200, 1, 0, 0, 0, 0, 0, 0, 210, 30, 0,
0, 0, 0, 0, 0,
];
let mut rng = Isaac64Rng::from_seed(seed);
let mut results = [0u32; 12];
for i in results.iter_mut() {
*i = rng.next_u32();
}
let expected = [
3477963620, 687845478, 227048253, 4044335064, 4079741768, 69157722, 3912394646,
1204022051, 2459090310, 2151271855, 384864925, 1183723065,
];
assert_eq!(results, expected);
}
#[test]
fn test_isaac64_true_values_mixed() {
let seed = [
1, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 200, 1, 0, 0, 0, 0, 0, 0, 210, 30, 0,
0, 0, 0, 0, 0,
];
let mut rng = Isaac64Rng::from_seed(seed);
assert_eq!(rng.next_u64(), 15071495833797886820);
assert_eq!(rng.next_u32(), 687845478);
assert_eq!(rng.next_u32(), 227048253);
assert_eq!(rng.next_u64(), 5414053799617603544);
assert_eq!(rng.next_u32(), 4079741768);
assert_eq!(rng.next_u64(), 17001051845652595546);
assert_eq!(rng.next_u32(), 3912394646);
}
#[test]
#[rustfmt::skip]
fn test_isaac64_true_bytes() {
let seed = [
1, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 200, 1, 0, 0, 0, 0, 0, 0, 210, 30, 0,
0, 0, 0, 0, 0,
];
let mut rng = Isaac64Rng::from_seed(seed);
let mut results = [0u8; 32];
rng.fill_bytes(&mut results);
let expected = [100, 131, 77, 207, 155, 181, 40, 209,
102, 176, 255, 40, 238, 155, 35, 107,
61, 123, 136, 13, 246, 243, 99, 150,
216, 167, 15, 241, 62, 149, 34, 75];
assert_eq!(results, expected);
}
#[test]
fn test_isaac64_new_uninitialized() {
let mut rng = Isaac64Rng::seed_from_u64(0);
let mut results = [0u64; 16];
for i in results.iter_mut() {
*i = rng.next_u64();
}
let expected: [u64; 16] = [
0xF67DFBA498E4937C,
0x84A5066A9204F380,
0xFEE34BD5F5514DBB,
0x4D1664739B8F80D6,
0x8607459AB52A14AA,
0x0E78BC5A98529E49,
0xFE5332822AD13777,
0x556C27525E33D01A,
0x08643CA615F3149F,
0xD0771FAF3CB04714,
0x30E86F68A37B008D,
0x3074EBC0488A3ADF,
0x270645EA7A2790BC,
0x5601A0A8D3763C6A,
0x2F83071F53F325DD,
0xB9090F3D42D2D2EA,
];
assert_eq!(results, expected);
}
#[test]
fn test_isaac64_clone() {
let seed = [
1, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 200, 1, 0, 0, 0, 0, 0, 0, 210, 30, 0,
0, 0, 0, 0, 0,
];
let mut rng1 = Isaac64Rng::from_seed(seed);
let mut rng2 = rng1.clone();
for _ in 0..16 {
assert_eq!(rng1.next_u64(), rng2.next_u64());
}
}
#[test]
#[cfg(feature = "serde")]
fn test_isaac64_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 = Isaac64Rng::from_seed(seed);
let _ = rng.next_u64();
let _ = rng.next_u32();
let buf = postcard::to_allocvec(&rng).expect("Could not serialize");
let mut deserialized: Isaac64Rng =
postcard::from_bytes(&buf).expect("Could not deserialize");
for _ in 0..300 {
assert_eq!(rng.next_u64(), deserialized.next_u64());
}
}
}