From 825d0506948c540e1d712ec098e18acc2bf561e7 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Mon, 29 Mar 2021 09:44:44 +0100 Subject: [PATCH 1/4] Uniform(float) distrs: add range overflow check and fix tests --- src/distributions/uniform.rs | 48 +++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/src/distributions/uniform.rs b/src/distributions/uniform.rs index e8d0dcad8b3..576d761585a 100644 --- a/src/distributions/uniform.rs +++ b/src/distributions/uniform.rs @@ -827,11 +827,11 @@ macro_rules! uniform_float_impl { { let low = *low_b.borrow(); let high = *high_b.borrow(); - assert!( + debug_assert!( low.all_finite(), "Uniform::new called with `low` non-finite." ); - assert!( + debug_assert!( high.all_finite(), "Uniform::new called with `high` non-finite." ); @@ -841,6 +841,7 @@ macro_rules! uniform_float_impl { ); let mut scale = high - low; + assert!(scale.all_finite(), "Uniform::new: range overflow"); loop { let mask = (scale * max_rand + low).ge_mask(high); @@ -862,19 +863,24 @@ macro_rules! uniform_float_impl { { let low = *low_b.borrow(); let high = *high_b.borrow(); + debug_assert!( + low.all_finite(), + "Uniform::new_inclusive called with `low` non-finite." + ); + debug_assert!( + high.all_finite(), + "Uniform::new_inclusive called with `high` non-finite." + ); assert!( low.all_le(high), "Uniform::new_inclusive called with `low > high`" ); - assert!( - low.all_finite() && high.all_finite(), - "Uniform::new_inclusive called with non-finite boundaries" - ); let max_rand = <$ty>::splat( (::core::$u_scalar::MAX >> $bits_to_discard).into_float_with_exponent(0) - 1.0, ); let mut scale = (high - low) / max_rand; + assert!(scale.all_finite(), "Uniform::new_inclusive: range overflow"); loop { let mask = (scale * max_rand + low).gt_mask(high); @@ -913,11 +919,20 @@ macro_rules! uniform_float_impl { { let low = *low_b.borrow(); let high = *high_b.borrow(); + debug_assert!( + low.all_finite(), + "UniformSampler::sample_single called with `low` non-finite." + ); + debug_assert!( + high.all_finite(), + "UniformSampler::sample_single called with `high` non-finite." + ); assert!( low.all_lt(high), "UniformSampler::sample_single: low >= high" ); let mut scale = high - low; + assert!(scale.all_finite(), "UniformSampler::sample_single: range overflow"); loop { // Generate a value in the range [1, 2) @@ -1332,12 +1347,8 @@ mod tests { (-<$f_scalar>::from_bits(10), -<$f_scalar>::from_bits(1)), (-<$f_scalar>::from_bits(5), 0.0), (-<$f_scalar>::from_bits(7), -0.0), - (10.0, ::core::$f_scalar::MAX), - (-100.0, ::core::$f_scalar::MAX), - (-::core::$f_scalar::MAX / 5.0, ::core::$f_scalar::MAX), - (-::core::$f_scalar::MAX, ::core::$f_scalar::MAX / 5.0), - (-::core::$f_scalar::MAX * 0.8, ::core::$f_scalar::MAX * 0.7), - (-::core::$f_scalar::MAX, ::core::$f_scalar::MAX), + (0.1 * ::core::$f_scalar::MAX, ::core::$f_scalar::MAX), + (-::core::$f_scalar::MAX * 0.2, ::core::$f_scalar::MAX * 0.7), ]; for &(low_scalar, high_scalar) in v.iter() { for lane in 0..<$ty>::lanes() { @@ -1416,6 +1427,19 @@ mod tests { } } + #[test] + #[should_panic] + fn test_float_overflow() { + Uniform::from(f64::MIN..f64::MAX); + } + + #[test] + #[should_panic] + fn test_float_overflow_single() { + let mut rng = crate::test::rng(252); + rng.gen_range(f64::MIN..f64::MAX); + } + #[test] #[cfg(all( feature = "std", From 7b1b2d00b21a3aa778fba9a3df110ae81aea4ecb Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Mon, 29 Mar 2021 09:48:30 +0100 Subject: [PATCH 2/4] Update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 536c510af81..377380bbbfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ A [separate changelog is kept for rand_core](rand_core/CHANGELOG.md). You may also find the [Upgrade Guide](https://rust-random.github.io/book/update.html) useful. +## [Unreleased] +### Other +- Reorder asserts in `Uniform` float distributions for easier debugging of non-finite arguments + (#1094, #1108) +- Add range overflow check in `Uniform` float distributions (#1108) + ## [0.8.3] - 2021-01-25 ### Fixes - Fix `no-std` + `alloc` build by gating `choose_multiple_weighted` on `std` (#1088) From 80172a2071b48feb7ad4c42f3e79af7abe850992 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Mon, 29 Mar 2021 10:40:03 +0100 Subject: [PATCH 3/4] Changelog for #1104 --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 377380bbbfc..d69d7948a83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ A [separate changelog is kept for rand_core](rand_core/CHANGELOG.md). You may also find the [Upgrade Guide](https://rust-random.github.io/book/update.html) useful. ## [Unreleased] +### Additions +- Use const-generics to support arrays of all sizes (#1104) + ### Other - Reorder asserts in `Uniform` float distributions for easier debugging of non-finite arguments (#1094, #1108) From b1cecac7c61f08386eaa37cff24721042016670d Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Mon, 29 Mar 2021 10:41:31 +0100 Subject: [PATCH 4/4] Fix for MSRV --- src/distributions/uniform.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/distributions/uniform.rs b/src/distributions/uniform.rs index 576d761585a..57934838ae8 100644 --- a/src/distributions/uniform.rs +++ b/src/distributions/uniform.rs @@ -1430,14 +1430,14 @@ mod tests { #[test] #[should_panic] fn test_float_overflow() { - Uniform::from(f64::MIN..f64::MAX); + Uniform::from(::core::f64::MIN..::core::f64::MAX); } #[test] #[should_panic] fn test_float_overflow_single() { let mut rng = crate::test::rng(252); - rng.gen_range(f64::MIN..f64::MAX); + rng.gen_range(::core::f64::MIN..::core::f64::MAX); } #[test]