]> git.lizzy.rs Git - rust.git/blob - src/libtest/stats.rs
Rollup merge of #31295 - steveklabnik:gh31266, r=alexcrichton
[rust.git] / src / libtest / stats.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 #![allow(missing_docs)]
12 #![allow(deprecated)] // Float
13
14 use std::cmp::Ordering::{self, Less, Greater, Equal};
15 use std::mem;
16
17 fn local_cmp(x: f64, y: f64) -> Ordering {
18     // arbitrarily decide that NaNs are larger than everything.
19     if y.is_nan() {
20         Less
21     } else if x.is_nan() {
22         Greater
23     } else if x < y {
24         Less
25     } else if x == y {
26         Equal
27     } else {
28         Greater
29     }
30 }
31
32 fn local_sort(v: &mut [f64]) {
33     v.sort_by(|x: &f64, y: &f64| local_cmp(*x, *y));
34 }
35
36 /// Trait that provides simple descriptive statistics on a univariate set of numeric samples.
37 pub trait Stats {
38
39     /// Sum of the samples.
40     ///
41     /// Note: this method sacrifices performance at the altar of accuracy
42     /// Depends on IEEE-754 arithmetic guarantees. See proof of correctness at:
43     /// ["Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates"]
44     /// (http://www.cs.cmu.edu/~quake-papers/robust-arithmetic.ps)
45     fn sum(&self) -> f64;
46
47     /// Minimum value of the samples.
48     fn min(&self) -> f64;
49
50     /// Maximum value of the samples.
51     fn max(&self) -> f64;
52
53     /// Arithmetic mean (average) of the samples: sum divided by sample-count.
54     ///
55     /// See: https://en.wikipedia.org/wiki/Arithmetic_mean
56     fn mean(&self) -> f64;
57
58     /// Median of the samples: value separating the lower half of the samples from the higher half.
59     /// Equal to `self.percentile(50.0)`.
60     ///
61     /// See: https://en.wikipedia.org/wiki/Median
62     fn median(&self) -> f64;
63
64     /// Variance of the samples: bias-corrected mean of the squares of the differences of each
65     /// sample from the sample mean. Note that this calculates the _sample variance_ rather than the
66     /// population variance, which is assumed to be unknown. It therefore corrects the `(n-1)/n`
67     /// bias that would appear if we calculated a population variance, by dividing by `(n-1)` rather
68     /// than `n`.
69     ///
70     /// See: https://en.wikipedia.org/wiki/Variance
71     fn var(&self) -> f64;
72
73     /// Standard deviation: the square root of the sample variance.
74     ///
75     /// Note: this is not a robust statistic for non-normal distributions. Prefer the
76     /// `median_abs_dev` for unknown distributions.
77     ///
78     /// See: https://en.wikipedia.org/wiki/Standard_deviation
79     fn std_dev(&self) -> f64;
80
81     /// Standard deviation as a percent of the mean value. See `std_dev` and `mean`.
82     ///
83     /// Note: this is not a robust statistic for non-normal distributions. Prefer the
84     /// `median_abs_dev_pct` for unknown distributions.
85     fn std_dev_pct(&self) -> f64;
86
87     /// Scaled median of the absolute deviations of each sample from the sample median. This is a
88     /// robust (distribution-agnostic) estimator of sample variability. Use this in preference to
89     /// `std_dev` if you cannot assume your sample is normally distributed. Note that this is scaled
90     /// by the constant `1.4826` to allow its use as a consistent estimator for the standard
91     /// deviation.
92     ///
93     /// See: http://en.wikipedia.org/wiki/Median_absolute_deviation
94     fn median_abs_dev(&self) -> f64;
95
96     /// Median absolute deviation as a percent of the median. See `median_abs_dev` and `median`.
97     fn median_abs_dev_pct(&self) -> f64;
98
99     /// Percentile: the value below which `pct` percent of the values in `self` fall. For example,
100     /// percentile(95.0) will return the value `v` such that 95% of the samples `s` in `self`
101     /// satisfy `s <= v`.
102     ///
103     /// Calculated by linear interpolation between closest ranks.
104     ///
105     /// See: http://en.wikipedia.org/wiki/Percentile
106     fn percentile(&self, pct: f64) -> f64;
107
108     /// Quartiles of the sample: three values that divide the sample into four equal groups, each
109     /// with 1/4 of the data. The middle value is the median. See `median` and `percentile`. This
110     /// function may calculate the 3 quartiles more efficiently than 3 calls to `percentile`, but
111     /// is otherwise equivalent.
112     ///
113     /// See also: https://en.wikipedia.org/wiki/Quartile
114     fn quartiles(&self) -> (f64, f64, f64);
115
116     /// Inter-quartile range: the difference between the 25th percentile (1st quartile) and the 75th
117     /// percentile (3rd quartile). See `quartiles`.
118     ///
119     /// See also: https://en.wikipedia.org/wiki/Interquartile_range
120     fn iqr(&self) -> f64;
121 }
122
123 /// Extracted collection of all the summary statistics of a sample set.
124 #[derive(Clone, PartialEq)]
125 #[allow(missing_docs)]
126 pub struct Summary {
127     pub sum: f64,
128     pub min: f64,
129     pub max: f64,
130     pub mean: f64,
131     pub median: f64,
132     pub var: f64,
133     pub std_dev: f64,
134     pub std_dev_pct: f64,
135     pub median_abs_dev: f64,
136     pub median_abs_dev_pct: f64,
137     pub quartiles: (f64, f64, f64),
138     pub iqr: f64,
139 }
140
141 impl Summary {
142     /// Construct a new summary of a sample set.
143     pub fn new(samples: &[f64]) -> Summary {
144         Summary {
145             sum: samples.sum(),
146             min: samples.min(),
147             max: samples.max(),
148             mean: samples.mean(),
149             median: samples.median(),
150             var: samples.var(),
151             std_dev: samples.std_dev(),
152             std_dev_pct: samples.std_dev_pct(),
153             median_abs_dev: samples.median_abs_dev(),
154             median_abs_dev_pct: samples.median_abs_dev_pct(),
155             quartiles: samples.quartiles(),
156             iqr: samples.iqr(),
157         }
158     }
159 }
160
161 impl Stats for [f64] {
162     // FIXME #11059 handle NaN, inf and overflow
163     fn sum(&self) -> f64 {
164         let mut partials = vec![];
165
166         for &x in self {
167             let mut x = x;
168             let mut j = 0;
169             // This inner loop applies `hi`/`lo` summation to each
170             // partial so that the list of partial sums remains exact.
171             for i in 0..partials.len() {
172                 let mut y: f64 = partials[i];
173                 if x.abs() < y.abs() {
174                     mem::swap(&mut x, &mut y);
175                 }
176                 // Rounded `x+y` is stored in `hi` with round-off stored in
177                 // `lo`. Together `hi+lo` are exactly equal to `x+y`.
178                 let hi = x + y;
179                 let lo = y - (hi - x);
180                 if lo != 0.0 {
181                     partials[j] = lo;
182                     j += 1;
183                 }
184                 x = hi;
185             }
186             if j >= partials.len() {
187                 partials.push(x);
188             } else {
189                 partials[j] = x;
190                 partials.truncate(j + 1);
191             }
192         }
193         let zero: f64 = 0.0;
194         partials.iter().fold(zero, |p, q| p + *q)
195     }
196
197     fn min(&self) -> f64 {
198         assert!(!self.is_empty());
199         self.iter().fold(self[0], |p, q| p.min(*q))
200     }
201
202     fn max(&self) -> f64 {
203         assert!(!self.is_empty());
204         self.iter().fold(self[0], |p, q| p.max(*q))
205     }
206
207     fn mean(&self) -> f64 {
208         assert!(!self.is_empty());
209         self.sum() / (self.len() as f64)
210     }
211
212     fn median(&self) -> f64 {
213         self.percentile(50 as f64)
214     }
215
216     fn var(&self) -> f64 {
217         if self.len() < 2 {
218             0.0
219         } else {
220             let mean = self.mean();
221             let mut v: f64 = 0.0;
222             for s in self {
223                 let x = *s - mean;
224                 v = v + x * x;
225             }
226             // NB: this is _supposed to be_ len-1, not len. If you
227             // change it back to len, you will be calculating a
228             // population variance, not a sample variance.
229             let denom = (self.len() - 1) as f64;
230             v / denom
231         }
232     }
233
234     fn std_dev(&self) -> f64 {
235         self.var().sqrt()
236     }
237
238     fn std_dev_pct(&self) -> f64 {
239         let hundred = 100 as f64;
240         (self.std_dev() / self.mean()) * hundred
241     }
242
243     fn median_abs_dev(&self) -> f64 {
244         let med = self.median();
245         let abs_devs: Vec<f64> = self.iter().map(|&v| (med - v).abs()).collect();
246         // This constant is derived by smarter statistics brains than me, but it is
247         // consistent with how R and other packages treat the MAD.
248         let number = 1.4826;
249         abs_devs.median() * number
250     }
251
252     fn median_abs_dev_pct(&self) -> f64 {
253         let hundred = 100 as f64;
254         (self.median_abs_dev() / self.median()) * hundred
255     }
256
257     fn percentile(&self, pct: f64) -> f64 {
258         let mut tmp = self.to_vec();
259         local_sort(&mut tmp);
260         percentile_of_sorted(&tmp, pct)
261     }
262
263     fn quartiles(&self) -> (f64, f64, f64) {
264         let mut tmp = self.to_vec();
265         local_sort(&mut tmp);
266         let first = 25f64;
267         let a = percentile_of_sorted(&tmp, first);
268         let secound = 50f64;
269         let b = percentile_of_sorted(&tmp, secound);
270         let third = 75f64;
271         let c = percentile_of_sorted(&tmp, third);
272         (a, b, c)
273     }
274
275     fn iqr(&self) -> f64 {
276         let (a, _, c) = self.quartiles();
277         c - a
278     }
279 }
280
281
282 // Helper function: extract a value representing the `pct` percentile of a sorted sample-set, using
283 // linear interpolation. If samples are not sorted, return nonsensical value.
284 fn percentile_of_sorted(sorted_samples: &[f64], pct: f64) -> f64 {
285     assert!(!sorted_samples.is_empty());
286     if sorted_samples.len() == 1 {
287         return sorted_samples[0];
288     }
289     let zero: f64 = 0.0;
290     assert!(zero <= pct);
291     let hundred = 100f64;
292     assert!(pct <= hundred);
293     if pct == hundred {
294         return sorted_samples[sorted_samples.len() - 1];
295     }
296     let length = (sorted_samples.len() - 1) as f64;
297     let rank = (pct / hundred) * length;
298     let lrank = rank.floor();
299     let d = rank - lrank;
300     let n = lrank as usize;
301     let lo = sorted_samples[n];
302     let hi = sorted_samples[n + 1];
303     lo + (hi - lo) * d
304 }
305
306
307 /// Winsorize a set of samples, replacing values above the `100-pct` percentile
308 /// and below the `pct` percentile with those percentiles themselves. This is a
309 /// way of minimizing the effect of outliers, at the cost of biasing the sample.
310 /// It differs from trimming in that it does not change the number of samples,
311 /// just changes the values of those that are outliers.
312 ///
313 /// See: http://en.wikipedia.org/wiki/Winsorising
314 pub fn winsorize(samples: &mut [f64], pct: f64) {
315     let mut tmp = samples.to_vec();
316     local_sort(&mut tmp);
317     let lo = percentile_of_sorted(&tmp, pct);
318     let hundred = 100 as f64;
319     let hi = percentile_of_sorted(&tmp, hundred - pct);
320     for samp in samples {
321         if *samp > hi {
322             *samp = hi
323         } else if *samp < lo {
324             *samp = lo
325         }
326     }
327 }
328
329 // Test vectors generated from R, using the script src/etc/stat-test-vectors.r.
330
331 #[cfg(test)]
332 mod tests {
333     use stats::Stats;
334     use stats::Summary;
335     use std::f64;
336     use std::io::prelude::*;
337     use std::io;
338
339     macro_rules! assert_approx_eq {
340         ($a:expr, $b:expr) => ({
341             let (a, b) = (&$a, &$b);
342             assert!((*a - *b).abs() < 1.0e-6,
343                     "{} is not approximately equal to {}", *a, *b);
344         })
345     }
346
347     fn check(samples: &[f64], summ: &Summary) {
348
349         let summ2 = Summary::new(samples);
350
351         let mut w = io::sink();
352         let w = &mut w;
353         (write!(w, "\n")).unwrap();
354
355         assert_eq!(summ.sum, summ2.sum);
356         assert_eq!(summ.min, summ2.min);
357         assert_eq!(summ.max, summ2.max);
358         assert_eq!(summ.mean, summ2.mean);
359         assert_eq!(summ.median, summ2.median);
360
361         // We needed a few more digits to get exact equality on these
362         // but they're within float epsilon, which is 1.0e-6.
363         assert_approx_eq!(summ.var, summ2.var);
364         assert_approx_eq!(summ.std_dev, summ2.std_dev);
365         assert_approx_eq!(summ.std_dev_pct, summ2.std_dev_pct);
366         assert_approx_eq!(summ.median_abs_dev, summ2.median_abs_dev);
367         assert_approx_eq!(summ.median_abs_dev_pct, summ2.median_abs_dev_pct);
368
369         assert_eq!(summ.quartiles, summ2.quartiles);
370         assert_eq!(summ.iqr, summ2.iqr);
371     }
372
373     #[test]
374     fn test_min_max_nan() {
375         let xs = &[1.0, 2.0, f64::NAN, 3.0, 4.0];
376         let summary = Summary::new(xs);
377         assert_eq!(summary.min, 1.0);
378         assert_eq!(summary.max, 4.0);
379     }
380
381     #[test]
382     fn test_norm2() {
383         let val = &[958.0000000000, 924.0000000000];
384         let summ = &Summary {
385             sum: 1882.0000000000,
386             min: 924.0000000000,
387             max: 958.0000000000,
388             mean: 941.0000000000,
389             median: 941.0000000000,
390             var: 578.0000000000,
391             std_dev: 24.0416305603,
392             std_dev_pct: 2.5549022912,
393             median_abs_dev: 25.2042000000,
394             median_abs_dev_pct: 2.6784484591,
395             quartiles: (932.5000000000, 941.0000000000, 949.5000000000),
396             iqr: 17.0000000000,
397         };
398         check(val, summ);
399     }
400     #[test]
401     fn test_norm10narrow() {
402         let val = &[966.0000000000,
403                     985.0000000000,
404                     1110.0000000000,
405                     848.0000000000,
406                     821.0000000000,
407                     975.0000000000,
408                     962.0000000000,
409                     1157.0000000000,
410                     1217.0000000000,
411                     955.0000000000];
412         let summ = &Summary {
413             sum: 9996.0000000000,
414             min: 821.0000000000,
415             max: 1217.0000000000,
416             mean: 999.6000000000,
417             median: 970.5000000000,
418             var: 16050.7111111111,
419             std_dev: 126.6914010938,
420             std_dev_pct: 12.6742097933,
421             median_abs_dev: 102.2994000000,
422             median_abs_dev_pct: 10.5408964451,
423             quartiles: (956.7500000000, 970.5000000000, 1078.7500000000),
424             iqr: 122.0000000000,
425         };
426         check(val, summ);
427     }
428     #[test]
429     fn test_norm10medium() {
430         let val = &[954.0000000000,
431                     1064.0000000000,
432                     855.0000000000,
433                     1000.0000000000,
434                     743.0000000000,
435                     1084.0000000000,
436                     704.0000000000,
437                     1023.0000000000,
438                     357.0000000000,
439                     869.0000000000];
440         let summ = &Summary {
441             sum: 8653.0000000000,
442             min: 357.0000000000,
443             max: 1084.0000000000,
444             mean: 865.3000000000,
445             median: 911.5000000000,
446             var: 48628.4555555556,
447             std_dev: 220.5186059170,
448             std_dev_pct: 25.4846418487,
449             median_abs_dev: 195.7032000000,
450             median_abs_dev_pct: 21.4704552935,
451             quartiles: (771.0000000000, 911.5000000000, 1017.2500000000),
452             iqr: 246.2500000000,
453         };
454         check(val, summ);
455     }
456     #[test]
457     fn test_norm10wide() {
458         let val = &[505.0000000000,
459                     497.0000000000,
460                     1591.0000000000,
461                     887.0000000000,
462                     1026.0000000000,
463                     136.0000000000,
464                     1580.0000000000,
465                     940.0000000000,
466                     754.0000000000,
467                     1433.0000000000];
468         let summ = &Summary {
469             sum: 9349.0000000000,
470             min: 136.0000000000,
471             max: 1591.0000000000,
472             mean: 934.9000000000,
473             median: 913.5000000000,
474             var: 239208.9888888889,
475             std_dev: 489.0899599142,
476             std_dev_pct: 52.3146817750,
477             median_abs_dev: 611.5725000000,
478             median_abs_dev_pct: 66.9482758621,
479             quartiles: (567.2500000000, 913.5000000000, 1331.2500000000),
480             iqr: 764.0000000000,
481         };
482         check(val, summ);
483     }
484     #[test]
485     fn test_norm25verynarrow() {
486         let val = &[991.0000000000,
487                     1018.0000000000,
488                     998.0000000000,
489                     1013.0000000000,
490                     974.0000000000,
491                     1007.0000000000,
492                     1014.0000000000,
493                     999.0000000000,
494                     1011.0000000000,
495                     978.0000000000,
496                     985.0000000000,
497                     999.0000000000,
498                     983.0000000000,
499                     982.0000000000,
500                     1015.0000000000,
501                     1002.0000000000,
502                     977.0000000000,
503                     948.0000000000,
504                     1040.0000000000,
505                     974.0000000000,
506                     996.0000000000,
507                     989.0000000000,
508                     1015.0000000000,
509                     994.0000000000,
510                     1024.0000000000];
511         let summ = &Summary {
512             sum: 24926.0000000000,
513             min: 948.0000000000,
514             max: 1040.0000000000,
515             mean: 997.0400000000,
516             median: 998.0000000000,
517             var: 393.2066666667,
518             std_dev: 19.8294393937,
519             std_dev_pct: 1.9888308788,
520             median_abs_dev: 22.2390000000,
521             median_abs_dev_pct: 2.2283567134,
522             quartiles: (983.0000000000, 998.0000000000, 1013.0000000000),
523             iqr: 30.0000000000,
524         };
525         check(val, summ);
526     }
527     #[test]
528     fn test_exp10a() {
529         let val = &[23.0000000000,
530                     11.0000000000,
531                     2.0000000000,
532                     57.0000000000,
533                     4.0000000000,
534                     12.0000000000,
535                     5.0000000000,
536                     29.0000000000,
537                     3.0000000000,
538                     21.0000000000];
539         let summ = &Summary {
540             sum: 167.0000000000,
541             min: 2.0000000000,
542             max: 57.0000000000,
543             mean: 16.7000000000,
544             median: 11.5000000000,
545             var: 287.7888888889,
546             std_dev: 16.9643416875,
547             std_dev_pct: 101.5828843560,
548             median_abs_dev: 13.3434000000,
549             median_abs_dev_pct: 116.0295652174,
550             quartiles: (4.2500000000, 11.5000000000, 22.5000000000),
551             iqr: 18.2500000000,
552         };
553         check(val, summ);
554     }
555     #[test]
556     fn test_exp10b() {
557         let val = &[24.0000000000,
558                     17.0000000000,
559                     6.0000000000,
560                     38.0000000000,
561                     25.0000000000,
562                     7.0000000000,
563                     51.0000000000,
564                     2.0000000000,
565                     61.0000000000,
566                     32.0000000000];
567         let summ = &Summary {
568             sum: 263.0000000000,
569             min: 2.0000000000,
570             max: 61.0000000000,
571             mean: 26.3000000000,
572             median: 24.5000000000,
573             var: 383.5666666667,
574             std_dev: 19.5848580967,
575             std_dev_pct: 74.4671410520,
576             median_abs_dev: 22.9803000000,
577             median_abs_dev_pct: 93.7971428571,
578             quartiles: (9.5000000000, 24.5000000000, 36.5000000000),
579             iqr: 27.0000000000,
580         };
581         check(val, summ);
582     }
583     #[test]
584     fn test_exp10c() {
585         let val = &[71.0000000000,
586                     2.0000000000,
587                     32.0000000000,
588                     1.0000000000,
589                     6.0000000000,
590                     28.0000000000,
591                     13.0000000000,
592                     37.0000000000,
593                     16.0000000000,
594                     36.0000000000];
595         let summ = &Summary {
596             sum: 242.0000000000,
597             min: 1.0000000000,
598             max: 71.0000000000,
599             mean: 24.2000000000,
600             median: 22.0000000000,
601             var: 458.1777777778,
602             std_dev: 21.4050876611,
603             std_dev_pct: 88.4507754589,
604             median_abs_dev: 21.4977000000,
605             median_abs_dev_pct: 97.7168181818,
606             quartiles: (7.7500000000, 22.0000000000, 35.0000000000),
607             iqr: 27.2500000000,
608         };
609         check(val, summ);
610     }
611     #[test]
612     fn test_exp25() {
613         let val = &[3.0000000000,
614                     24.0000000000,
615                     1.0000000000,
616                     19.0000000000,
617                     7.0000000000,
618                     5.0000000000,
619                     30.0000000000,
620                     39.0000000000,
621                     31.0000000000,
622                     13.0000000000,
623                     25.0000000000,
624                     48.0000000000,
625                     1.0000000000,
626                     6.0000000000,
627                     42.0000000000,
628                     63.0000000000,
629                     2.0000000000,
630                     12.0000000000,
631                     108.0000000000,
632                     26.0000000000,
633                     1.0000000000,
634                     7.0000000000,
635                     44.0000000000,
636                     25.0000000000,
637                     11.0000000000];
638         let summ = &Summary {
639             sum: 593.0000000000,
640             min: 1.0000000000,
641             max: 108.0000000000,
642             mean: 23.7200000000,
643             median: 19.0000000000,
644             var: 601.0433333333,
645             std_dev: 24.5161851301,
646             std_dev_pct: 103.3565983562,
647             median_abs_dev: 19.2738000000,
648             median_abs_dev_pct: 101.4410526316,
649             quartiles: (6.0000000000, 19.0000000000, 31.0000000000),
650             iqr: 25.0000000000,
651         };
652         check(val, summ);
653     }
654     #[test]
655     fn test_binom25() {
656         let val = &[18.0000000000,
657                     17.0000000000,
658                     27.0000000000,
659                     15.0000000000,
660                     21.0000000000,
661                     25.0000000000,
662                     17.0000000000,
663                     24.0000000000,
664                     25.0000000000,
665                     24.0000000000,
666                     26.0000000000,
667                     26.0000000000,
668                     23.0000000000,
669                     15.0000000000,
670                     23.0000000000,
671                     17.0000000000,
672                     18.0000000000,
673                     18.0000000000,
674                     21.0000000000,
675                     16.0000000000,
676                     15.0000000000,
677                     31.0000000000,
678                     20.0000000000,
679                     17.0000000000,
680                     15.0000000000];
681         let summ = &Summary {
682             sum: 514.0000000000,
683             min: 15.0000000000,
684             max: 31.0000000000,
685             mean: 20.5600000000,
686             median: 20.0000000000,
687             var: 20.8400000000,
688             std_dev: 4.5650848842,
689             std_dev_pct: 22.2037202539,
690             median_abs_dev: 5.9304000000,
691             median_abs_dev_pct: 29.6520000000,
692             quartiles: (17.0000000000, 20.0000000000, 24.0000000000),
693             iqr: 7.0000000000,
694         };
695         check(val, summ);
696     }
697     #[test]
698     fn test_pois25lambda30() {
699         let val = &[27.0000000000,
700                     33.0000000000,
701                     34.0000000000,
702                     34.0000000000,
703                     24.0000000000,
704                     39.0000000000,
705                     28.0000000000,
706                     27.0000000000,
707                     31.0000000000,
708                     28.0000000000,
709                     38.0000000000,
710                     21.0000000000,
711                     33.0000000000,
712                     36.0000000000,
713                     29.0000000000,
714                     37.0000000000,
715                     32.0000000000,
716                     34.0000000000,
717                     31.0000000000,
718                     39.0000000000,
719                     25.0000000000,
720                     31.0000000000,
721                     32.0000000000,
722                     40.0000000000,
723                     24.0000000000];
724         let summ = &Summary {
725             sum: 787.0000000000,
726             min: 21.0000000000,
727             max: 40.0000000000,
728             mean: 31.4800000000,
729             median: 32.0000000000,
730             var: 26.5933333333,
731             std_dev: 5.1568724372,
732             std_dev_pct: 16.3814245145,
733             median_abs_dev: 5.9304000000,
734             median_abs_dev_pct: 18.5325000000,
735             quartiles: (28.0000000000, 32.0000000000, 34.0000000000),
736             iqr: 6.0000000000,
737         };
738         check(val, summ);
739     }
740     #[test]
741     fn test_pois25lambda40() {
742         let val = &[42.0000000000,
743                     50.0000000000,
744                     42.0000000000,
745                     46.0000000000,
746                     34.0000000000,
747                     45.0000000000,
748                     34.0000000000,
749                     49.0000000000,
750                     39.0000000000,
751                     28.0000000000,
752                     40.0000000000,
753                     35.0000000000,
754                     37.0000000000,
755                     39.0000000000,
756                     46.0000000000,
757                     44.0000000000,
758                     32.0000000000,
759                     45.0000000000,
760                     42.0000000000,
761                     37.0000000000,
762                     48.0000000000,
763                     42.0000000000,
764                     33.0000000000,
765                     42.0000000000,
766                     48.0000000000];
767         let summ = &Summary {
768             sum: 1019.0000000000,
769             min: 28.0000000000,
770             max: 50.0000000000,
771             mean: 40.7600000000,
772             median: 42.0000000000,
773             var: 34.4400000000,
774             std_dev: 5.8685603004,
775             std_dev_pct: 14.3978417577,
776             median_abs_dev: 5.9304000000,
777             median_abs_dev_pct: 14.1200000000,
778             quartiles: (37.0000000000, 42.0000000000, 45.0000000000),
779             iqr: 8.0000000000,
780         };
781         check(val, summ);
782     }
783     #[test]
784     fn test_pois25lambda50() {
785         let val = &[45.0000000000,
786                     43.0000000000,
787                     44.0000000000,
788                     61.0000000000,
789                     51.0000000000,
790                     53.0000000000,
791                     59.0000000000,
792                     52.0000000000,
793                     49.0000000000,
794                     51.0000000000,
795                     51.0000000000,
796                     50.0000000000,
797                     49.0000000000,
798                     56.0000000000,
799                     42.0000000000,
800                     52.0000000000,
801                     51.0000000000,
802                     43.0000000000,
803                     48.0000000000,
804                     48.0000000000,
805                     50.0000000000,
806                     42.0000000000,
807                     43.0000000000,
808                     42.0000000000,
809                     60.0000000000];
810         let summ = &Summary {
811             sum: 1235.0000000000,
812             min: 42.0000000000,
813             max: 61.0000000000,
814             mean: 49.4000000000,
815             median: 50.0000000000,
816             var: 31.6666666667,
817             std_dev: 5.6273143387,
818             std_dev_pct: 11.3913245723,
819             median_abs_dev: 4.4478000000,
820             median_abs_dev_pct: 8.8956000000,
821             quartiles: (44.0000000000, 50.0000000000, 52.0000000000),
822             iqr: 8.0000000000,
823         };
824         check(val, summ);
825     }
826     #[test]
827     fn test_unif25() {
828         let val = &[99.0000000000,
829                     55.0000000000,
830                     92.0000000000,
831                     79.0000000000,
832                     14.0000000000,
833                     2.0000000000,
834                     33.0000000000,
835                     49.0000000000,
836                     3.0000000000,
837                     32.0000000000,
838                     84.0000000000,
839                     59.0000000000,
840                     22.0000000000,
841                     86.0000000000,
842                     76.0000000000,
843                     31.0000000000,
844                     29.0000000000,
845                     11.0000000000,
846                     41.0000000000,
847                     53.0000000000,
848                     45.0000000000,
849                     44.0000000000,
850                     98.0000000000,
851                     98.0000000000,
852                     7.0000000000];
853         let summ = &Summary {
854             sum: 1242.0000000000,
855             min: 2.0000000000,
856             max: 99.0000000000,
857             mean: 49.6800000000,
858             median: 45.0000000000,
859             var: 1015.6433333333,
860             std_dev: 31.8691595957,
861             std_dev_pct: 64.1488719719,
862             median_abs_dev: 45.9606000000,
863             median_abs_dev_pct: 102.1346666667,
864             quartiles: (29.0000000000, 45.0000000000, 79.0000000000),
865             iqr: 50.0000000000,
866         };
867         check(val, summ);
868     }
869
870     #[test]
871     fn test_sum_f64s() {
872         assert_eq!([0.5f64, 3.2321f64, 1.5678f64].sum(), 5.2999);
873     }
874     #[test]
875     fn test_sum_f64_between_ints_that_sum_to_0() {
876         assert_eq!([1e30f64, 1.2f64, -1e30f64].sum(), 1.2);
877     }
878 }
879
880 #[cfg(test)]
881 mod bench {
882     use Bencher;
883     use stats::Stats;
884
885     #[bench]
886     pub fn sum_three_items(b: &mut Bencher) {
887         b.iter(|| {
888             [1e20f64, 1.5f64, -1e20f64].sum();
889         })
890     }
891     #[bench]
892     pub fn sum_many_f64(b: &mut Bencher) {
893         let nums = [-1e30f64, 1e60, 1e30, 1.0, -1e60];
894         let v = (0..500).map(|i| nums[i % 5]).collect::<Vec<_>>();
895
896         b.iter(|| {
897             v.sum();
898         })
899     }
900 }