@@ -225,6 +225,55 @@ impl IndependentSample<f64> for ChiSquared {
225
225
}
226
226
}
227
227
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
+
228
277
#[ cfg( test) ]
229
278
mod test {
230
279
use rand:: * ;
@@ -264,6 +313,16 @@ mod test {
264
313
fn test_log_normal_invalid_dof ( ) {
265
314
ChiSquared :: new ( -1.0 ) ;
266
315
}
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
+ }
267
326
}
268
327
269
328
#[ cfg( test) ]
0 commit comments