impl FromIterator<&f64> and FromIterator<&(f64, f64)>

This allows to write

    let k: Kurtosis = a.iter().collect();

instead of

    let k: Kurtosis = a.iter().map(|x| *x).collect();

but breaks type inference for code like

    let m: Min = (1..6).map(Into::into).collect();

where

    let m: Min = (1..6).map(f64::from).collect();

has to be used instead.

Fixes #8.
This commit is contained in:
Vinzent Steinberg 2018-02-27 01:38:45 +01:00
parent 68a4fa64cb
commit e4345f5046
15 changed files with 86 additions and 50 deletions

View File

@ -29,7 +29,7 @@
//! ```
//! use average::{MeanWithError, Estimate};
//!
//! let mut a: MeanWithError = (1..6).map(Into::into).collect();
//! let mut a: MeanWithError = (1..6).map(f64::from).collect();
//! a.add(42.);
//! println!("The mean is {} ± {}.", a.mean(), a.error());
//! ```

View File

@ -44,7 +44,7 @@ macro_rules! assert_almost_eq {
///
/// concatenate!(MinMax, [Min, min], [Max, max]);
///
/// let s: MinMax = (1..6).map(Into::into).collect();
/// let s: MinMax = (1..6).map(f64::from).collect();
///
/// assert_eq!(s.min(), 1.0);
/// assert_eq!(s.max(), 5.0);
@ -157,5 +157,17 @@ macro_rules! impl_from_iterator {
e
}
}
impl<'a> ::core::iter::FromIterator<&'a f64> for $name {
fn from_iter<T>(iter: T) -> $name
where T: IntoIterator<Item=&'a f64>
{
let mut e = $name::new();
for &i in iter {
e.add(i);
}
e
}
}
};
}

View File

