From 72af6f84f26daca5f8248be52f687fe734b2f79a Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Sun, 15 Sep 2019 10:51:54 +0100 Subject: [PATCH] Add value_stability tests for bernoulli, int, float and other distrs --- src/distributions/bernoulli.rs | 11 ++++++ src/distributions/float.rs | 47 ++++++++++++++++++++++--- src/distributions/integer.rs | 63 ++++++++++++++++++++++++++++++++-- src/distributions/other.rs | 38 ++++++++++++++++++-- 4 files changed, 150 insertions(+), 9 deletions(-) diff --git a/src/distributions/bernoulli.rs b/src/distributions/bernoulli.rs index eadd0563b05..614d8429498 100644 --- a/src/distributions/bernoulli.rs +++ b/src/distributions/bernoulli.rs @@ -163,4 +163,15 @@ mod test { let avg2 = (sum2 as f64) / (N as f64); assert!((avg2 - (NUM as f64)/(DENOM as f64)).abs() < 5e-3); } + + #[test] + fn value_stability() { + let mut rng = crate::test::rng(3); + let distr = Bernoulli::new(0.4532).unwrap(); + let mut buf = [false; 10]; + for x in &mut buf { + *x = rng.sample(&distr); + } + assert_eq!(buf, [true, false, false, true, false, false, true, true, true, true]); + } } diff --git a/src/distributions/float.rs b/src/distributions/float.rs index bda523ad485..bef18a5b560 100644 --- a/src/distributions/float.rs +++ b/src/distributions/float.rs @@ -168,11 +168,8 @@ float_impls! { f64x8, u64x8, f64, u64, 52, 1023 } #[cfg(test)] mod tests { - use crate::Rng; - use crate::distributions::{Open01, OpenClosed01}; + use super::*; use crate::rngs::mock::StepRng; - #[cfg(feature="simd_support")] - use packed_simd::*; const EPSILON32: f32 = ::core::f32::EPSILON; const EPSILON64: f64 = ::core::f64::EPSILON; @@ -256,4 +253,46 @@ mod tests { test_f64! { f64x4_edge_cases, f64x4, f64x4::splat(0.0), f64x4::splat(EPSILON64) } #[cfg(feature="simd_support")] test_f64! { f64x8_edge_cases, f64x8, f64x8::splat(0.0), f64x8::splat(EPSILON64) } + + #[test] + fn value_stability() { + fn test_samples>( + distr: &D, zero: T, expected: &[T] + ) { + let mut rng = crate::test::rng(0x6f44f5646c2a7334); + let mut buf = [zero; 3]; + for x in &mut buf { + *x = rng.sample(&distr); + } + assert_eq!(&buf, expected); + } + + test_samples(&Standard, 0f32, &[0.0035963655, 0.7346052, 0.09778172]); + test_samples(&Standard, 0f64, &[0.7346051961657583, + 0.20298547462974248, 0.8166436635290655]); + + test_samples(&OpenClosed01, 0f32, &[0.003596425, 0.73460525, 0.09778178]); + test_samples(&OpenClosed01, 0f64, &[0.7346051961657584, + 0.2029854746297426, 0.8166436635290656]); + + test_samples(&Open01, 0f32, &[0.0035963655, 0.73460525, 0.09778172]); + test_samples(&Open01, 0f64, &[0.7346051961657584, + 0.20298547462974248, 0.8166436635290656]); + + #[cfg(feature="simd_support")] { + // We only test a sub-set of types here. Values are identical to + // non-SIMD types; we assume this pattern continues across all + // SIMD types. + + test_samples(&Standard, f32x2::new(0.0, 0.0), &[ + f32x2::new(0.0035963655, 0.7346052), + f32x2::new(0.09778172, 0.20298547), + f32x2::new(0.34296435, 0.81664366)]); + + test_samples(&Standard, f64x2::new(0.0, 0.0), &[ + f64x2::new(0.7346051961657583, 0.20298547462974248), + f64x2::new(0.8166436635290655, 0.7423708925400552), + f64x2::new(0.16387782224016323, 0.9087068770169618)]); + } + } } diff --git a/src/distributions/integer.rs b/src/distributions/integer.rs index 5238339a026..63cd3b9489b 100644 --- a/src/distributions/integer.rs +++ b/src/distributions/integer.rs @@ -158,8 +158,7 @@ simd_impl!((__m64, u8x8), (__m128i, u8x16), (__m256i, u8x32),); #[cfg(test)] mod tests { - use crate::Rng; - use crate::distributions::{Standard}; + use super::*; #[test] fn test_integers() { @@ -181,4 +180,64 @@ mod tests { #[cfg(not(target_os = "emscripten"))] rng.sample::(Standard); } + + #[test] + fn value_stability() { + fn test_samples( + zero: T, expected: &[T] + ) + where Standard: Distribution + { + let mut rng = crate::test::rng(807); + let mut buf = [zero; 3]; + for x in &mut buf { + *x = rng.sample(Standard); + } + assert_eq!(&buf, expected); + } + + test_samples(0u8, &[9, 247, 111]); + test_samples(0u16, &[32265, 42999, 38255]); + test_samples(0u32, &[2220326409, 2575017975, 2018088303]); + test_samples(0u64, &[11059617991457472009, + 16096616328739788143, 1487364411147516184]); + test_samples(0u128, &[296930161868957086625409848350820761097, + 145644820879247630242265036535529306392, + 111087889832015897993126088499035356354]); + #[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))] + test_samples(0usize, &[2220326409, 2575017975, 2018088303]); + #[cfg(target_pointer_width = "64")] + test_samples(0usize, &[11059617991457472009, + 16096616328739788143, 1487364411147516184]); + + test_samples(0i8, &[9, -9, 111]); + // Skip further i* types: they are simple reinterpretation of u* samples + + #[cfg(feature="simd_support")] { + // We only test a sub-set of types here and make assumptions about the rest. + + test_samples(u8x2::default(), &[u8x2::new(9, 126), + u8x2::new(247, 167), u8x2::new(111, 149)]); + test_samples(u8x4::default(), &[u8x4::new(9, 126, 87, 132), + u8x4::new(247, 167, 123, 153), u8x4::new(111, 149, 73, 120)]); + test_samples(u8x8::default(), &[ + u8x8::new(9, 126, 87, 132, 247, 167, 123, 153), + u8x8::new(111, 149, 73, 120, 68, 171, 98, 223), + u8x8::new(24, 121, 1, 50, 13, 46, 164, 20)]); + + test_samples(i64x8::default(), &[ + i64x8::new(-7387126082252079607, -2350127744969763473, + 1487364411147516184, 7895421560427121838, + 602190064936008898, 6022086574635100741, + -5080089175222015595, -4066367846667249123), + i64x8::new(9180885022207963908, 3095981199532211089, + 6586075293021332726, 419343203796414657, + 3186951873057035255, 5287129228749947252, + 444726432079249540, -1587028029513790706), + i64x8::new(6075236523189346388, 1351763722368165432, + -6192309979959753740, -7697775502176768592, + -4482022114172078123, 7522501477800909500, + -1837258847956201231, -586926753024886735)]); + } + } } diff --git a/src/distributions/other.rs b/src/distributions/other.rs index 6ec04734842..8c0e477b21e 100644 --- a/src/distributions/other.rs +++ b/src/distributions/other.rs @@ -177,9 +177,8 @@ impl Distribution> for Standard where Standard: Distribution { #[cfg(test)] mod tests { - use crate::{Rng, RngCore, Standard}; - use crate::distributions::Alphanumeric; - #[cfg(all(not(feature="std"), feature="alloc"))] use alloc::string::String; + use super::*; + use crate::RngCore; #[test] fn test_misc() { @@ -217,4 +216,37 @@ mod tests { } assert!(incorrect == false); } + + #[test] + fn value_stability() { + fn test_samples>( + distr: &D, zero: T, expected: &[T]) { + let mut rng = crate::test::rng(807); + let mut buf = [zero; 5]; + for x in &mut buf { + *x = rng.sample(&distr); + } + assert_eq!(&buf, expected); + } + + test_samples(&Standard, 'a', &['\u{8cdac}', '\u{a346a}', '\u{80120}', '\u{ed692}', '\u{35888}']); + test_samples(&Alphanumeric, 'a', &['h', 'm', 'e', '3', 'M']); + test_samples(&Standard, false, &[true, true, false, true, false]); + test_samples(&Standard, Option::::None, + &[Some(true), None, Some(false), None, Some(false)]); + test_samples(&Standard, Wrapping(0i32), &[Wrapping(-2074640887), + Wrapping(-1719949321), Wrapping(2018088303), + Wrapping(-547181756), Wrapping(838957336)]); + + // We test only sub-sets of tuple and array impls + test_samples(&Standard, (), &[(), (), (), (), ()]); + test_samples(&Standard, (false,), &[(true,), (true,), (false,), (true,), (false,)]); + test_samples(&Standard, (false,false), &[(true,true), (false,true), + (false,false), (true,false), (false,false)]); + + test_samples(&Standard, [0u8; 0], &[[], [], [], [], []]); + test_samples(&Standard, [0u8; 3], &[[9, 247, 111], + [68, 24, 13], [174, 19, 194], + [172, 69, 213], [149, 207, 29]]); + } }