Skip to content

Commit 53daaa7

Browse files
committed
Avoid panics on invalid parameters for Zipf
The generalized Zipf distribution is not well defined when its normalization constant is 0 (when s is infinite) or is infinity (when n is infinite and s is <= 1).
1 parent fe2a875 commit 53daaa7

File tree

2 files changed

+12
-5
lines changed

2 files changed

+12
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1919
### Fixes
2020
- Fix `Geometric::new` for small `p > 0` where `1 - p` rounds to 1 (#36)
2121
- Fix panic in `FisherF::new` on almost zero parameters (#39)
22+
- Fix panic in `Zipf::new` by rejecting more invalid parameters (#41)
2223

2324
## [0.5.2]
2425

src/zipf.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,20 @@ where
6666
/// Error type returned from [`Zipf::new`].
6767
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
6868
pub enum Error {
69-
/// `s < 0` or `nan`.
69+
/// `s < 0` or `s` is `nan` or `inf`
7070
STooSmall,
71-
/// `n < 1`.
71+
/// `n < 1` or `n` is `nan`
7272
NTooSmall,
73+
/// `n = inf` and `s <= 1`
74+
IllDefined,
7375
}
7476

7577
impl fmt::Display for Error {
7678
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7779
f.write_str(match self {
78-
Error::STooSmall => "s < 0 or is NaN in Zipf distribution",
79-
Error::NTooSmall => "n < 1 in Zipf distribution",
80+
Error::STooSmall => "s < 0 or is inf or NaN in Zipf distribution",
81+
Error::NTooSmall => "n < 1 or is NaN in Zipf distribution",
82+
Error::IllDefined => "n = inf and s <= 1 in Zipf distribution",
8083
})
8184
}
8285
}
@@ -97,12 +100,15 @@ where
97100
/// and since our implementation requires a floating-point type.
98101
#[inline]
99102
pub fn new(n: F, s: F) -> Result<Zipf<F>, Error> {
100-
if !(s >= F::zero()) {
103+
if !(s >= F::zero()) || s.is_infinite() {
101104
return Err(Error::STooSmall);
102105
}
103106
if n < F::one() {
104107
return Err(Error::NTooSmall);
105108
}
109+
if n.is_infinite() && s <= F::one() {
110+
return Err(Error::IllDefined);
111+
}
106112
let q = if s != F::one() {
107113
// Make sure to calculate the division only once.
108114
F::one() / (F::one() - s)

0 commit comments

Comments
 (0)