Skip to content

Commit 6155a1c

Browse files
committed
std::rand: implement the F distribution.
1 parent 1ee4291 commit 6155a1c

File tree

2 files changed

+60
-1
lines changed

2 files changed

+60
-1
lines changed

src/libstd/rand/distributions/gamma.rs

+59
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,55 @@ impl IndependentSample<f64> for ChiSquared {
225225
}
226226
}
227227

228+
/// The Fisher F distribution `F(m, n)`.
229+
///
230+
/// This distribution is equivalent to the ratio of two normalised
231+
/// chi-squared distributions, that is, `F(m,n) = (χ²(m)/m) /
232+
/// (χ²(n)/n)`.
233+
///
234+
/// # Example
235+
///
236+
/// ```rust
237+
/// use std::rand;
238+
/// use std::rand::distributions::{FisherF, IndependentSample};
239+
///
240+
/// fn main() {
241+
/// let f = FisherF::new(2.0, 32.0);
242+
/// let v = f.ind_sample(&mut rand::task_rng());
243+
/// println!("{} is from an F(2, 32) distribution", v)
244+
/// }
245+
/// ```
246+
pub struct FisherF {
247+
priv numer: ChiSquared,
248+
priv denom: ChiSquared,
249+
// denom_dof / numer_dof so that this can just be a straight
250+
// multiplication, rather than a division.
251+
priv dof_ratio: f64,
252+
}
253+
254+
impl FisherF {
255+
/// Create a new `FisherF` distribution, with the given
256+
/// parameter. Fails if either `m` or `n` are not positive.
257+
pub fn new(m: f64, n: f64) -> FisherF {
258+
assert!(m > 0.0, "FisherF::new called with `m < 0`");
259+
assert!(n > 0.0, "FisherF::new called with `n < 0`");
260+
261+
FisherF {
262+
numer: ChiSquared::new(m),
263+
denom: ChiSquared::new(n),
264+
dof_ratio: n / m
265+
}
266+
}
267+
}
268+
impl Sample<f64> for FisherF {
269+
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
270+
}
271+
impl IndependentSample<f64> for FisherF {
272+
fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
273+
self.numer.ind_sample(rng) / self.denom.ind_sample(rng) * self.dof_ratio
274+
}
275+
}
276+
228277
#[cfg(test)]
229278
mod test {
230279
use rand::*;
@@ -264,6 +313,16 @@ mod test {
264313
fn test_log_normal_invalid_dof() {
265314
ChiSquared::new(-1.0);
266315
}
316+
317+
#[test]
318+
fn test_f() {
319+
let mut f = FisherF::new(2.0, 32.0);
320+
let mut rng = task_rng();
321+
for _ in range(0, 1000) {
322+
f.sample(&mut rng);
323+
f.ind_sample(&mut rng);
324+
}
325+
}
267326
}
268327

269328
#[cfg(test)]

src/libstd/rand/distributions/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use rand::{Rng, Rand};
2727
use clone::Clone;
2828

2929
pub use self::range::Range;
30-
pub use self::gamma::{Gamma, ChiSquared};
30+
pub use self::gamma::{Gamma, ChiSquared, FisherF};
3131
pub use self::normal::{Normal, LogNormal};
3232
pub use self::exponential::Exp;
3333

0 commit comments

Comments
 (0)