2019-09-17 14:07:24 +00:00
|
|
|
/// The zerocopy crate exists and can replace this function.
|
|
|
|
/// We should evaluate using it when we have multiple usage spots for it.
|
|
|
|
/// For now we have this safe alternative.
|
2019-09-17 14:05:08 +00:00
|
|
|
fn cast_u32x8_u8x32(a: [u32; 8]) -> [u8; 32] {
|
|
|
|
let mut r = [0; 32];
|
|
|
|
for i in 0..8 {
|
|
|
|
let a = a[i].to_ne_bytes();
|
|
|
|
for j in 0..4 {
|
|
|
|
r[i * 4 + j] = a[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r
|
|
|
|
}
|
2019-08-18 22:55:04 +00:00
|
|
|
|
2019-08-06 00:03:51 +00:00
|
|
|
/// Simple non-cryptographic diffusion function.
|
2019-09-21 17:40:27 +00:00
|
|
|
#[inline(always)]
|
|
|
|
pub fn diffuse(mut a: u32) -> u32 {
|
|
|
|
a ^= a.rotate_right(23);
|
|
|
|
a.wrapping_mul(2654435761)
|
2019-08-05 16:46:28 +00:00
|
|
|
}
|
|
|
|
|
2019-09-17 14:56:23 +00:00
|
|
|
/// Diffuse but takes multiple values as input.
|
2019-09-21 17:40:27 +00:00
|
|
|
#[inline(always)]
|
2019-09-17 14:56:23 +00:00
|
|
|
pub fn diffuse_mult(v: &[u32]) -> u32 {
|
|
|
|
let mut state = (1 << 31) - 1;
|
|
|
|
for e in v {
|
|
|
|
state = diffuse(state ^ e);
|
|
|
|
}
|
|
|
|
state
|
|
|
|
}
|
|
|
|
|
2019-08-06 00:03:51 +00:00
|
|
|
/// Expand a 32 bit seed into a 32 byte RNG state.
|
|
|
|
pub fn rng_state(mut x: u32) -> [u8; 32] {
|
|
|
|
let mut r: [u32; 8] = [0; 8];
|
|
|
|
for s in &mut r {
|
|
|
|
x = diffuse(x);
|
|
|
|
*s = x;
|
2019-08-05 16:46:28 +00:00
|
|
|
}
|
2019-09-17 14:05:08 +00:00
|
|
|
cast_u32x8_u8x32(r)
|
2019-08-05 16:46:28 +00:00
|
|
|
}
|