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