diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d78a8d8ca9..71c7353174c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,14 +21,11 @@ You may also find the [Upgrade Guide](https://rust-random.github.io/book/update. - Rename `rand::distributions` to `rand::distr` (#1470) - The `serde1` feature has been renamed `serde` (#1477) - The implicit feature `rand_chacha` has been removed. This is enabled by `std_rng`. (#1473) -- Mark `WeightError`, `PoissonError`, `BinomialError` as `#[non_exhaustive]` (#1480). +- Mark `WeightError` as `#[non_exhaustive]` (#1480). - Add `p()` for `Bernoulli` to access probability (#1481) - Add `UniformUsize` and use to make `Uniform` for `usize` portable (#1487) -- Remove support for generating `isize` and `usize` values with `Standard`, `Uniform` and `Fill` and usage as a `WeightedAliasIndex` weight (#1487) - Require `Clone` and `AsRef` bound for `SeedableRng::Seed`. (#1491) - Improve SmallRng initialization performance (#1482) -- Implement `Distribution` for `Poisson` (#1498) -- Limit the maximal acceptable lambda for `Poisson` to solve (#1312) (#1498) - Rename `Rng::gen_iter` to `random_iter` (#1500) - Rename `rand::thread_rng()` to `rand::rng()`, and remove from the prelude (#1506) - Remove `rand::random()` from the prelude (#1506) diff --git a/rand_distr/CHANGELOG.md b/rand_distr/CHANGELOG.md index c9ab729be8c..8e6cfff686b 100644 --- a/rand_distr/CHANGELOG.md +++ b/rand_distr/CHANGELOG.md @@ -10,6 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Move some of the computations in Binomial from `sample` to `new` (#1484) - Add Kolmogorov Smirnov test for sampling of `Normal` and `Binomial` (#1494) - Add Kolmogorov Smirnov test for more distributions (#1504) +- Mark `WeightError`, `PoissonError`, `BinomialError` as `#[non_exhaustive]` (#1480). +- Remove support for generating `isize` and `usize` values with `Standard`, `Uniform` and `Fill` and usage as a `WeightedAliasIndex` weight (#1487) +- Limit the maximal acceptable lambda for `Poisson` to solve (#1312) (#1498) ### Added - Add plots for `rand_distr` distributions to documentation (#1434) diff --git a/rand_distr/src/poisson.rs b/rand_distr/src/poisson.rs index f06c29aef41..20b41ace64a 100644 --- a/rand_distr/src/poisson.rs +++ b/rand_distr/src/poisson.rs @@ -39,6 +39,17 @@ use rand::Rng; /// let v: f64 = poi.sample(&mut rand::rng()); /// println!("{} is from a Poisson(2) distribution", v); /// ``` +/// +/// # Integer vs FP return type +/// +/// This implementation uses floating-point (FP) logic internally. +/// +/// Due to the parameter limit λ < [Self::MAX_LAMBDA], it +/// statistically impossible to sample a value larger [`u64::MAX`]. As such, it +/// is reasonable to cast generated samples to `u64` using `as`: +/// `distr.sample(&mut rng) as u64` (and memory safe since Rust 1.45). +/// Similarly, when `λ < 4.2e9` it can be safely assumed that samples are less +/// than `u32::MAX`. #[derive(Clone, Copy, Debug, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Poisson(Method) @@ -238,14 +249,6 @@ where } } -impl Distribution for Poisson { - #[inline] - fn sample(&self, rng: &mut R) -> u64 { - // `as` from float to int saturates - as Distribution>::sample(self, rng) as u64 - } -} - #[cfg(test)] mod test { use super::*; diff --git a/rand_distr/src/zeta.rs b/rand_distr/src/zeta.rs index 3c2f55546e5..e06208c94ea 100644 --- a/rand_distr/src/zeta.rs +++ b/rand_distr/src/zeta.rs @@ -40,6 +40,17 @@ use rand::{distr::OpenClosed01, Rng}; /// println!("{}", val); /// ``` /// +/// # Integer vs FP return type +/// +/// This implementation uses floating-point (FP) logic internally, which can +/// potentially generate very large samples (exceeding e.g. `u64::MAX`). +/// +/// It is *safe* to cast such results to an integer type using `as` +/// (e.g. `distr.sample(&mut rng) as u64`), since such casts are saturating +/// (e.g. `2f64.powi(64) as u64 == u64::MAX`). It is up to the user to +/// determine whether this potential loss of accuracy is acceptable +/// (this determination may depend on the distribution's parameters). +/// /// # Notes /// /// The zeta distribution has no upper limit. Sampled values may be infinite. diff --git a/rand_distr/src/zipf.rs b/rand_distr/src/zipf.rs index 0a56fdf8182..9d98458db08 100644 --- a/rand_distr/src/zipf.rs +++ b/rand_distr/src/zipf.rs @@ -39,6 +39,13 @@ use rand::Rng; /// println!("{}", val); /// ``` /// +/// # Integer vs FP return type +/// +/// This implementation uses floating-point (FP) logic internally. It may be +/// expected that the samples are no greater than `n`, thus it is reasonable to +/// cast generated samples to any integer type which can also represent `n` +/// (e.g. `distr.sample(&mut rng) as u64`). +/// /// # Implementation details /// /// Implemented via [rejection sampling](https://en.wikipedia.org/wiki/Rejection_sampling),