@ -20,7 +20,7 @@ fn max(a: f64, b: f64) -> f64 {
/// ```
/// use average::Min;
///
/// let a: Min = (1..6).map(Into::into).collect();
/// let a: Min = (1..6).map(f64::from).collect();
/// println!("The minimum is {}.", a.min());
/// ```
#[derive(Debug, Clone)]
@ -82,9 +82,9 @@ impl Merge for Min {
///
/// let sequence: &[f64] = &[1., 2., 3., 4., 5., 6., 7., 8., 9.];
/// let (left, right) = sequence.split_at(3);
/// let min_total: Min = sequence.iter().map(|x| *x).collect();
/// let mut min_left: Min = left.iter().map(|x| *x).collect();
/// let min_right: Min = right.iter().map(|x| *x).collect();
/// let min_total: Min = sequence.iter().collect();
/// let mut min_left: Min = left.iter().collect();
/// let min_right: Min = right.iter().collect();
/// min_left.merge(&min_right);
/// assert_eq!(min_total.min(), min_left.min());
/// ```
@ -102,7 +102,7 @@ impl Merge for Min {
/// ```
/// use average::Max;
///
/// let a: Max = (1..6).map(Into::into).collect();
/// let a: Max = (1..6).map(f64::from).collect();
/// assert_eq!(a.max(), 5.);
/// ```
#[derive(Debug, Clone)]
@ -164,9 +164,9 @@ impl Merge for Max {
///
/// let sequence: &[f64] = &[1., 2., 3., 4., 5., 6., 7., 8., 9.];
/// let (left, right) = sequence.split_at(3);
/// let max_total: Max = sequence.iter().map(|x| *x).collect();
/// let mut max_left: Max = left.iter().map(|x| *x).collect();
/// let max_right: Max = right.iter().map(|x| *x).collect();
/// let max_total: Max = sequence.iter().collect();
/// let mut max_left: Max = left.iter().collect();
/// let max_right: Max = right.iter().collect();
/// max_left.merge(&max_right);
/// assert_eq!(max_total.max(), max_left.max());
/// ```

View File

@ -6,7 +6,7 @@
/// ```
/// use average::Mean;
///
/// let a: Mean = (1..6).map(Into::into).collect();
/// let a: Mean = (1..6).map(f64::from).collect();
/// println!("The mean is {}.", a.mean());
/// ```
#[derive(Debug, Clone)]
@ -100,9 +100,9 @@ impl Merge for Mean {
///
/// let sequence: &[f64] = &[1., 2., 3., 4., 5., 6., 7., 8., 9.];
/// let (left, right) = sequence.split_at(3);
/// let avg_total: Mean = sequence.iter().map(|x| *x).collect();
/// let mut avg_left: Mean = left.iter().map(|x| *x).collect();
/// let avg_right: Mean = right.iter().map(|x| *x).collect();
/// let avg_total: Mean = sequence.iter().collect();
/// let mut avg_left: Mean = left.iter().collect();
/// let avg_right: Mean = right.iter().collect();
/// avg_left.merge(&avg_right);
/// assert_eq!(avg_total.mean(), avg_left.mean());
/// ```

View File

@ -9,7 +9,7 @@
/// ```
/// use average::Variance;
///
/// let a: Variance = (1..6).map(Into::into).collect();
/// let a: Variance = (1..6).map(f64::from).collect();
/// println!("The mean is {} ± {}.", a.mean(), a.error());
/// ```
#[derive(Debug, Clone)]
@ -139,9 +139,9 @@ impl Merge for Variance {
///
/// let sequence: &[f64] = &[1., 2., 3., 4., 5., 6., 7., 8., 9.];
/// let (left, right) = sequence.split_at(3);
/// let avg_total: Variance = sequence.iter().map(|x| *x).collect();
/// let mut avg_left: Variance = left.iter().map(|x| *x).collect();
/// let avg_right: Variance = right.iter().map(|x| *x).collect();
/// let avg_total: Variance = sequence.iter().collect();
/// let mut avg_left: Variance = left.iter().collect();
/// let avg_right: Variance = right.iter().collect();
/// avg_left.merge(&avg_right);
/// assert_eq!(avg_total.mean(), avg_left.mean());
/// assert_eq!(avg_total.sample_variance(), avg_left.sample_variance());

View File

@ -91,6 +91,18 @@ impl core::iter::FromIterator<(f64, f64)> for WeightedMean {
}
}
impl<'a> core::iter::FromIterator<&'a (f64, f64)> for WeightedMean {
fn from_iter<T>(iter: T) -> WeightedMean
where T: IntoIterator<Item=&'a (f64, f64)>
{
let mut a = WeightedMean::new();
for &(i, w) in iter {
a.add(i, w);
}
a
}
}
impl Merge for WeightedMean {
/// Merge another sample into this one.
///
@ -104,9 +116,9 @@ impl Merge for WeightedMean {
/// (1., 0.1), (2., 0.2), (3., 0.3), (4., 0.4), (5., 0.5),
/// (6., 0.6), (7., 0.7), (8., 0.8), (9., 0.9)];
/// let (left, right) = weighted_sequence.split_at(3);
/// let avg_total: WeightedMean = weighted_sequence.iter().map(|&x| x).collect();
/// let mut avg_left: WeightedMean = left.iter().map(|&x| x).collect();
/// let avg_right: WeightedMean = right.iter().map(|&x| x).collect();
/// let avg_total: WeightedMean = weighted_sequence.iter().collect();
/// let mut avg_left: WeightedMean = left.iter().collect();
/// let avg_right: WeightedMean = right.iter().collect();
/// avg_left.merge(&avg_right);
/// assert!((avg_total.mean() - avg_left.mean()).abs() < 1e-15);
/// ```
@ -276,9 +288,9 @@ impl Merge for WeightedMeanWithError {
/// (1., 0.1), (2., 0.2), (3., 0.3), (4., 0.4), (5., 0.5),
/// (6., 0.6), (7., 0.7), (8., 0.8), (9., 0.9)];
/// let (left, right) = weighted_sequence.split_at(3);
/// let avg_total: WeightedMeanWithError = weighted_sequence.iter().map(|&x| x).collect();
/// let mut avg_left: WeightedMeanWithError = left.iter().map(|&x| x).collect();
/// let avg_right: WeightedMeanWithError = right.iter().map(|&x| x).collect();
/// let avg_total: WeightedMeanWithError = weighted_sequence.iter().collect();
/// let mut avg_left: WeightedMeanWithError = left.iter().collect();
/// let avg_right: WeightedMeanWithError = right.iter().collect();
/// avg_left.merge(&avg_right);
/// assert!((avg_total.weighted_mean() - avg_left.weighted_mean()).abs() < 1e-15);
/// assert!((avg_total.error() - avg_left.error()).abs() < 1e-15);
@ -308,3 +320,15 @@ impl core::iter::FromIterator<(f64, f64)> for WeightedMeanWithError {
a
}
}
impl<'a> core::iter::FromIterator<&'a (f64, f64)> for WeightedMeanWithError {
fn from_iter<T>(iter: T) -> WeightedMeanWithError
where T: IntoIterator<Item=&'a (f64, f64)>
{
let mut a = WeightedMeanWithError::new();
for &(i, w) in iter {
a.add(i, w);
}
a
}
}

View File

@ -65,9 +65,9 @@ fn merge() {
let sequence: &[f64] = &[1., 2., 3., -4., 5.1, 6.3, 7.3, -8., 9., 1.];
for mid in 0..sequence.len() {
let (left, right) = sequence.split_at(mid);
let avg_total: Kurtosis = sequence.iter().map(|x| *x).collect();
let mut avg_left: Kurtosis = left.iter().map(|x| *x).collect();
let avg_right: Kurtosis = right.iter().map(|x| *x).collect();
let avg_total: Kurtosis = sequence.iter().collect();
let mut avg_left: Kurtosis = left.iter().collect();
let avg_right: Kurtosis = right.iter().collect();
avg_left.merge(&avg_right);
assert_eq!(avg_total.len(), avg_left.len());
assert_almost_eq!(avg_total.mean(), avg_left.mean(), 1e-14);

View File

@ -33,7 +33,7 @@ fn concatenate_simple() {
}
{
let s: MinMax = (1..6).map(Into::into).collect();
let s: MinMax = (1..6).map(f64::from).collect();
assert_eq!(s.min(), 1.0);
assert_eq!(s.max(), 5.0);
@ -48,7 +48,7 @@ fn concatenate_moments() {
[Variance, variance, mean, sample_variance],
[Quantile, quantile, quantile]);
let e: Estimator = (1..6).map(Into::into).collect();
let e: Estimator = (1..6).map(f64::from).collect();
assert_eq!(e.mean(), 3.0);
assert_eq!(e.sample_variance(), 2.5);

View File

@ -40,11 +40,11 @@ fn merge() {
let sequence: &[f64] = &[1., 2., 3., 4., 5., 6., 7., 8., 9.];
for mid in 1..sequence.len() {
let (left, right) = sequence.split_at(mid);
let max_total: Max = sequence.iter().map(|x| *x).collect();
let max_total: Max = sequence.iter().collect();
assert_eq!(max_total.max(), 9.);
let mut max_left: Max = left.iter().map(|x| *x).collect();
let mut max_left: Max = left.iter().collect();
assert_eq!(max_left.max(), sequence[mid - 1]);
let max_right: Max = right.iter().map(|x| *x).collect();
let max_right: Max = right.iter().collect();
assert_eq!(max_right.max(), 9.);
max_left.merge(&max_right);
assert_eq!(max_total.max(), max_left.max());

View File

@ -55,7 +55,7 @@ fn numerically_unstable() {
// The naive algorithm fails for this example due to cancelation.
let big = 1e9;
let sample = &[big + 4., big + 7., big + 13., big + 16.];
let a: MeanWithError = sample.iter().map(|x| *x).collect();
let a: MeanWithError = sample.iter().collect();
assert_eq!(a.sample_variance(), 30.);
}
@ -64,9 +64,9 @@ fn merge() {
let sequence: &[f64] = &[1., 2., 3., 4., 5., 6., 7., 8., 9.];
for mid in 0..sequence.len() {
let (left, right) = sequence.split_at(mid);
let avg_total: MeanWithError = sequence.iter().map(|x| *x).collect();
let mut avg_left: MeanWithError = left.iter().map(|x| *x).collect();
let avg_right: MeanWithError = right.iter().map(|x| *x).collect();
let avg_total: MeanWithError = sequence.iter().collect();
let mut avg_left: MeanWithError = left.iter().collect();
let avg_right: MeanWithError = right.iter().collect();
avg_left.merge(&avg_right);
assert_eq!(avg_total.len(), avg_left.len());
assert_eq!(avg_total.mean(), avg_left.mean());

View File

@ -40,11 +40,11 @@ fn merge() {
let sequence: &[f64] = &[1., 2., 3., 4., 5., 6., 7., 8., 9.];
for mid in 1..sequence.len() {
let (left, right) = sequence.split_at(mid);
let min_total: Min = sequence.iter().map(|x| *x).collect();
let min_total: Min = sequence.iter().collect();
assert_eq!(min_total.min(), 1.);
let mut min_left: Min = left.iter().map(|x| *x).collect();
let mut min_left: Min = left.iter().collect();
assert_eq!(min_left.min(), 1.);
let min_right: Min = right.iter().map(|x| *x).collect();
let min_right: Min = right.iter().collect();
assert_eq!(min_right.min(), sequence[mid]);
min_left.merge(&min_right);
assert_eq!(min_total.min(), min_left.min());

View File

@ -81,9 +81,9 @@ fn merge() {
let sequence: &[f64] = &[1., 2., 3., -4., 5.1, 6.3, 7.3, -8., 9., 1.];
for mid in 0..sequence.len() {
let (left, right) = sequence.split_at(mid);
let avg_total: Moments = sequence.iter().map(|x| *x).collect();
let mut avg_left: Moments = left.iter().map(|x| *x).collect();
let avg_right: Moments = right.iter().map(|x| *x).collect();
let avg_total: Moments = sequence.iter().collect();
let mut avg_left: Moments = left.iter().collect();
let avg_right: Moments = right.iter().collect();
avg_left.merge(&avg_right);
assert_eq!(avg_total.len(), avg_left.len());
assert_almost_eq!(avg_total.mean(), avg_left.mean(), 1e-14);

View File

@ -63,9 +63,9 @@ fn merge() {
let sequence: &[f64] = &[1., 2., 3., -4., 5., 6., 7., 8., 9., 1.];
for mid in 0..sequence.len() {
let (left, right) = sequence.split_at(mid);
let avg_total: Skewness = sequence.iter().map(|x| *x).collect();
let mut avg_left: Skewness = left.iter().map(|x| *x).collect();
let avg_right: Skewness = right.iter().map(|x| *x).collect();
let avg_total: Skewness = sequence.iter().collect();
let mut avg_left: Skewness = left.iter().collect();
let avg_right: Skewness = right.iter().collect();
avg_left.merge(&avg_right);
assert_eq!(avg_total.len(), avg_left.len());
assert_almost_eq!(avg_total.mean(), avg_left.mean(), 1e-14);

View File

@ -21,7 +21,7 @@ fn initialize_vec(size: usize) -> Vec<f64> {
#[test]
fn average_vs_streaming_stats_small() {
let values = initialize_vec(100);
let a: average::MeanWithError = values.iter().map(|x| *x).collect();
let a: average::MeanWithError = values.iter().collect();
let b: stats::OnlineStats = values.iter().map(|x| *x).collect();
assert_almost_eq!(a.mean(), b.mean(), 1e-16);
assert_almost_eq!(a.population_variance(), b.variance(), 1e-14);
@ -30,7 +30,7 @@ fn average_vs_streaming_stats_small() {
#[test]
fn average_vs_streaming_stats_large() {
let values = initialize_vec(1_000_000);
let a: average::MeanWithError = values.iter().map(|x| *x).collect();
let a: average::MeanWithError = values.iter().collect();
let b: stats::OnlineStats = values.iter().map(|x| *x).collect();
assert_almost_eq!(a.mean(), b.mean(), 1e-16);
assert_almost_eq!(a.population_variance(), b.variance(), 1e-13);

View File

@ -111,9 +111,9 @@ fn merge_weighted() {
(6., 0.6), (7., 0.7), (8., 0.8), (9., 0.)];
for mid in 0..sequence.len() {
let (left, right) = sequence.split_at(mid);
let avg_total: WeightedMeanWithError = sequence.iter().map(|&(x, w)| (x, w)).collect();
let mut avg_left: WeightedMeanWithError = left.iter().map(|&(x, w)| (x, w)).collect();
let avg_right: WeightedMeanWithError = right.iter().map(|&(x, w)| (x, w)).collect();
let avg_total: WeightedMeanWithError = sequence.iter().collect();
let mut avg_left: WeightedMeanWithError = left.iter().collect();
let avg_right: WeightedMeanWithError = right.iter().collect();
avg_left.merge(&avg_right);
assert_eq!(avg_total.len(), avg_left.len());
assert_almost_eq!(avg_total.sum_weights(), avg_left.sum_weights(), 1e-15);