Struct rand_isaac::isaac::IsaacCore
source · pub struct IsaacCore {
mem: [Wrapping<u32>; 256],
a: Wrapping<u32>,
b: Wrapping<u32>,
c: Wrapping<u32>,
}
Fields§
§mem: [Wrapping<u32>; 256]
§a: Wrapping<u32>
§b: Wrapping<u32>
§c: Wrapping<u32>
Implementations§
source§impl IsaacCore
impl IsaacCore
sourcefn init(mem: [Wrapping<u32>; 256], rounds: u32) -> Self
fn init(mem: [Wrapping<u32>; 256], rounds: u32) -> Self
Create a new ISAAC random number generator.
The author Bob Jenkins describes how to best initialize ISAAC here: https://rt.cpan.org/Public/Bug/Display.html?id=64324 The answer is included here just in case:
“No, you don’t need a full 8192 bits of seed data. Normal key sizes will
do fine, and they should have their expected strength (eg a 40-bit key
will take as much time to brute force as 40-bit keys usually will). You
could fill the remainder with 0, but set the last array element to the
length of the key provided (to distinguish keys that differ only by
different amounts of 0 padding). You do still need to call randinit()
to make sure the initial state isn’t uniform-looking.”
“After publishing ISAAC, I wanted to limit the key to half the size of
r[]
, and repeat it twice. That would have made it hard to provide a
key that sets the whole internal state to anything convenient. But I’d
already published it.”
And his answer to the question “For my code, would repeating the key over and over to fill 256 integers be a better solution than zero-filling, or would they essentially be the same?”: “If the seed is under 32 bytes, they’re essentially the same, otherwise repeating the seed would be stronger. randinit() takes a chunk of 32 bytes, mixes it, and combines that with the next 32 bytes, et cetera. Then loops over all the elements the same way a second time.”
Trait Implementations§
source§impl BlockRngCore for IsaacCore
impl BlockRngCore for IsaacCore
source§fn generate(&mut self, results: &mut IsaacArray<Self::Item>)
fn generate(&mut self, results: &mut IsaacArray<Self::Item>)
Refills the output buffer, results
. See also the pseudocode desciption
of the algorithm in the IsaacRng
documentation.
Optimisations used (similar to the reference implementation):
- The loop is unrolled 4 times, once for every constant of mix().
- The contents of the main loop are moved to a function
rngstep
, to reduce code duplication. - We use local variables for a and b, which helps with optimisations.
- We split the main loop in two, one that operates over 0..128 and one
over 128..256. This way we can optimise out the addition and modulus
from
s[i+128 mod 256]
. - We maintain one index
i
and addm
orm2
as base (m2 for thes[i+128 mod 256]
), relying on the optimizer to turn it into pointer arithmetic. - We fill
results
backwards. The reference implementation reads values fromresults
in reverse. We read them in the normal direction, to makefill_bytes
a memcopy. To maintain compatibility we fill in reverse.
§type Results = IsaacArray<<IsaacCore as BlockRngCore>::Item>
type Results = IsaacArray<<IsaacCore as BlockRngCore>::Item>
BlockRngCore
generates, which will usually be an array like [u32; 16]
.source§impl PartialEq for IsaacCore
impl PartialEq for IsaacCore
source§impl SeedableRng for IsaacCore
impl SeedableRng for IsaacCore
source§fn seed_from_u64(seed: u64) -> Self
fn seed_from_u64(seed: u64) -> Self
Create an ISAAC random number generator using an u64
as seed.
If seed == 0
this will produce the same stream of random numbers as
the reference implementation when used unseeded.
§type Seed = [u8; 32]
type Seed = [u8; 32]
u8
arrays (we recommend [u8; N]
for some N
). Read moresource§fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error>
fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error>
Rng
. Read more