]>
git.proxmox.com Git - rustc.git/blob - src/librand/isaac.rs
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! The ISAAC random number generator.
13 #![allow(non_camel_case_types)]
17 use core
::iter
::repeat
;
18 use core
::num
::Wrapping
as w
;
20 use {Rand, Rng, SeedableRng}
;
25 const RAND_SIZE_LEN
: usize = 8;
26 const RAND_SIZE
: u32 = 1 << RAND_SIZE_LEN
;
27 const RAND_SIZE_USIZE
: usize = 1 << RAND_SIZE_LEN
;
29 /// A random number generator that uses the ISAAC algorithm[1].
31 /// The ISAAC algorithm is generally accepted as suitable for
32 /// cryptographic purposes, but this implementation has not be
33 /// verified as such. Prefer a generator like `OsRng` that defers to
34 /// the operating system for cases that need high security.
36 /// [1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number
37 /// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html)
41 rsl
: [w32
; RAND_SIZE_USIZE
],
42 mem
: [w32
; RAND_SIZE_USIZE
],
48 impl fmt
::Debug
for IsaacRng
{
49 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
50 f
.debug_struct("IsaacRng")
51 .field("cnt", &self.cnt
)
52 .field("rsl", &self.rsl
.iter())
53 .field("mem", &self.mem
.iter())
61 static EMPTY
: IsaacRng
= IsaacRng
{
63 rsl
: [w(0); RAND_SIZE_USIZE
],
64 mem
: [w(0); RAND_SIZE_USIZE
],
71 /// Create an ISAAC random number generator using the default
73 pub fn new_unseeded() -> IsaacRng
{
79 /// Initializes `self`. If `use_rsl` is true, then use the current value
80 /// of `rsl` as a seed, otherwise construct one algorithmically (not
82 fn init(&mut self, use_rsl
: bool
) {
83 let mut a
= w(0x9e3779b9);
133 macro_rules
! memloop
{
135 for i
in (0..RAND_SIZE_USIZE
).step_by(8) {
160 for i
in (0..RAND_SIZE_USIZE
).step_by(8) {
176 /// Refills the output buffer (`self.rsl`)
178 fn isaac(&mut self) {
179 self.c
= self.c
+ w(1);
182 let mut b
= self.b
+ self.c
;
184 const MIDPOINT
: usize = RAND_SIZE_USIZE
/ 2;
187 ($x
:expr
) => (self.mem
[($x
>> 2).0 as usize & (RAND_SIZE_USIZE
- 1)] )
190 let r
= [(0, MIDPOINT
), (MIDPOINT
, 0)];
191 for &(mr_offset
, m2_offset
) in &r
{
193 macro_rules
! rngstepp
{
194 ($j
:expr
, $shift
:expr
) => {{
196 let mix
= a
<< $shift
;
198 let x
= self.mem
[base
+ mr_offset
];
199 a
= (a ^ mix
) + self.mem
[base
+ m2_offset
];
200 let y
= ind
!(x
) + a
+ b
;
201 self.mem
[base
+ mr_offset
] = y
;
203 b
= ind
!(y
>> RAND_SIZE_LEN
) + x
;
204 self.rsl
[base
+ mr_offset
] = b
;
208 macro_rules
! rngstepn
{
209 ($j
:expr
, $shift
:expr
) => {{
211 let mix
= a
>> $shift
;
213 let x
= self.mem
[base
+ mr_offset
];
214 a
= (a ^ mix
) + self.mem
[base
+ m2_offset
];
215 let y
= ind
!(x
) + a
+ b
;
216 self.mem
[base
+ mr_offset
] = y
;
218 b
= ind
!(y
>> RAND_SIZE_LEN
) + x
;
219 self.rsl
[base
+ mr_offset
] = b
;
223 for i
in (0..MIDPOINT
).step_by(4) {
224 rngstepp
!(i
+ 0, 13);
227 rngstepn
!(i
+ 3, 16);
233 self.cnt
= RAND_SIZE
;
237 // Cannot be derived because [u32; 256] does not implement Clone
238 impl Clone
for IsaacRng
{
239 fn clone(&self) -> IsaacRng
{
244 impl Rng
for IsaacRng
{
246 fn next_u32(&mut self) -> u32 {
248 // make some more numbers
253 // self.cnt is at most RAND_SIZE, but that is before the
254 // subtraction above. We want to index without bounds
255 // checking, but this could lead to incorrect code if someone
256 // misrefactors, so we check, sometimes.
258 // (Changes here should be reflected in Isaac64Rng.next_u64.)
259 debug_assert
!(self.cnt
< RAND_SIZE
);
261 // (the % is cheaply telling the optimiser that we're always
262 // in bounds, without unsafe. NB. this is a power of two, so
263 // it optimises to a bitwise mask).
264 self.rsl
[(self.cnt
% RAND_SIZE
) as usize].0
268 impl<'a
> SeedableRng
<&'a
[u32]> for IsaacRng
{
269 fn reseed(&mut self, seed
: &'a
[u32]) {
270 // make the seed into [seed[0], seed[1], ..., seed[seed.len()
271 // - 1], 0, 0, ...], to fill rng.rsl.
272 let seed_iter
= seed
.iter().cloned().chain(repeat(0));
274 for (rsl_elem
, seed_elem
) in self.rsl
.iter_mut().zip(seed_iter
) {
275 *rsl_elem
= w(seed_elem
);
285 /// Create an ISAAC random number generator with a seed. This can
286 /// be any length, although the maximum number of elements used is
287 /// 256 and any more will be silently ignored. A generator
288 /// constructed with a given seed will generate the same sequence
289 /// of values as all other generators constructed with that seed.
290 fn from_seed(seed
: &'a
[u32]) -> IsaacRng
{
297 impl Rand
for IsaacRng
{
298 fn rand
<R
: Rng
>(other
: &mut R
) -> IsaacRng
{
301 let ptr
= ret
.rsl
.as_mut_ptr() as *mut u8;
303 let slice
= slice
::from_raw_parts_mut(ptr
, RAND_SIZE_USIZE
* 4);
304 other
.fill_bytes(slice
);
316 const RAND_SIZE_64_LEN
: usize = 8;
317 const RAND_SIZE_64
: usize = 1 << RAND_SIZE_64_LEN
;
319 /// A random number generator that uses ISAAC-64[1], the 64-bit
320 /// variant of the ISAAC algorithm.
322 /// The ISAAC algorithm is generally accepted as suitable for
323 /// cryptographic purposes, but this implementation has not be
324 /// verified as such. Prefer a generator like `OsRng` that defers to
325 /// the operating system for cases that need high security.
327 /// [1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number
328 /// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html)
330 pub struct Isaac64Rng
{
332 rsl
: [w64
; RAND_SIZE_64
],
333 mem
: [w64
; RAND_SIZE_64
],
339 impl fmt
::Debug
for Isaac64Rng
{
340 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
341 f
.debug_struct("Isaac64Rng")
342 .field("cnt", &self.cnt
)
343 .field("rsl", &self.rsl
.iter())
344 .field("mem", &self.mem
.iter())
352 static EMPTY_64
: Isaac64Rng
= Isaac64Rng
{
354 rsl
: [w(0); RAND_SIZE_64
],
355 mem
: [w(0); RAND_SIZE_64
],
362 /// Create a 64-bit ISAAC random number generator using the
363 /// default fixed seed.
364 pub fn new_unseeded() -> Isaac64Rng
{
365 let mut rng
= EMPTY_64
;
370 /// Initializes `self`. If `use_rsl` is true, then use the current value
371 /// of `rsl` as a seed, otherwise construct one algorithmically (not
373 fn init(&mut self, use_rsl
: bool
) {
376 let mut $var
= w(0x9e3779b97f4a7c13);
429 macro_rules
! memloop
{
431 for i
in (0..RAND_SIZE_64
/ 8).map(|i
| i
* 8) {
456 for i
in (0..RAND_SIZE_64
/ 8).map(|i
| i
* 8) {
472 /// Refills the output buffer (`self.rsl`)
473 fn isaac64(&mut self) {
474 self.c
= self.c
+ w(1);
477 let mut b
= self.b
+ self.c
;
478 const MIDPOINT
: usize = RAND_SIZE_64
/ 2;
479 const MP_VEC
: [(usize, usize); 2] = [(0, MIDPOINT
), (MIDPOINT
, 0)];
482 *self.mem
.get_unchecked((($x
>> 3).0 as usize) & (RAND_SIZE_64
- 1))
486 for &(mr_offset
, m2_offset
) in &MP_VEC
{
487 for base
in (0..MIDPOINT
/ 4).map(|i
| i
* 4) {
489 macro_rules
! rngstepp
{
490 ($j
:expr
, $shift
:expr
) => {{
491 let base
= base
+ $j
;
492 let mix
= a ^
(a
<< $shift
);
493 let mix
= if $j
== 0 {!mix}
else {mix}
;
496 let x
= *self.mem
.get_unchecked(base
+ mr_offset
);
497 a
= mix
+ *self.mem
.get_unchecked(base
+ m2_offset
);
498 let y
= ind
!(x
) + a
+ b
;
499 *self.mem
.get_unchecked_mut(base
+ mr_offset
) = y
;
501 b
= ind
!(y
>> RAND_SIZE_64_LEN
) + x
;
502 *self.rsl
.get_unchecked_mut(base
+ mr_offset
) = b
;
507 macro_rules
! rngstepn
{
508 ($j
:expr
, $shift
:expr
) => {{
509 let base
= base
+ $j
;
510 let mix
= a ^
(a
>> $shift
);
511 let mix
= if $j
== 0 {!mix}
else {mix}
;
514 let x
= *self.mem
.get_unchecked(base
+ mr_offset
);
515 a
= mix
+ *self.mem
.get_unchecked(base
+ m2_offset
);
516 let y
= ind
!(x
) + a
+ b
;
517 *self.mem
.get_unchecked_mut(base
+ mr_offset
) = y
;
519 b
= ind
!(y
>> RAND_SIZE_64_LEN
) + x
;
520 *self.rsl
.get_unchecked_mut(base
+ mr_offset
) = b
;
534 self.cnt
= RAND_SIZE_64
;
538 // Cannot be derived because [u32; 256] does not implement Clone
539 impl Clone
for Isaac64Rng
{
540 fn clone(&self) -> Isaac64Rng
{
545 impl Rng
for Isaac64Rng
{
546 // FIXME(https://github.com/rust-lang/rfcs/issues/628)
547 // having next_u32 like this should be unnecessary
549 fn next_u32(&mut self) -> u32 {
550 self.next_u64() as u32
554 fn next_u64(&mut self) -> u64 {
556 // make some more numbers
561 // See corresponding location in IsaacRng.next_u32 for
563 debug_assert
!(self.cnt
< RAND_SIZE_64
);
564 self.rsl
[(self.cnt
% RAND_SIZE_64
) as usize].0
568 impl<'a
> SeedableRng
<&'a
[u64]> for Isaac64Rng
{
569 fn reseed(&mut self, seed
: &'a
[u64]) {
570 // make the seed into [seed[0], seed[1], ..., seed[seed.len()
571 // - 1], 0, 0, ...], to fill rng.rsl.
572 let seed_iter
= seed
.iter().cloned().chain(repeat(0));
574 for (rsl_elem
, seed_elem
) in self.rsl
.iter_mut().zip(seed_iter
) {
575 *rsl_elem
= w(seed_elem
);
585 /// Create an ISAAC random number generator with a seed. This can
586 /// be any length, although the maximum number of elements used is
587 /// 256 and any more will be silently ignored. A generator
588 /// constructed with a given seed will generate the same sequence
589 /// of values as all other generators constructed with that seed.
590 fn from_seed(seed
: &'a
[u64]) -> Isaac64Rng
{
591 let mut rng
= EMPTY_64
;
597 impl Rand
for Isaac64Rng
{
598 fn rand
<R
: Rng
>(other
: &mut R
) -> Isaac64Rng
{
599 let mut ret
= EMPTY_64
;
601 let ptr
= ret
.rsl
.as_mut_ptr() as *mut u8;
603 let slice
= slice
::from_raw_parts_mut(ptr
, RAND_SIZE_64
* 8);
604 other
.fill_bytes(slice
);
619 use std
::prelude
::v1
::*;
621 use {Rng, SeedableRng}
;
622 use super::{Isaac64Rng, IsaacRng}
;
625 fn test_rng_32_rand_seeded() {
626 let s
= ::test
::rng().gen_iter
::<u32>().take(256).collect
::<Vec
<u32>>();
627 let mut ra
: IsaacRng
= SeedableRng
::from_seed(&s
[..]);
628 let mut rb
: IsaacRng
= SeedableRng
::from_seed(&s
[..]);
629 assert
!(ra
.gen_ascii_chars()
631 .eq(rb
.gen_ascii_chars().take(100)));
634 fn test_rng_64_rand_seeded() {
635 let s
= ::test
::rng().gen_iter
::<u64>().take(256).collect
::<Vec
<u64>>();
636 let mut ra
: Isaac64Rng
= SeedableRng
::from_seed(&s
[..]);
637 let mut rb
: Isaac64Rng
= SeedableRng
::from_seed(&s
[..]);
638 assert
!(ra
.gen_ascii_chars()
640 .eq(rb
.gen_ascii_chars().take(100)));
644 fn test_rng_32_seeded() {
645 let seed
: &[_
] = &[1, 23, 456, 7890, 12345];
646 let mut ra
: IsaacRng
= SeedableRng
::from_seed(seed
);
647 let mut rb
: IsaacRng
= SeedableRng
::from_seed(seed
);
648 assert
!(ra
.gen_ascii_chars()
650 .eq(rb
.gen_ascii_chars().take(100)));
653 fn test_rng_64_seeded() {
654 let seed
: &[_
] = &[1, 23, 456, 7890, 12345];
655 let mut ra
: Isaac64Rng
= SeedableRng
::from_seed(seed
);
656 let mut rb
: Isaac64Rng
= SeedableRng
::from_seed(seed
);
657 assert
!(ra
.gen_ascii_chars()
659 .eq(rb
.gen_ascii_chars().take(100)));
663 fn test_rng_32_reseed() {
664 let s
= ::test
::rng().gen_iter
::<u32>().take(256).collect
::<Vec
<u32>>();
665 let mut r
: IsaacRng
= SeedableRng
::from_seed(&s
[..]);
666 let string1
: String
= r
.gen_ascii_chars().take(100).collect();
670 let string2
: String
= r
.gen_ascii_chars().take(100).collect();
671 assert_eq
!(string1
, string2
);
674 fn test_rng_64_reseed() {
675 let s
= ::test
::rng().gen_iter
::<u64>().take(256).collect
::<Vec
<u64>>();
676 let mut r
: Isaac64Rng
= SeedableRng
::from_seed(&s
[..]);
677 let string1
: String
= r
.gen_ascii_chars().take(100).collect();
681 let string2
: String
= r
.gen_ascii_chars().take(100).collect();
682 assert_eq
!(string1
, string2
);
687 fn test_rng_32_true_values() {
688 let seed
: &[_
] = &[1, 23, 456, 7890, 12345];
689 let mut ra
: IsaacRng
= SeedableRng
::from_seed(seed
);
690 // Regression test that isaac is actually using the above vector
691 let v
= (0..10).map(|_
| ra
.next_u32()).collect
::<Vec
<_
>>();
693 vec
![2558573138, 873787463, 263499565, 2103644246, 3595684709,
694 4203127393, 264982119, 2765226902, 2737944514, 3900253796]);
696 let seed
: &[_
] = &[12345, 67890, 54321, 9876];
697 let mut rb
: IsaacRng
= SeedableRng
::from_seed(seed
);
698 // skip forward to the 10000th number
703 let v
= (0..10).map(|_
| rb
.next_u32()).collect
::<Vec
<_
>>();
705 vec
![3676831399, 3183332890, 2834741178, 3854698763, 2717568474,
706 1576568959, 3507990155, 179069555, 141456972, 2478885421]);
710 fn test_rng_64_true_values() {
711 let seed
: &[_
] = &[1, 23, 456, 7890, 12345];
712 let mut ra
: Isaac64Rng
= SeedableRng
::from_seed(seed
);
713 // Regression test that isaac is actually using the above vector
714 let v
= (0..10).map(|_
| ra
.next_u64()).collect
::<Vec
<_
>>();
716 vec
![547121783600835980, 14377643087320773276, 17351601304698403469,
717 1238879483818134882, 11952566807690396487, 13970131091560099343,
718 4469761996653280935, 15552757044682284409, 6860251611068737823,
719 13722198873481261842]);
721 let seed
: &[_
] = &[12345, 67890, 54321, 9876];
722 let mut rb
: Isaac64Rng
= SeedableRng
::from_seed(seed
);
723 // skip forward to the 10000th number
728 let v
= (0..10).map(|_
| rb
.next_u64()).collect
::<Vec
<_
>>();
730 vec
![18143823860592706164, 8491801882678285927, 2699425367717515619,
731 17196852593171130876, 2606123525235546165, 15790932315217671084,
732 596345674630742204, 9947027391921273664, 11788097613744130851,
733 10391409374914919106]);
738 fn test_rng_clone() {
739 let seed
: &[_
] = &[1, 23, 456, 7890, 12345];
740 let mut rng
: Isaac64Rng
= SeedableRng
::from_seed(seed
);
741 let mut clone
= rng
.clone();
743 assert_eq
!(rng
.next_u64(), clone
.next_u64());