Skip to content

Commit

Permalink
Switch Rand's test::rng to Pcg32
Browse files Browse the repository at this point in the history
  • Loading branch information
dhardy committed May 23, 2019
1 parent d6ee5e8 commit 66c22e0
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 33 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -77,6 +77,7 @@ rand_chacha = { path = "rand_chacha", version = "0.2" }
rand_hc = { path = "rand_hc", version = "0.1" }

[dev-dependencies]
rand_pcg = { path = "rand_pcg", version = "0.1" }
# Only for benches:
rand_hc = { path = "rand_hc", version = "0.1" }
rand_xoshiro = { path = "rand_xoshiro", version = "0.1" }
Expand Down
23 changes: 8 additions & 15 deletions src/distributions/cauchy.rs
Expand Up @@ -68,31 +68,24 @@ mod test {

#[test]
#[cfg(not(miri))] // Miri doesn't support transcendental functions
fn test_cauchy_median() {
fn test_cauchy_averages() {
// NOTE: given that the variance and mean are undefined,
// this test does not have any rigorous statistical meaning.
let cauchy = Cauchy::new(10.0, 5.0);
let mut rng = ::test::rng(123);
let mut rng = crate::test::rng(123);
let mut numbers: [f64; 1000] = [0.0; 1000];
let mut sum = 0.0;
for i in 0..1000 {
numbers[i] = cauchy.sample(&mut rng);
sum += numbers[i];
}
let median = median(&mut numbers);
println!("Cauchy median: {}", median);
assert!((median - 10.0).abs() < 0.5); // not 100% certain, but probable enough
}

#[test]
#[cfg(not(miri))] // Miri doesn't support transcendental functions
fn test_cauchy_mean() {
let cauchy = Cauchy::new(10.0, 5.0);
let mut rng = ::test::rng(123);
let mut sum = 0.0;
for _ in 0..1000 {
sum += cauchy.sample(&mut rng);
}
assert!((median - 10.0).abs() < 0.4); // not 100% certain, but probable enough
let mean = sum / 1000.0;
println!("Cauchy mean: {}", mean);
// for a Cauchy distribution the mean should not converge
assert!((mean - 10.0).abs() > 0.5); // not 100% certain, but probable enough
assert!((mean - 10.0).abs() > 0.4); // not 100% certain, but probable enough
}

#[test]
Expand Down
17 changes: 12 additions & 5 deletions src/distributions/unit_circle.rs
Expand Up @@ -84,10 +84,17 @@ mod tests {

#[test]
fn value_stability() {
let mut rng = ::test::rng(2);
let dist = UnitCircle::new();
assert_eq!(dist.sample(&mut rng), [0.968253135419177, 0.2499717299034683]);
assert_eq!(dist.sample(&mut rng), [-0.2083028196300198, 0.9780643819985387]);
assert_eq!(dist.sample(&mut rng), [0.4284767927057159, -0.9035527865667964]);
let mut rng = crate::test::rng(2);
let expected = [
[-0.9965658683520504, -0.08280380447614634],
[-0.9790853270389644, -0.20345004884984505],
[-0.8449189758898707, 0.5348943112253227],
];
let samples = [
UnitCircle.sample(&mut rng),
UnitCircle.sample(&mut rng),
UnitCircle.sample(&mut rng),
];
assert_eq!(samples, expected);
}
}
20 changes: 12 additions & 8 deletions src/distributions/unit_sphere.rs
Expand Up @@ -79,13 +79,17 @@ mod tests {

#[test]
fn value_stability() {
let mut rng = ::test::rng(2);
let dist = UnitSphereSurface::new();
assert_eq!(dist.sample(&mut rng),
[0.9754391834492048, 0.12388255134190126, -0.18213048307455182]);
assert_eq!(dist.sample(&mut rng),
[0.45487349593184284, 0.5619516852114866, -0.6908693119445342]);
assert_eq!(dist.sample(&mut rng),
[-0.8374011645099787, 0.5296803977011814, 0.13489983679919715]);
let mut rng = crate::test::rng(2);
let expected = [
[0.03247542860231647, -0.7830477442152738, 0.6211131755296027],
[-0.09978440840914075, 0.9706650829833128, -0.21875184231323952],
[0.2735582468624679, 0.9435374242279655, -0.1868234852870203],
];
let samples = [
UnitSphereSurface.sample(&mut rng),
UnitSphereSurface.sample(&mut rng),
UnitSphereSurface.sample(&mut rng),
];
assert_eq!(samples, expected);
}
}
8 changes: 5 additions & 3 deletions src/lib.rs
Expand Up @@ -561,10 +561,12 @@ mod test {
use super::*;
#[cfg(all(not(feature="std"), feature="alloc"))] use alloc::boxed::Box;

/// Construct a deterministic RNG with the given seed
pub fn rng(seed: u64) -> impl RngCore {
// For tests, we want a statistically good, fast, reproducible RNG. We
// do not need cryptographic strength. ChaCha8 is a good choice.
rand_chacha::ChaCha8Rng::seed_from_u64(seed)
// For tests, we want a statistically good, fast, reproducible RNG.
// PCG32 will do fine, and will be easy to embed if we ever need to.
const INC: u64 = 11634580027462260723;
rand_pcg::Pcg32::new(seed, INC)
}

#[test]
Expand Down
6 changes: 4 additions & 2 deletions src/seq/mod.rs
Expand Up @@ -613,8 +613,10 @@ mod test {
counts[permutation] += 1;
}
for count in counts.iter() {
let err = *count - 10000i32 / 24;
assert!(-50 <= err && err <= 50);
// Binomial(10000, 1/24) with average 416.667
// Octave: binocdf(n, 10000, 1/24)
// 99.9% chance samples lie within this range:
assert!(352 <= *count && *count <= 483, "count: {}", count);
}
}

Expand Down

0 comments on commit 66c22e0

Please sign in to comment.