diff options
Diffstat (limited to 'src/stats/mod.rs')
-rwxr-xr-x | src/stats/mod.rs | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/src/stats/mod.rs b/src/stats/mod.rs new file mode 100755 index 0000000..4f926de --- /dev/null +++ b/src/stats/mod.rs @@ -0,0 +1,112 @@ +//! [Criterion]'s statistics library. +//! +//! [Criterion]: https://github.com/bheisler/criterion.rs +//! +//! **WARNING** This library is criterion's implementation detail and there no plans to stabilize +//! it. In other words, the API may break at any time without notice. + +#[cfg(test)] +mod test; + +pub mod bivariate; +pub mod tuple; +pub mod univariate; + +mod float; +mod rand_util; + +use std::mem; +use std::ops::Deref; + +use crate::stats::float::Float; +use crate::stats::univariate::Sample; + +/// The bootstrap distribution of some parameter +#[derive(Clone)] +pub struct Distribution<A>(Box<[A]>); + +impl<A> Distribution<A> +where + A: Float, +{ + /// Create a distribution from the given values + pub fn from(values: Box<[A]>) -> Distribution<A> { + Distribution(values) + } + + /// Computes the confidence interval of the population parameter using percentiles + /// + /// # Panics + /// + /// Panics if the `confidence_level` is not in the `(0, 1)` range. + pub fn confidence_interval(&self, confidence_level: A) -> (A, A) + where + usize: cast::From<A, Output = Result<usize, cast::Error>>, + { + let _0 = A::cast(0); + let _1 = A::cast(1); + let _50 = A::cast(50); + + assert!(confidence_level > _0 && confidence_level < _1); + + let percentiles = self.percentiles(); + + // FIXME(privacy) this should use the `at_unchecked()` method + ( + percentiles.at(_50 * (_1 - confidence_level)), + percentiles.at(_50 * (_1 + confidence_level)), + ) + } + + /// Computes the "likelihood" of seeing the value `t` or "more extreme" values in the + /// distribution. + pub fn p_value(&self, t: A, tails: &Tails) -> A { + use std::cmp; + + let n = self.0.len(); + let hits = self.0.iter().filter(|&&x| x < t).count(); + + let tails = A::cast(match *tails { + Tails::One => 1, + Tails::Two => 2, + }); + + A::cast(cmp::min(hits, n - hits)) / A::cast(n) * tails + } +} + +impl<A> Deref for Distribution<A> { + type Target = Sample<A>; + + fn deref(&self) -> &Sample<A> { + let slice: &[_] = &self.0; + + unsafe { mem::transmute(slice) } + } +} + +/// Number of tails for significance testing +pub enum Tails { + /// One tailed test + One, + /// Two tailed test + Two, +} + +fn dot<A>(xs: &[A], ys: &[A]) -> A +where + A: Float, +{ + xs.iter() + .zip(ys) + .fold(A::cast(0), |acc, (&x, &y)| acc + x * y) +} + +fn sum<A>(xs: &[A]) -> A +where + A: Float, +{ + use std::ops::Add; + + xs.iter().cloned().fold(A::cast(0), Add::add) +} |