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)] |

9 | mod test; |

10 | |

11 | pub mod bivariate; |

12 | pub mod tuple; |

13 | pub mod univariate; |

14 | |

15 | mod float; |

16 | mod rand_util; |

17 | |

18 | use std::mem; |

19 | use std::ops::Deref; |

20 | |

21 | use crate::stats::float::Float; |

22 | use crate::stats::univariate::Sample; |

23 | |

24 | /// The bootstrap distribution of some parameter |

25 | #[derive(Clone)] |

26 | pub struct Distribution<A>(Box<[A]>); |

27 | |

28 | impl<A> Distribution<A> |

29 | where |

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 | |

78 | impl<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 |

89 | pub enum Tails { |

90 | /// One tailed test |

91 | One, |

92 | /// Two tailed test |

93 | Two, |

94 | } |

95 | |

96 | fn dot<A>(xs: &[A], ys: &[A]) -> A |

97 | where |

98 | A: Float, |

99 | { |

100 | xs.iter() |

101 | .zip(ys) |

102 | .fold(A::cast(0), |acc, (&x, &y)| acc + x * y) |

103 | } |

104 | |

105 | fn sum<A>(xs: &[A]) -> A |

106 | where |

107 | A: Float, |

108 | { |

109 | use std::ops::Add; |

110 | |

111 | xs.iter().cloned().fold(A::cast(0), Add::add) |

112 | } |

113 |