Skip to content

Commit

Permalink
Zipf: let n have type F (#1518)
Browse files Browse the repository at this point in the history
  • Loading branch information
dhardy authored Nov 12, 2024
1 parent 585b29f commit ad67294
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 17 deletions.
2 changes: 1 addition & 1 deletion benches/benches/distr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ fn bench(c: &mut Criterion<CyclesPerByte>) {
g.finish();

let mut g = c.benchmark_group("zipf");
distr_float!(g, "zipf", f64, Zipf::new(10, 1.5).unwrap());
distr_float!(g, "zipf", f64, Zipf::new(10.0, 1.5).unwrap());
distr_float!(g, "zeta", f64, Zeta::new(1.5).unwrap());
g.finish();

Expand Down
1 change: 1 addition & 0 deletions rand_distr/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- 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)
- Change parameter type of `Zipf::new`: `n` is now floating-point (#1518)

### Added
- Add plots for `rand_distr` distributions to documentation (#1434)
Expand Down
31 changes: 16 additions & 15 deletions rand_distr/src/zipf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use rand::Rng;
/// use rand::prelude::*;
/// use rand_distr::Zipf;
///
/// let val: f64 = rand::rng().sample(Zipf::new(10, 1.5).unwrap());
/// let val: f64 = rand::rng().sample(Zipf::new(10.0, 1.5).unwrap());
/// println!("{}", val);
/// ```
///
Expand Down Expand Up @@ -92,16 +92,17 @@ where
/// Construct a new `Zipf` distribution for a set with `n` elements and a
/// frequency rank exponent `s`.
///
/// For large `n`, rounding may occur to fit the number into the float type.
/// The parameter `n` is typically integral, however we use type
/// <pre><code>F: [Float]</code></pre> in order to permit very large values
/// and since our implementation requires a floating-point type.
#[inline]
pub fn new(n: u64, s: F) -> Result<Zipf<F>, Error> {
pub fn new(n: F, s: F) -> Result<Zipf<F>, Error> {
if !(s >= F::zero()) {
return Err(Error::STooSmall);
}
if n < 1 {
if n < F::one() {
return Err(Error::NTooSmall);
}
let n = F::from(n).unwrap(); // This does not fail.
let q = if s != F::one() {
// Make sure to calculate the division only once.
F::one() / (F::one() - s)
Expand Down Expand Up @@ -173,24 +174,24 @@ mod tests {
#[test]
#[should_panic]
fn zipf_s_too_small() {
Zipf::new(10, -1.).unwrap();
Zipf::new(10., -1.).unwrap();
}

#[test]
#[should_panic]
fn zipf_n_too_small() {
Zipf::new(0, 1.).unwrap();
Zipf::new(0., 1.).unwrap();
}

#[test]
#[should_panic]
fn zipf_nan() {
Zipf::new(10, f64::NAN).unwrap();
Zipf::new(10., f64::NAN).unwrap();
}

#[test]
fn zipf_sample() {
let d = Zipf::new(10, 0.5).unwrap();
let d = Zipf::new(10., 0.5).unwrap();
let mut rng = crate::test::rng(2);
for _ in 0..1000 {
let r = d.sample(&mut rng);
Expand All @@ -200,7 +201,7 @@ mod tests {

#[test]
fn zipf_sample_s_1() {
let d = Zipf::new(10, 1.).unwrap();
let d = Zipf::new(10., 1.).unwrap();
let mut rng = crate::test::rng(2);
for _ in 0..1000 {
let r = d.sample(&mut rng);
Expand All @@ -210,7 +211,7 @@ mod tests {

#[test]
fn zipf_sample_s_0() {
let d = Zipf::new(10, 0.).unwrap();
let d = Zipf::new(10., 0.).unwrap();
let mut rng = crate::test::rng(2);
for _ in 0..1000 {
let r = d.sample(&mut rng);
Expand All @@ -221,7 +222,7 @@ mod tests {

#[test]
fn zipf_sample_large_n() {
let d = Zipf::new(u64::MAX, 1.5).unwrap();
let d = Zipf::new(f64::MAX, 1.5).unwrap();
let mut rng = crate::test::rng(2);
for _ in 0..1000 {
let r = d.sample(&mut rng);
Expand All @@ -232,12 +233,12 @@ mod tests {

#[test]
fn zipf_value_stability() {
test_samples(Zipf::new(10, 0.5).unwrap(), 0f32, &[10.0, 2.0, 6.0, 7.0]);
test_samples(Zipf::new(10, 2.0).unwrap(), 0f64, &[1.0, 2.0, 3.0, 2.0]);
test_samples(Zipf::new(10., 0.5).unwrap(), 0f32, &[10.0, 2.0, 6.0, 7.0]);
test_samples(Zipf::new(10., 2.0).unwrap(), 0f64, &[1.0, 2.0, 3.0, 2.0]);
}

#[test]
fn zipf_distributions_can_be_compared() {
assert_eq!(Zipf::new(1, 2.0), Zipf::new(1, 2.0));
assert_eq!(Zipf::new(1.0, 2.0), Zipf::new(1.0, 2.0));
}
}
2 changes: 1 addition & 1 deletion rand_distr/tests/cdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ fn zipf() {
let parameters = [(1000, 1.0), (500, 2.0), (1000, 0.5)];

for (seed, (n, x)) in parameters.into_iter().enumerate() {
let dist = rand_distr::Zipf::new(n, x).unwrap();
let dist = rand_distr::Zipf::new(n as f64, x).unwrap();
test_discrete(seed as u64, dist, |k| cdf(k, n, x));
}
}
Expand Down

0 comments on commit ad67294

Please sign in to comment.