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 crate::stats::float::Float;
22use crate::stats::univariate::Sample;
23
24/// The bootstrap distribution of some parameter
25#[derive(Clone)]
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}
113