Skip to content

Commit 5d6d67b

Browse files
committed
Move add and merge to trait
This should make it possible to write more generic code.
1 parent d5b3fc8 commit 5d6d67b

19 files changed

+278
-192
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
//! ### Example
2020
//!
2121
//! ```
22-
//! use average::MeanWithError;
22+
//! use average::{MeanWithError, Estimate};
2323
//!
2424
//! let mut a: MeanWithError = (1..6).map(Into::into).collect();
2525
//! a.add(42.);

src/macros.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ macro_rules! assert_almost_eq {
4040
/// # extern crate core;
4141
/// # #[macro_use] extern crate average;
4242
/// # fn main() {
43-
/// use average::{Min, Max};
43+
/// use average::{Min, Max, Estimate};
4444
///
4545
/// concatenate!(MinMax, [Min, min], [Max, max]);
4646
///
@@ -54,7 +54,7 @@ macro_rules! assert_almost_eq {
5454
/// The generated code looks roughly like this:
5555
///
5656
/// ```
57-
/// # use average::{Min, Max};
57+
/// # use average::{Min, Max, Estimate};
5858
/// #
5959
/// struct MinMax {
6060
/// min: Min,
@@ -88,7 +88,7 @@ macro_rules! assert_almost_eq {
8888
/// # extern crate core;
8989
/// # #[macro_use] extern crate average;
9090
/// # fn main() {
91-
/// use average::{Variance, Quantile};
91+
/// use average::{Variance, Quantile, Estimate};
9292
///
9393
/// concatenate!(Estimator,
9494
/// [Variance, variance, mean, sample_variance],

src/minmax.rs

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use core;
22

33
use super::reduce::Reduce;
4+
use super::{Estimate, Merge};
45

56
/// Calculate the minimum of `a` and `b`.
67
fn min(a: f64, b: f64) -> f64 {
@@ -43,25 +44,41 @@ impl Min {
4344
Min::from_value(::core::f64::INFINITY)
4445
}
4546

46-
/// Add an observation sampled from the population.
47+
/// Estimate the minium of the population.
4748
#[inline]
48-
pub fn add(&mut self, x: f64) {
49+
pub fn min(&self) -> f64 {
50+
self.r.reduction()
51+
}
52+
}
53+
54+
impl core::default::Default for Min {
55+
fn default() -> Min {
56+
Min::new()
57+
}
58+
}
59+
60+
impl_from_iterator!(Min);
61+
62+
impl Estimate for Min {
63+
#[inline]
64+
fn add(&mut self, x: f64) {
4965
self.r.add(x);
5066
}
5167

52-
/// Estimate the minium of the population.
5368
#[inline]
54-
pub fn min(&self) -> f64 {
55-
self.r.reduction()
69+
fn estimate(&self) -> f64 {
70+
self.min()
5671
}
72+
}
5773

74+
impl Merge for Min {
5875
/// Merge another sample into this one.
5976
///
6077
///
6178
/// ## Example
6279
///
6380
/// ```
64-
/// use average::Min;
81+
/// use average::{Min, Merge};
6582
///
6683
/// let sequence: &[f64] = &[1., 2., 3., 4., 5., 6., 7., 8., 9.];
6784
/// let (left, right) = sequence.split_at(3);
@@ -72,19 +89,11 @@ impl Min {
7289
/// assert_eq!(min_total.min(), min_left.min());
7390
/// ```
7491
#[inline]
75-
pub fn merge(&mut self, other: &Min) {
92+
fn merge(&mut self, other: &Min) {
7693
self.r.merge(&other.r);
7794
}
7895
}
7996

80-
impl core::default::Default for Min {
81-
fn default() -> Min {
82-
Min::new()
83-
}
84-
}
85-
86-
impl_from_iterator!(Min);
87-
8897
/// Estimate the maximum of a sequence of numbers ("population").
8998
///
9099
///
@@ -116,25 +125,41 @@ impl Max {
116125
Max::from_value(::core::f64::NEG_INFINITY)
117126
}
118127

119-
/// Add an observation sampled from the population.
128+
/// Estimate the maxium of the population.
120129
#[inline]
121-
pub fn add(&mut self, x: f64) {
130+
pub fn max(&self) -> f64 {
131+
self.r.reduction()
132+
}
133+
}
134+
135+
impl core::default::Default for Max {
136+
fn default() -> Max {
137+
Max::new()
138+
}
139+
}
140+
141+
impl_from_iterator!(Max);
142+
143+
impl Estimate for Max {
144+
#[inline]
145+
fn add(&mut self, x: f64) {
122146
self.r.add(x);
123147
}
124148

125-
/// Estimate the maxium of the population.
126149
#[inline]
127-
pub fn max(&self) -> f64 {
128-
self.r.reduction()
150+
fn estimate(&self) -> f64 {
151+
self.max()
129152
}
153+
}
130154

155+
impl Merge for Max {
131156
/// Merge another sample into this one.
132157
///
133158
///
134159
/// ## Example
135160
///
136161
/// ```
137-
/// use average::Max;
162+
/// use average::{Max, Merge};
138163
///
139164
/// let sequence: &[f64] = &[1., 2., 3., 4., 5., 6., 7., 8., 9.];
140165
/// let (left, right) = sequence.split_at(3);
@@ -145,15 +170,7 @@ impl Max {
145170
/// assert_eq!(max_total.max(), max_left.max());
146171
/// ```
147172
#[inline]
148-
pub fn merge(&mut self, other: &Max) {
173+
fn merge(&mut self, other: &Max) {
149174
self.r.merge(&other.r);
150175
}
151176
}
152-
153-
impl core::default::Default for Max {
154-
fn default() -> Max {
155-
Max::new()
156-
}
157-
}
158-
159-
impl_from_iterator!(Max);

src/moments/kurtosis.rs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,6 @@ impl Kurtosis {
2020
}
2121
}
2222

23-
/// Add an observation sampled from the population.
24-
#[inline]
25-
pub fn add(&mut self, x: f64) {
26-
let delta = x - self.mean();
27-
self.increment();
28-
let n = f64::approx_from(self.len()).unwrap();
29-
self.add_inner(delta, delta/n);
30-
}
31-
3223
/// Increment the sample size.
3324
///
3425
/// This does not update anything else.
@@ -114,9 +105,26 @@ impl Kurtosis {
114105
n * self.sum_4 / (self.avg.avg.sum_2 * self.avg.avg.sum_2) - 3.
115106
}
116107

117-
/// Merge another sample into this one.
108+
}
109+
110+
impl Estimate for Kurtosis {
111+
#[inline]
112+
fn add(&mut self, x: f64) {
113+
let delta = x - self.mean();
114+
self.increment();
115+
let n = f64::approx_from(self.len()).unwrap();
116+
self.add_inner(delta, delta/n);
117+
}
118+
119+
#[inline]
120+
fn estimate(&self) -> f64 {
121+
self.kurtosis()
122+
}
123+
}
124+
125+
impl Merge for Kurtosis {
118126
#[inline]
119-
pub fn merge(&mut self, other: &Kurtosis) {
127+
fn merge(&mut self, other: &Kurtosis) {
120128
let len_self = f64::approx_from(self.len()).unwrap();
121129
let len_other = f64::approx_from(other.len()).unwrap();
122130
let len_total = len_self + len_other;

src/moments/mean.rs

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
use core;
2-
3-
use conv::ApproxFrom;
4-
5-
61
/// Estimate the arithmetic mean of a sequence of numbers ("population").
72
///
83
///
@@ -29,15 +24,6 @@ impl Mean {
2924
Mean { avg: 0., n: 0 }
3025
}
3126

32-
/// Add an observation sampled from the population.
33-
#[inline]
34-
pub fn add(&mut self, sample: f64) {
35-
self.increment();
36-
let delta_n = (sample - self.avg)
37-
/ f64::approx_from(self.n).unwrap();
38-
self.add_inner(delta_n);
39-
}
40-
4127
/// Increment the sample size.
4228
///
4329
/// This does not update anything else.
@@ -80,13 +66,36 @@ impl Mean {
8066
self.n
8167
}
8268

69+
}
70+
71+
impl core::default::Default for Mean {
72+
fn default() -> Mean {
73+
Mean::new()
74+
}
75+
}
76+
77+
impl Estimate for Mean {
78+
#[inline]
79+
fn add(&mut self, sample: f64) {
80+
self.increment();
81+
let delta_n = (sample - self.avg)
82+
/ f64::approx_from(self.n).unwrap();
83+
self.add_inner(delta_n);
84+
}
85+
86+
fn estimate(&self) -> f64 {
87+
self.mean()
88+
}
89+
}
90+
91+
impl Merge for Mean {
8392
/// Merge another sample into this one.
8493
///
8594
///
8695
/// ## Example
8796
///
8897
/// ```
89-
/// use average::Mean;
98+
/// use average::{Mean, Merge};
9099
///
91100
/// let sequence: &[f64] = &[1., 2., 3., 4., 5., 6., 7., 8., 9.];
92101
/// let (left, right) = sequence.split_at(3);
@@ -97,7 +106,7 @@ impl Mean {
97106
/// assert_eq!(avg_total.mean(), avg_left.mean());
98107
/// ```
99108
#[inline]
100-
pub fn merge(&mut self, other: &Mean) {
109+
fn merge(&mut self, other: &Mean) {
101110
// This algorithm was proposed by Chan et al. in 1979.
102111
//
103112
// See https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance.
@@ -114,10 +123,4 @@ impl Mean {
114123
}
115124
}
116125

117-
impl core::default::Default for Mean {
118-
fn default() -> Mean {
119-
Mean::new()
120-
}
121-
}
122-
123126
impl_from_iterator!(Mean);

src/moments/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
use core;
2+
3+
use conv::ApproxFrom;
4+
5+
use super::{Estimate, Merge};
6+
17
include!("mean.rs");
28
include!("variance.rs");
39
include!("skewness.rs");

src/moments/skewness.rs

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,6 @@ impl Skewness {
2020
}
2121
}
2222

23-
/// Add an observation sampled from the population.
24-
#[inline]
25-
pub fn add(&mut self, x: f64) {
26-
let delta = x - self.mean();
27-
self.increment();
28-
let n = f64::approx_from(self.len()).unwrap();
29-
self.add_inner(delta, delta/n);
30-
}
31-
3223
/// Increment the sample size.
3324
///
3425
/// This does not update anything else.
@@ -107,10 +98,32 @@ impl Skewness {
10798
debug_assert_ne!(sum_2, 0.);
10899
n.sqrt() * self.sum_3 / (sum_2*sum_2*sum_2).sqrt()
109100
}
101+
}
102+
103+
impl Default for Skewness {
104+
fn default() -> Skewness {
105+
Skewness::new()
106+
}
107+
}
108+
109+
impl Estimate for Skewness {
110+
#[inline]
111+
fn add(&mut self, x: f64) {
112+
let delta = x - self.mean();
113+
self.increment();
114+
let n = f64::approx_from(self.len()).unwrap();
115+
self.add_inner(delta, delta/n);
116+
}
117+
118+
#[inline]
119+
fn estimate(&self) -> f64 {
120+
self.skewness()
121+
}
122+
}
110123

111-
/// Merge another sample into this one.
124+
impl Merge for Skewness {
112125
#[inline]
113-
pub fn merge(&mut self, other: &Skewness) {
126+
fn merge(&mut self, other: &Skewness) {
114127
let len_self = f64::approx_from(self.len()).unwrap();
115128
let len_other = f64::approx_from(other.len()).unwrap();
116129
let len_total = len_self + len_other;

0 commit comments

Comments
 (0)