Skip to content

Commit

Permalink
Make Uniform constructors return a result
Browse files Browse the repository at this point in the history
- This is a breaking change.
- The new error type had to be made public, otherwise `Uniform` could
  not be extended for user-defined types by implementing
  `UniformSampler`.
- `rand_distr` was updated accordingly.
- Also forbid unsafe code for crates where none is used.

Fixes rust-random#1195, rust-random#1211.
  • Loading branch information
vks committed Apr 22, 2022
1 parent f9bce60 commit e40f00a
Show file tree
Hide file tree
Showing 20 changed files with 199 additions and 168 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ 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.

## [0.9.0] - unreleased
### Distributions
- `{Uniform, UniformSampler}::{new, new_inclusive}` return a `Result` (instead of potentially panicking)
- `Uniform` implements `TryFrom` instead of `From` for ranges

## [0.8.5] - 2021-08-20
### Fixes
- Fix build on non-32/64-bit architectures (#1144)
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rand"
version = "0.8.5"
version = "0.9.0"
authors = ["The Rand Project Developers", "The Rust Project Developers"]
license = "MIT OR Apache-2.0"
readme = "README.md"
Expand Down
2 changes: 1 addition & 1 deletion examples/monte-carlo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
use rand::distributions::{Distribution, Uniform};

fn main() {
let range = Uniform::new(-1.0f64, 1.0);
let range = Uniform::new(-1.0f64, 1.0).unwrap();
let mut rng = rand::thread_rng();

let total = 1_000_000;
Expand Down
2 changes: 1 addition & 1 deletion examples/monty-hall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ fn main() {
let num_simulations = 10000;

let mut rng = rand::thread_rng();
let random_door = Uniform::new(0u32, 3);
let random_door = Uniform::new(0u32, 3).unwrap();

let (mut switch_wins, mut switch_losses) = (0, 0);
let (mut keep_wins, mut keep_losses) = (0, 0);
Expand Down
1 change: 1 addition & 0 deletions rand_distr/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [0.5.0] - unreleased
- Remove unused fields from `Gamma`, `NormalInverseGaussian` and `Zipf` distributions (#1184)
This breaks serialization compatibility with older versions.
- Upgrade Rand

## [0.4.3] - 2021-12-30
- Fix `no_std` build (#1208)
Expand Down
4 changes: 2 additions & 2 deletions rand_distr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ std_math = ["num-traits/std"]
serde1 = ["serde", "rand/serde1"]

[dependencies]
rand = { path = "..", version = "0.8.0", default-features = false }
rand = { path = "..", version = "0.9.0", default-features = false }
num-traits = { version = "0.2", default-features = false, features = ["libm"] }
serde = { version = "1.0.103", features = ["derive"], optional = true }

[dev-dependencies]
rand_pcg = { version = "0.3.0", path = "../rand_pcg" }
# For inline examples
rand = { path = "..", version = "0.8.0", default-features = false, features = ["std_rng", "std", "small_rng"] }
rand = { path = "..", version = "0.9.0", default-features = false, features = ["std_rng", "std", "small_rng"] }
# Histogram implementation for testing uniformity
average = { version = "0.13", features = [ "std" ] }
# Special functions for testing distributions
Expand Down
4 changes: 2 additions & 2 deletions rand_distr/src/binomial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ impl Distribution<u64> for Binomial {
// return value
let mut y: i64;

let gen_u = Uniform::new(0., p4);
let gen_v = Uniform::new(0., 1.);
let gen_u = Uniform::new(0., p4).unwrap();
let gen_v = Uniform::new(0., 1.).unwrap();

loop {
// Step 1: Generate `u` for selecting the region. If region 1 is
Expand Down
2 changes: 1 addition & 1 deletion rand_distr/src/hypergeometric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ impl Distribution<u64> for Hypergeometric {
x
},
RejectionAcceptance { m, a, lambda_l, lambda_r, x_l, x_r, p1, p2, p3 } => {
let distr_region_select = Uniform::new(0.0, p3);
let distr_region_select = Uniform::new(0.0, p3).unwrap();
loop {
let (y, v) = loop {
let u = distr_region_select.sample(rng);
Expand Down
2 changes: 1 addition & 1 deletion rand_distr/src/unit_ball.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub struct UnitBall;
impl<F: Float + SampleUniform> Distribution<[F; 3]> for UnitBall {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> [F; 3] {
let uniform = Uniform::new(F::from(-1.).unwrap(), F::from(1.).unwrap());
let uniform = Uniform::new(F::from(-1.).unwrap(), F::from(1.).unwrap()).unwrap();
let mut x1;
let mut x2;
let mut x3;
Expand Down
2 changes: 1 addition & 1 deletion rand_distr/src/unit_circle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub struct UnitCircle;
impl<F: Float + SampleUniform> Distribution<[F; 2]> for UnitCircle {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> [F; 2] {
let uniform = Uniform::new(F::from(-1.).unwrap(), F::from(1.).unwrap());
let uniform = Uniform::new(F::from(-1.).unwrap(), F::from(1.).unwrap()).unwrap();
let mut x1;
let mut x2;
let mut sum;
Expand Down
2 changes: 1 addition & 1 deletion rand_distr/src/unit_disc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub struct UnitDisc;
impl<F: Float + SampleUniform> Distribution<[F; 2]> for UnitDisc {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> [F; 2] {
let uniform = Uniform::new(F::from(-1.).unwrap(), F::from(1.).unwrap());
let uniform = Uniform::new(F::from(-1.).unwrap(), F::from(1.).unwrap()).unwrap();
let mut x1;
let mut x2;
loop {
Expand Down
2 changes: 1 addition & 1 deletion rand_distr/src/unit_sphere.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub struct UnitSphere;
impl<F: Float + SampleUniform> Distribution<[F; 3]> for UnitSphere {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> [F; 3] {
let uniform = Uniform::new(F::from(-1.).unwrap(), F::from(1.).unwrap());
let uniform = Uniform::new(F::from(-1.).unwrap(), F::from(1.).unwrap()).unwrap();
loop {
let (x1, x2) = (uniform.sample(rng), uniform.sample(rng));
let sum = x1 * x1 + x2 * x2;
Expand Down
6 changes: 3 additions & 3 deletions rand_distr/src/weighted_alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,8 @@ impl<W: AliasableWeight> WeightedAliasIndex<W> {

// Prepare distributions for sampling. Creating them beforehand improves
// sampling performance.
let uniform_index = Uniform::new(0, n);
let uniform_within_weight_sum = Uniform::new(W::ZERO, weight_sum);
let uniform_index = Uniform::new(0, n).unwrap();
let uniform_within_weight_sum = Uniform::new(W::ZERO, weight_sum).unwrap();

Ok(Self {
aliases: aliases.aliases,
Expand Down Expand Up @@ -458,7 +458,7 @@ mod test {
let random_weight_distribution = Uniform::new_inclusive(
W::ZERO,
W::MAX / W::try_from_u32_lossy(NUM_WEIGHTS).unwrap(),
);
).unwrap();
for _ in 0..NUM_WEIGHTS {
weights.push(rng.sample(&random_weight_distribution));
}
Expand Down
7 changes: 4 additions & 3 deletions src/distributions/distribution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ pub trait Distribution<T> {
/// .collect();
///
/// // Dice-rolling:
/// let die_range = Uniform::new_inclusive(1, 6);
/// let die_range = Uniform::new_inclusive(1, 6).unwrap();
/// let mut roll_die = die_range.sample_iter(&mut rng);
/// while roll_die.next().unwrap() != 6 {
/// println!("Not a 6; rolling again!");
Expand Down Expand Up @@ -93,7 +93,7 @@ pub trait Distribution<T> {
///
/// let mut rng = thread_rng();
///
/// let die = Uniform::new_inclusive(1, 6);
/// let die = Uniform::new_inclusive(1, 6).unwrap();
/// let even_number = die.map(|num| num % 2 == 0);
/// while !even_number.sample(&mut rng) {
/// println!("Still odd; rolling again!");
Expand Down Expand Up @@ -227,7 +227,7 @@ mod tests {

#[test]
fn test_distributions_map() {
let dist = Uniform::new_inclusive(0, 5).map(|val| val + 15);
let dist = Uniform::new_inclusive(0, 5).unwrap().map(|val| val + 15);

let mut rng = crate::test::rng(212);
let val = dist.sample(&mut rng);
Expand All @@ -240,6 +240,7 @@ mod tests {
rng: &mut R,
) -> impl Iterator<Item = i32> + '_ {
Uniform::new_inclusive(1, 6)
.unwrap()
.sample_iter(rng)
.filter(|x| *x != 5)
.take(10)
Expand Down
4 changes: 2 additions & 2 deletions src/distributions/other.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ impl Distribution<char> for Standard {
// reserved for surrogates. This is the size of that gap.
const GAP_SIZE: u32 = 0xDFFF - 0xD800 + 1;

// Uniform::new(0, 0x11_0000 - GAP_SIZE) can also be used but it
// Uniform::new(0, 0x11_0000 - GAP_SIZE) can also be used, but it
// seemed slower.
let range = Uniform::new(GAP_SIZE, 0x11_0000);
let range = Uniform::new(GAP_SIZE, 0x11_0000).unwrap();

let mut n = range.sample(rng);
if n <= 0xDFFF {
Expand Down
2 changes: 1 addition & 1 deletion src/distributions/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ impl<'a, T> Slice<'a, T> {
0 => Err(EmptySlice),
len => Ok(Self {
slice,
range: Uniform::new(0, len),
range: Uniform::new(0, len).unwrap(),
}),
}
}
Expand Down
Loading

0 comments on commit e40f00a

Please sign in to comment.