-
-
Notifications
You must be signed in to change notification settings - Fork 10
Description
Summary
I observe that when n is a large fraction of u64::MAX and p is a small floating point value, Binomial::sample sometimes panics with the following error:
thread 'main' panicked at /playground/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rand_distr-0.5.1/src/binomial.rs:174:5:
assertion failed: x < (i64::MAX as f64)
stack backtrace:
0: rust_begin_unwind
at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/panicking.rs:692:5
1: core::panicking::panic_fmt
at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/panicking.rs:75:14
2: core::panicking::panic
at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/panicking.rs:145:5
3: rand_distr::binomial::f64_to_i64
at ./.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rand_distr-0.5.1/src/binomial.rs:174:5
4: rand_distr::binomial::btpe
at ./.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rand_distr-0.5.1/src/binomial.rs:344:18
5: <rand_distr::binomial::Binomial as rand::distr::distribution::Distribution<u64>>::sample
at ./.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rand_distr-0.5.1/src/binomial.rs:385:49
6: playground::main
at ./src/main.rs:19:17
7: core::ops::function::FnOnce::call_once
at ./.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
I was using current stable rust (1.85) and rand_distr 0.5.1, rand + rand_chacha v0.9.0, on x86_64 (Ryzen 7 7840 HS). The executable is linked to libm from the Arch Linux build of glibc, version 2.41+r9+ga900dbaf70f0-1.
Code sample:
Starting from a specific random generator state, the issue can be reproduced at the Rust Playground with both Stable and Nightly compilers.
use rand::SeedableRng;
use rand_chacha::ChaCha12Rng;
use rand_distr::{Binomial, Distribution};
fn main() {
let n: u64 = 13301667360732270876;
let p: f64 = 6.099468852510934e-7;
let seed: [u8; 32] = [
65, 56, 42, 90, 76, 75, 12, 151, 226, 205, 74, 251, 40, 152, 42, 207, 114, 35, 176, 234,
170, 225, 85, 155, 136, 8, 223, 69, 98, 184, 87, 212,
];
let pos: u128 = 1940220;
let stream: u64 = 0;
let mut rng = ChaCha12Rng::from_seed(seed);
rng.set_stream(stream);
rng.set_word_pos(pos);
let bin = Binomial::new(n, p).unwrap();
let value = bin.sample(&mut rng);
println!("Output: {}", value);
}Let me know if you'd like me to provide more information; I will try to debug this further if I ever have enough free time.
Workaround
In case anyone else is affected by this edge case, my current workaround is to use the fact that Binomial(n + m, p) can be sampled by sampling x ~ Binomial(n, p), y ~ Binomial(m, p), and outputting x+y (or adding together more copies of smaller distributions, if necessary; I have yet to experimentally verify an exact upper bound for n below which this error does not occur. n <= 1<<62 appears fine so far.)