criterion/stats/
mod.rs

1//! [Criterion]'s statistics library.
2//!
3//! [Criterion]: https://github.com/bheisler/criterion.rs
4//!
5//! **WARNING** This library is criterion's implementation detail and there no plans to stabilize
6//! it. In other words, the API may break at any time without notice.
7
8#[cfg(test)]
9mod test;
10
11pub mod bivariate;
12pub mod tuple;
13pub mod univariate;
14
15mod float;
16mod rand_util;
17
18use std::mem;
19use std::ops::Deref;
20
21use cast;
22use stats::float::Float;
23use stats::univariate::Sample;
24
25/// The bootstrap distribution of some parameter
26pub struct Distribution<A>(Box<[A]>);
27
28impl<A> Distribution<A>
29where
30    A: Float,
31{
32    /// Create a distribution from the given values
33    pub fn from(values: Box<[A]>) -> Distribution<A> {
34        Distribution(values)
35    }
36
37    /// Computes the confidence interval of the population parameter using percentiles
38    ///
39    /// # Panics
40    ///
41    /// Panics if the `confidence_level` is not in the `(0, 1)` range.
42    pub fn confidence_interval(&self, confidence_level: A) -> (A, A)
43    where
44        usize: cast::From<A, Output = Result<usize, cast::Error>>,
45    {
46        let _0 = A::cast(0);
47        let _1 = A::cast(1);
48        let _50 = A::cast(50);
49
50        assert!(confidence_level > _0 && confidence_level < _1);
51
52        let percentiles = self.percentiles();
53
54        // FIXME(privacy) this should use the `at_unchecked()` method
55        (
56            percentiles.at(_50 * (_1 - confidence_level)),
57            percentiles.at(_50 * (_1 + confidence_level)),
58        )
59    }
60
61    /// Computes the "likelihood" of seeing the value `t` or "more extreme" values in the
62    /// distribution.
63    pub fn p_value(&self, t: A, tails: &Tails) -> A {
64        use std::cmp;
65
66        let n = self.0.len();
67        let hits = self.0.iter().filter(|&&x| x < t).count();
68
69        let tails = A::cast(match *tails {
70            Tails::One => 1,
71            Tails::Two => 2,
72        });
73
74        A::cast(cmp::min(hits, n - hits)) / A::cast(n) * tails
75    }
76}
77
78impl<A> Deref for Distribution<A> {
79    type Target = Sample<A>;
80
81    fn deref(&self) -> &Sample<A> {
82        let slice: &[_] = &self.0;
83
84        unsafe { mem::transmute(slice) }
85    }
86}
87
88/// Number of tails for significance testing
89pub enum Tails {
90    /// One tailed test
91    One,
92    /// Two tailed test
93    Two,
94}
95
96fn dot<A>(xs: &[A], ys: &[A]) -> A
97where
98    A: Float,
99{
100    xs.iter()
101        .zip(ys)
102        .fold(A::cast(0), |acc, (&x, &y)| acc + x * y)
103}
104
105fn sum<A>(xs: &[A]) -> A
106where
107    A: Float,
108{
109    use std::ops::Add;
110
111    xs.iter().cloned().fold(A::cast(0), Add::add)
112}