Replies: 3 comments 6 replies
-
|
I've translated the entire java code from the paper to rust, using a mutable pattern. It might help our discussion (I'm not-so-secretly working on a rust port). pub struct SplittableRandom {
seed: u64,
gamma: u64,
}
impl SplittableRandom {
pub fn from_seed(seed: u64) {
Self::new(seed, GOLDEN_GAMMA);
}
fn new(seed: u64, gamma: u64) -> Self {
assert!((gamma & 1) == 1, "gamma should always be odd.");
Self {
seed,
gamma,
}
}
pub fn seed(&self) -> u64 {
self.seed
}
fn next(&self) -> Self {
Self::new(self.seed + self.gamma, self.gamma)
}
pub fn random() -> Self {
let seed = std::time::UNIX_EPOCH.elapsed().unwrap().as_nanos() as u64;
Self::new(
mix_u64(seed),
mix_gamma(seed + GOLDEN_GAMMA),
)
}
pub fn next_u64(&self) -> (Self, u64) {
let rand = self.next();
let seed = rand.seed();
(rand, mix_u64(seed))
}
pub fn next_u32(&self) -> (Self, u32) {
let rand = self.next();
let seed = mix_u32(rand.seed());
(rand, seed)
}
pub fn next_f64(&self) -> (Self, f64) {
let (rand, seed) = self.next_u64();
let seed = ((seed >> 11) as f64) * DOUBLE_ULP;
(rand, seed)
}
pub fn split(&self) -> Self {
let rand0 = self;
let rand1 = rand0.next();
let rand2 = rand1.next();
let seed = mix_u64(rand1.seed());
let gamma = mix_gamma(rand2.seed());
Self::new(seed, gamma)
}
}
const DOUBLE_ULP: f64 = 1.0 / ((1u64 << 53) as f64);
const GOLDEN_GAMMA: u64 = 0x9e3779b97f4a7c15; // odd
fn mix_u64(mut z: u64) -> u64 {
z = (z ^ (z >> 33)) * 0xff51afd7ed558ccd;
z = (z ^ (z >> 33)) * 0xc4ceb9fe1a85ec53;
return z ^ (z >> 33);
}
fn mix_u32(mut z: u64) -> u32 {
z = (z ^ (z >> 33)) * 0xff51afd7ed558ccd;
z = (z ^ (z >> 33)) * 0xc4ceb9fe1a85ec53;
return (z >> 32) as u32;
}
fn mix_u64_variant_13(mut z: u64) -> u64 {
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
return z ^ (z >> 31);
}
fn mix_gamma(z: u64) -> u64 {
let z = mix_u64_variant_13(z) | 1;
let n = (z ^ (z >> 1)).count_ones();
if n >= 24 {
z ^ 0xaaaaaaaaaaaaaaaa
} else {
z
}
} |
Beta Was this translation helpful? Give feedback.
0 replies
-
|
I'll have to refresh my memory. Keep in mind, the original paper's implementation isn't perfect: hedgehogqa/haskell-hedgehog@39b15b9 |
Beta Was this translation helpful? Give feedback.
6 replies
-
|
This was addressed in #362. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I took some time today to read through the splittable random paper, and I noticed some differences between our implementation and theirs. Mainly, our
splitfunction creates and returns twoSeedvalues, while in the paper there is only a singleSplittableRandomcreated and also they shuffle thegammavalue while we don't (p. 465). Is this correct? Does Hedgehog need both generated this way to operate properly?Just trying to get my head wrapped around this. I want to start writing more documentation for these modules to help newcomers (and myself, apparently) understand them.
/cc @moodmosaic
Beta Was this translation helpful? Give feedback.
All reactions