1use core::{fmt, slice};
13use core::num::Wrapping as w;
14#[cfg(feature="serde1")] use serde::{Serialize, Deserialize};
15use rand_core::{RngCore, SeedableRng, Error, le};
16use rand_core::block::{BlockRngCore, BlockRng64};
17use crate::isaac_array::IsaacArray;
18
19#[allow(non_camel_case_types)]
20type w64 = w<u64>;
21
22const RAND_SIZE_LEN: usize = 8;
23const RAND_SIZE: usize = 1 << RAND_SIZE_LEN;
24
25#[derive(Debug, Clone)]
83#[cfg_attr(feature="serde1", derive(Serialize, Deserialize))]
84pub struct Isaac64Rng(BlockRng64<Isaac64Core>);
85
86impl RngCore for Isaac64Rng {
87 #[inline]
88 fn next_u32(&mut self) -> u32 {
89 self.0.next_u32()
90 }
91
92 #[inline]
93 fn next_u64(&mut self) -> u64 {
94 self.0.next_u64()
95 }
96
97 #[inline]
98 fn fill_bytes(&mut self, dest: &mut [u8]) {
99 self.0.fill_bytes(dest)
100 }
101
102 #[inline]
103 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
104 self.0.try_fill_bytes(dest)
105 }
106}
107
108impl SeedableRng for Isaac64Rng {
109 type Seed = <Isaac64Core as SeedableRng>::Seed;
110
111 #[inline]
112 fn from_seed(seed: Self::Seed) -> Self {
113 Isaac64Rng(BlockRng64::<Isaac64Core>::from_seed(seed))
114 }
115
116 #[inline]
120 fn seed_from_u64(seed: u64) -> Self {
121 Isaac64Rng(BlockRng64::<Isaac64Core>::seed_from_u64(seed))
122 }
123
124 #[inline]
125 fn from_rng<S: RngCore>(rng: S) -> Result<Self, Error> {
126 BlockRng64::<Isaac64Core>::from_rng(rng).map(|rng| Isaac64Rng(rng))
127 }
128}
129
130#[derive(Clone)]
132#[cfg_attr(feature="serde1", derive(Serialize, Deserialize))]
133pub struct Isaac64Core {
134 #[cfg_attr(feature="serde1",serde(with="super::isaac_array::isaac_array_serde"))]
135 mem: [w64; RAND_SIZE],
136 a: w64,
137 b: w64,
138 c: w64,
139}
140
141impl fmt::Debug for Isaac64Core {
143 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
144 write!(f, "Isaac64Core {{}}")
145 }
146}
147
148impl ::core::cmp::PartialEq for Isaac64Core {
150 fn eq(&self, other: &Isaac64Core) -> bool {
151 &self.mem[..] == &other.mem[..]
152 && self.a == other.a
153 && self.b == other.b
154 && self.c == other.c
155 }
156}
157
158impl ::core::cmp::Eq for Isaac64Core {
160}
161
162impl BlockRngCore for Isaac64Core {
163 type Item = u64;
164 type Results = IsaacArray<Self::Item>;
165
166 fn generate(&mut self, results: &mut IsaacArray<Self::Item>) {
186 self.c += w(1);
187 let mut a = self.a;
189 let mut b = self.b + self.c;
190 const MIDPOINT: usize = RAND_SIZE / 2;
191
192 #[inline]
193 fn ind(mem:&[w64; RAND_SIZE], v: w64, amount: usize) -> w64 {
194 let index = (v >> amount).0 as usize % RAND_SIZE;
195 mem[index]
196 }
197
198 #[inline]
199 fn rngstep(mem: &mut [w64; RAND_SIZE],
200 results: &mut [u64; RAND_SIZE],
201 mix: w64,
202 a: &mut w64,
203 b: &mut w64,
204 base: usize,
205 m: usize,
206 m2: usize) {
207 let x = mem[base + m];
208 *a = mix + mem[base + m2];
209 let y = *a + *b + ind(&mem, x, 3);
210 mem[base + m] = y;
211 *b = x + ind(&mem, y, 3 + RAND_SIZE_LEN);
212 results[RAND_SIZE - 1 - base - m] = (*b).0;
213 }
214
215 let mut m = 0;
216 let mut m2 = MIDPOINT;
217 for i in (0..MIDPOINT/4).map(|i| i * 4) {
218 rngstep(&mut self.mem, results, !(a ^ (a << 21)), &mut a, &mut b, i + 0, m, m2);
219 rngstep(&mut self.mem, results, a ^ (a >> 5 ), &mut a, &mut b, i + 1, m, m2);
220 rngstep(&mut self.mem, results, a ^ (a << 12), &mut a, &mut b, i + 2, m, m2);
221 rngstep(&mut self.mem, results, a ^ (a >> 33), &mut a, &mut b, i + 3, m, m2);
222 }
223
224 m = MIDPOINT;
225 m2 = 0;
226 for i in (0..MIDPOINT/4).map(|i| i * 4) {
227 rngstep(&mut self.mem, results, !(a ^ (a << 21)), &mut a, &mut b, i + 0, m, m2);
228 rngstep(&mut self.mem, results, a ^ (a >> 5 ), &mut a, &mut b, i + 1, m, m2);
229 rngstep(&mut self.mem, results, a ^ (a << 12), &mut a, &mut b, i + 2, m, m2);
230 rngstep(&mut self.mem, results, a ^ (a >> 33), &mut a, &mut b, i + 3, m, m2);
231 }
232
233 self.a = a;
234 self.b = b;
235 }
236}
237
238impl Isaac64Core {
239 fn init(mut mem: [w64; RAND_SIZE], rounds: u32) -> Self {
241 fn mix(a: &mut w64, b: &mut w64, c: &mut w64, d: &mut w64,
242 e: &mut w64, f: &mut w64, g: &mut w64, h: &mut w64) {
243 *a -= *e; *f ^= *h >> 9; *h += *a;
244 *b -= *f; *g ^= *a << 9; *a += *b;
245 *c -= *g; *h ^= *b >> 23; *b += *c;
246 *d -= *h; *a ^= *c << 15; *c += *d;
247 *e -= *a; *b ^= *d >> 14; *d += *e;
248 *f -= *b; *c ^= *e << 20; *e += *f;
249 *g -= *c; *d ^= *f >> 17; *f += *g;
250 *h -= *d; *e ^= *g << 14; *g += *h;
251 }
252
253 let mut a = w(0x647c4677a2884b7c);
257 let mut b = w(0xb9f8b322c73ac862);
258 let mut c = w(0x8c0ea5053d4712a0);
259 let mut d = w(0xb29b2e824a595524);
260 let mut e = w(0x82f053db8355e0ce);
261 let mut f = w(0x48fe4a0fa5a09315);
262 let mut g = w(0xae985bf2cbfc89ed);
263 let mut h = w(0x98f5704f6c44c0ab);
264
265 for _ in 0..rounds {
268 for i in (0..RAND_SIZE/8).map(|i| i * 8) {
269 a += mem[i ]; b += mem[i+1];
270 c += mem[i+2]; d += mem[i+3];
271 e += mem[i+4]; f += mem[i+5];
272 g += mem[i+6]; h += mem[i+7];
273 mix(&mut a, &mut b, &mut c, &mut d,
274 &mut e, &mut f, &mut g, &mut h);
275 mem[i ] = a; mem[i+1] = b;
276 mem[i+2] = c; mem[i+3] = d;
277 mem[i+4] = e; mem[i+5] = f;
278 mem[i+6] = g; mem[i+7] = h;
279 }
280 }
281
282 Self { mem, a: w(0), b: w(0), c: w(0) }
283 }
284}
285
286impl SeedableRng for Isaac64Core {
287 type Seed = [u8; 32];
288
289 fn from_seed(seed: Self::Seed) -> Self {
290 let mut seed_u64 = [0u64; 4];
291 le::read_u64_into(&seed, &mut seed_u64);
292 let mut seed_extended = [w(0); RAND_SIZE];
294 for (x, y) in seed_extended.iter_mut().zip(seed_u64.iter()) {
295 *x = w(*y);
296 }
297 Self::init(seed_extended, 2)
298 }
299
300 fn seed_from_u64(seed: u64) -> Self {
301 let mut key = [w(0); RAND_SIZE];
302 key[0] = w(seed);
303 Self::init(key, 1)
310 }
311
312 fn from_rng<R: RngCore>(mut rng: R) -> Result<Self, Error> {
313 let mut seed = [w(0u64); RAND_SIZE];
316 unsafe {
317 let ptr = seed.as_mut_ptr() as *mut u8;
318 let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE * 8);
319 rng.try_fill_bytes(slice)?;
320 }
321 for i in seed.iter_mut() {
322 *i = w(i.0.to_le());
323 }
324
325 Ok(Self::init(seed, 2))
326 }
327}
328
329#[cfg(test)]
330mod test {
331 use rand_core::{RngCore, SeedableRng};
332 use super::Isaac64Rng;
333
334 #[test]
335 fn test_isaac64_construction() {
336 let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0,
338 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];
339 let mut rng1 = Isaac64Rng::from_seed(seed);
340 assert_eq!(rng1.next_u64(), 14964555543728284049);
341
342 let mut rng2 = Isaac64Rng::from_rng(rng1).unwrap();
343 assert_eq!(rng2.next_u64(), 919595328260451758);
344 }
345
346 #[test]
347 fn test_isaac64_true_values_64() {
348 let seed = [1,0,0,0, 0,0,0,0, 23,0,0,0, 0,0,0,0,
349 200,1,0,0, 0,0,0,0, 210,30,0,0, 0,0,0,0];
350 let mut rng1 = Isaac64Rng::from_seed(seed);
351 let mut results = [0u64; 10];
352 for i in results.iter_mut() { *i = rng1.next_u64(); }
353 let expected = [
354 15071495833797886820, 7720185633435529318,
355 10836773366498097981, 5414053799617603544,
356 12890513357046278984, 17001051845652595546,
357 9240803642279356310, 12558996012687158051,
358 14673053937227185542, 1677046725350116783];
359 assert_eq!(results, expected);
360
361 let seed = [57,48,0,0, 0,0,0,0, 50,9,1,0, 0,0,0,0,
362 49,212,0,0, 0,0,0,0, 148,38,0,0, 0,0,0,0];
363 let mut rng2 = Isaac64Rng::from_seed(seed);
364 for _ in 0..10000 { rng2.next_u64(); }
366
367 for i in results.iter_mut() { *i = rng2.next_u64(); }
368 let expected = [
369 18143823860592706164, 8491801882678285927, 2699425367717515619,
370 17196852593171130876, 2606123525235546165, 15790932315217671084,
371 596345674630742204, 9947027391921273664, 11788097613744130851,
372 10391409374914919106];
373 assert_eq!(results, expected);
374 }
375
376 #[test]
377 fn test_isaac64_true_values_32() {
378 let seed = [1,0,0,0, 0,0,0,0, 23,0,0,0, 0,0,0,0,
379 200,1,0,0, 0,0,0,0, 210,30,0,0, 0,0,0,0];
380 let mut rng = Isaac64Rng::from_seed(seed);
381 let mut results = [0u32; 12];
382 for i in results.iter_mut() { *i = rng.next_u32(); }
383 let expected = [
385 3477963620, 3509106075,
386 687845478, 1797495790,
387 227048253, 2523132918,
388 4044335064, 1260557630,
389 4079741768, 3001306521,
390 69157722, 3958365844];
391 assert_eq!(results, expected);
392 }
393
394 #[test]
395 fn test_isaac64_true_values_mixed() {
396 let seed = [1,0,0,0, 0,0,0,0, 23,0,0,0, 0,0,0,0,
397 200,1,0,0, 0,0,0,0, 210,30,0,0, 0,0,0,0];
398 let mut rng = Isaac64Rng::from_seed(seed);
399 assert_eq!(rng.next_u64(), 15071495833797886820);
403 assert_eq!(rng.next_u32(), 687845478);
404 assert_eq!(rng.next_u32(), 1797495790);
405 assert_eq!(rng.next_u64(), 10836773366498097981);
406 assert_eq!(rng.next_u32(), 4044335064);
407 assert_eq!(rng.next_u64(), 12890513357046278984);
409 assert_eq!(rng.next_u32(), 69157722);
410 }
411
412 #[test]
413 fn test_isaac64_true_bytes() {
414 let seed = [1,0,0,0, 0,0,0,0, 23,0,0,0, 0,0,0,0,
415 200,1,0,0, 0,0,0,0, 210,30,0,0, 0,0,0,0];
416 let mut rng = Isaac64Rng::from_seed(seed);
417 let mut results = [0u8; 32];
418 rng.fill_bytes(&mut results);
419 let expected = [100, 131, 77, 207, 155, 181, 40, 209,
421 102, 176, 255, 40, 238, 155, 35, 107,
422 61, 123, 136, 13, 246, 243, 99, 150,
423 216, 167, 15, 241, 62, 149, 34, 75];
424 assert_eq!(results, expected);
425 }
426
427 #[test]
428 fn test_isaac64_new_uninitialized() {
429 let mut rng = Isaac64Rng::seed_from_u64(0);
435 let mut results = [0u64; 16];
436 for i in results.iter_mut() { *i = rng.next_u64(); }
437 let expected: [u64; 16] = [
438 0xF67DFBA498E4937C, 0x84A5066A9204F380, 0xFEE34BD5F5514DBB,
439 0x4D1664739B8F80D6, 0x8607459AB52A14AA, 0x0E78BC5A98529E49,
440 0xFE5332822AD13777, 0x556C27525E33D01A, 0x08643CA615F3149F,
441 0xD0771FAF3CB04714, 0x30E86F68A37B008D, 0x3074EBC0488A3ADF,
442 0x270645EA7A2790BC, 0x5601A0A8D3763C6A, 0x2F83071F53F325DD,
443 0xB9090F3D42D2D2EA];
444 assert_eq!(results, expected);
445 }
446
447 #[test]
448 fn test_isaac64_clone() {
449 let seed = [1,0,0,0, 0,0,0,0, 23,0,0,0, 0,0,0,0,
450 200,1,0,0, 0,0,0,0, 210,30,0,0, 0,0,0,0];
451 let mut rng1 = Isaac64Rng::from_seed(seed);
452 let mut rng2 = rng1.clone();
453 for _ in 0..16 {
454 assert_eq!(rng1.next_u64(), rng2.next_u64());
455 }
456 }
457
458 #[test]
459 #[cfg(feature="serde1")]
460 fn test_isaac64_serde() {
461 use bincode;
462 use std::io::{BufWriter, BufReader};
463
464 let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0,
465 57,48,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];
466 let mut rng = Isaac64Rng::from_seed(seed);
467
468 let buf: Vec<u8> = Vec::new();
469 let mut buf = BufWriter::new(buf);
470 bincode::serialize_into(&mut buf, &rng).expect("Could not serialize");
471
472 let buf = buf.into_inner().unwrap();
473 let mut read = BufReader::new(&buf[..]);
474 let mut deserialized: Isaac64Rng = bincode::deserialize_from(&mut read).expect("Could not deserialize");
475
476 for _ in 0..300 { assert_eq!(rng.next_u64(), deserialized.next_u64());
478 }
479 }
480}