Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bernoulli: catch other invalid parameterisations; fix doc links #925

Merged
merged 4 commits into from Jan 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -9,6 +9,10 @@ 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
### Fixes
- The `Bernoulli` distribution constructors now reports an error on NaN and on
`denominator == 0`. (#925)

### Additions
- Implement `std::error::Error` for `BernoulliError` (#919)

Expand Down
14 changes: 5 additions & 9 deletions rand_core/src/lib.rs
Expand Up @@ -141,24 +141,22 @@ pub trait RngCore {
///
/// RNGs must implement at least one method from this trait directly. In
/// the case this method is not implemented directly, it can be implemented
/// using `self.next_u64() as u32` or via
/// [`fill_bytes`](impls::next_u32_via_fill).
/// using `self.next_u64() as u32` or via [`impls::next_u32_via_fill`].
fn next_u32(&mut self) -> u32;

/// Return the next random `u64`.
///
/// RNGs must implement at least one method from this trait directly. In
/// the case this method is not implemented directly, it can be implemented
/// via [`next_u32`](impls::next_u64_via_u32) or via
/// [`fill_bytes`](impls::next_u64_via_fill).
/// via [`impls::next_u64_via_u32`] or via [`impls::next_u64_via_fill`].
fn next_u64(&mut self) -> u64;

/// Fill `dest` with random data.
///
/// RNGs must implement at least one method from this trait directly. In
/// the case this method is not implemented directly, it can be implemented
/// via [`next_u*`](impls::fill_bytes_via_next) or
/// via [`try_fill_bytes`](RngCore::try_fill_bytes); if this generator can
/// via [`impls::fill_bytes_via_next`] or
/// via [`RngCore::try_fill_bytes`]; if this generator can
/// fail the implementation must choose how best to handle errors here
/// (e.g. panic with a descriptive message or log a warning and retry a few
/// times).
Expand All @@ -176,12 +174,10 @@ pub trait RngCore {
/// by external (true) RNGs (e.g. `OsRng`) which can fail. It may be used
/// directly to generate keys and to seed (infallible) PRNGs.
///
/// Other than error handling, this method is identical to [`fill_bytes`];
/// Other than error handling, this method is identical to [`RngCore::fill_bytes`];
/// thus this may be implemented using `Ok(self.fill_bytes(dest))` or
/// `fill_bytes` may be implemented with
/// `self.try_fill_bytes(dest).unwrap()` or more specific error handling.
///
/// [`fill_bytes`]: RngCore::fill_bytes
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error>;
}

Expand Down
8 changes: 5 additions & 3 deletions src/distributions/bernoulli.rs
Expand Up @@ -93,7 +93,7 @@ impl Bernoulli {
/// 2<sup>-64</sup> in `[0, 1]` can be represented as a `f64`.)
#[inline]
pub fn new(p: f64) -> Result<Bernoulli, BernoulliError> {
if p < 0.0 || p >= 1.0 {
if !(p >= 0.0 && p < 1.0) {
if p == 1.0 { return Ok(Bernoulli { p_int: ALWAYS_TRUE }) }
return Err(BernoulliError::InvalidProbability);
}
Expand All @@ -104,11 +104,13 @@ impl Bernoulli {
/// `numerator`-in-`denominator`. I.e. `new_ratio(2, 3)` will return
/// a `Bernoulli` with a 2-in-3 chance, or about 67%, of returning `true`.
///
/// If `numerator == denominator` then the returned `Bernoulli` will always
/// return `true`. If `numerator == 0` it will always return `false`.
/// For `numerator > denominator` and `denominator == 0`, this returns an
/// error. Otherwise, for `numerator == denominator`, samples are always
/// true; for `numerator == 0` samples are always false.
#[inline]
pub fn from_ratio(numerator: u32, denominator: u32) -> Result<Bernoulli, BernoulliError> {
if numerator > denominator {
if numerator > denominator || denominator == 0 {
return Err(BernoulliError::InvalidProbability);
}
if numerator == denominator {
Expand Down
16 changes: 4 additions & 12 deletions src/distributions/mod.rs
Expand Up @@ -31,14 +31,14 @@
//! # The `Standard` distribution
//!
//! The [`Standard`] distribution is important to mention. This is the
//! distribution used by [`Rng::gen()`] and represents the "default" way to
//! distribution used by [`Rng::gen`] and represents the "default" way to
//! produce a random value for many different types, including most primitive
//! types, tuples, arrays, and a few derived types. See the documentation of
//! [`Standard`] for more details.
//!
//! Implementing `Distribution<T>` for [`Standard`] for user types `T` makes it
//! possible to generate type `T` with [`Rng::gen()`], and by extension also
//! with the [`random()`] function.
//! possible to generate type `T` with [`Rng::gen`], and by extension also
//! with the [`random`] function.
//!
//! ## Random characters
//!
Expand Down Expand Up @@ -89,15 +89,7 @@
//! [`rand_distr`]: https://crates.io/crates/rand_distr
//! [`statrs`]: https://crates.io/crates/statrs

//! [`Alphanumeric`]: distributions::Alphanumeric
//! [`Bernoulli`]: distributions::Bernoulli
//! [`Open01`]: distributions::Open01
//! [`OpenClosed01`]: distributions::OpenClosed01
//! [`Standard`]: distributions::Standard
//! [`Uniform`]: distributions::Uniform
//! [`Uniform::new`]: distributions::Uniform::new
//! [`Uniform::new_inclusive`]: distributions::Uniform::new_inclusive
//! [`weighted`]: distributions::weighted
//! [`random`]: crate::random
//! [`rand_distr`]: https://crates.io/crates/rand_distr
//! [`statrs`]: https://crates.io/crates/statrs

Expand Down
12 changes: 5 additions & 7 deletions src/rngs/mod.rs
Expand Up @@ -84,13 +84,11 @@
//! Some suggestions are: [`rand_chacha`], [`rand_pcg`], [`rand_xoshiro`].
//! A full list can be found by searching for crates with the [`rng` tag].
//!
//! [`SmallRng`]: rngs::SmallRng
//! [`StdRng`]: rngs::StdRng
//! [`OsRng`]: rngs::OsRng
//! [`ThreadRng`]: rngs::ThreadRng
//! [`mock::StepRng`]: rngs::mock::StepRng
//! [`adapter::ReadRng`]: rngs::adapter::ReadRng
//! [`adapter::ReseedingRng`]: rngs::adapter::ReseedingRng
//! [`Rng`]: crate::Rng
//! [`RngCore`]: crate::RngCore
//! [`CryptoRng`]: crate::CryptoRng
//! [`SeedableRng`]: crate::SeedableRng
//! [`thread_rng`]: crate::thread_rng
//! [`rdrand`]: https://crates.io/crates/rdrand
//! [`rand_jitter`]: https://crates.io/crates/rand_jitter
//! [`rand_chacha`]: https://crates.io/crates/rand_chacha
Expand Down
3 changes: 1 addition & 2 deletions src/rngs/std.rs
Expand Up @@ -22,8 +22,7 @@ pub(crate) use rand_chacha::ChaCha20Core as Core;
/// on the current platform, to be statistically strong and unpredictable
/// (meaning a cryptographically secure PRNG).
///
/// The current algorithm used is the ChaCha block cipher with either 20 or 12
/// rounds (see the `stdrng_*` feature flags, documented in the README).
/// The current algorithm used is the ChaCha block cipher with 20 rounds.
/// This may change as new evidence of cipher security and performance
/// becomes available.
///
Expand Down
10 changes: 5 additions & 5 deletions src/seq/mod.rs
Expand Up @@ -10,15 +10,15 @@
//!
//! This module provides:
//!
//! * [`seq::SliceRandom`] slice sampling and mutation
//! * [`seq::IteratorRandom`] iterator sampling
//! * [`seq::index::sample`] low-level API to choose multiple indices from
//! * [`SliceRandom`] slice sampling and mutation
//! * [`IteratorRandom`] iterator sampling
//! * [`index::sample`] low-level API to choose multiple indices from
//! `0..length`
//!
//! Also see:
//!
//! * [`distributions::weighted`] module which provides implementations of
//! weighted index sampling.
//! * [`crate::distributions::weighted`] module which provides
//! implementations of weighted index sampling.
//!
//! In order to make results reproducible across 32-64 bit architectures, all
//! `usize` indices are sampled as a `u32` where possible (also providing a
Expand Down