]> git.lizzy.rs Git - rust.git/blob - src/libtest/stats.rs
Auto merge of #27995 - nagisa:windows-error-message, 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 = &[
384             958.0000000000,
385             924.0000000000,
386         ];
387         let summ = &Summary {
388             sum: 1882.0000000000,
389             min: 924.0000000000,
390             max: 958.0000000000,
391             mean: 941.0000000000,
392             median: 941.0000000000,
393             var: 578.0000000000,
394             std_dev: 24.0416305603,
395             std_dev_pct: 2.5549022912,
396             median_abs_dev: 25.2042000000,
397             median_abs_dev_pct: 2.6784484591,
398             quartiles: (932.5000000000,941.0000000000,949.5000000000),
399             iqr: 17.0000000000,
400         };
401         check(val, summ);
402     }
403     #[test]
404     fn test_norm10narrow() {
405         let val = &[
406             966.0000000000,
407             985.0000000000,
408             1110.0000000000,
409             848.0000000000,
410             821.0000000000,
411             975.0000000000,
412             962.0000000000,
413             1157.0000000000,
414             1217.0000000000,
415             955.0000000000,
416         ];
417         let summ = &Summary {
418             sum: 9996.0000000000,
419             min: 821.0000000000,
420             max: 1217.0000000000,
421             mean: 999.6000000000,
422             median: 970.5000000000,
423             var: 16050.7111111111,
424             std_dev: 126.6914010938,
425             std_dev_pct: 12.6742097933,
426             median_abs_dev: 102.2994000000,
427             median_abs_dev_pct: 10.5408964451,
428             quartiles: (956.7500000000,970.5000000000,1078.7500000000),
429             iqr: 122.0000000000,
430         };
431         check(val, summ);
432     }
433     #[test]
434     fn test_norm10medium() {
435         let val = &[
436             954.0000000000,
437             1064.0000000000,
438             855.0000000000,
439             1000.0000000000,
440             743.0000000000,
441             1084.0000000000,
442             704.0000000000,
443             1023.0000000000,
444             357.0000000000,
445             869.0000000000,
446         ];
447         let summ = &Summary {
448             sum: 8653.0000000000,
449             min: 357.0000000000,
450             max: 1084.0000000000,
451             mean: 865.3000000000,
452             median: 911.5000000000,
453             var: 48628.4555555556,
454             std_dev: 220.5186059170,
455             std_dev_pct: 25.4846418487,
456             median_abs_dev: 195.7032000000,
457             median_abs_dev_pct: 21.4704552935,
458             quartiles: (771.0000000000,911.5000000000,1017.2500000000),
459             iqr: 246.2500000000,
460         };
461         check(val, summ);
462     }
463     #[test]
464     fn test_norm10wide() {
465         let val = &[
466             505.0000000000,
467             497.0000000000,
468             1591.0000000000,
469             887.0000000000,
470             1026.0000000000,
471             136.0000000000,
472             1580.0000000000,
473             940.0000000000,
474             754.0000000000,
475             1433.0000000000,
476         ];
477         let summ = &Summary {
478             sum: 9349.0000000000,
479             min: 136.0000000000,
480             max: 1591.0000000000,
481             mean: 934.9000000000,
482             median: 913.5000000000,
483             var: 239208.9888888889,
484             std_dev: 489.0899599142,
485             std_dev_pct: 52.3146817750,
486             median_abs_dev: 611.5725000000,
487             median_abs_dev_pct: 66.9482758621,
488             quartiles: (567.2500000000,913.5000000000,1331.2500000000),
489             iqr: 764.0000000000,
490         };
491         check(val, summ);
492     }
493     #[test]
494     fn test_norm25verynarrow() {
495         let val = &[
496             991.0000000000,
497             1018.0000000000,
498             998.0000000000,
499             1013.0000000000,
500             974.0000000000,
501             1007.0000000000,
502             1014.0000000000,
503             999.0000000000,
504             1011.0000000000,
505             978.0000000000,
506             985.0000000000,
507             999.0000000000,
508             983.0000000000,
509             982.0000000000,
510             1015.0000000000,
511             1002.0000000000,
512             977.0000000000,
513             948.0000000000,
514             1040.0000000000,
515             974.0000000000,
516             996.0000000000,
517             989.0000000000,
518             1015.0000000000,
519             994.0000000000,
520             1024.0000000000,
521         ];
522         let summ = &Summary {
523             sum: 24926.0000000000,
524             min: 948.0000000000,
525             max: 1040.0000000000,
526             mean: 997.0400000000,
527             median: 998.0000000000,
528             var: 393.2066666667,
529             std_dev: 19.8294393937,
530             std_dev_pct: 1.9888308788,
531             median_abs_dev: 22.2390000000,
532             median_abs_dev_pct: 2.2283567134,
533             quartiles: (983.0000000000,998.0000000000,1013.0000000000),
534             iqr: 30.0000000000,
535         };
536         check(val, summ);
537     }
538     #[test]
539     fn test_exp10a() {
540         let val = &[
541             23.0000000000,
542             11.0000000000,
543             2.0000000000,
544             57.0000000000,
545             4.0000000000,
546             12.0000000000,
547             5.0000000000,
548             29.0000000000,
549             3.0000000000,
550             21.0000000000,
551         ];
552         let summ = &Summary {
553             sum: 167.0000000000,
554             min: 2.0000000000,
555             max: 57.0000000000,
556             mean: 16.7000000000,
557             median: 11.5000000000,
558             var: 287.7888888889,
559             std_dev: 16.9643416875,
560             std_dev_pct: 101.5828843560,
561             median_abs_dev: 13.3434000000,
562             median_abs_dev_pct: 116.0295652174,
563             quartiles: (4.2500000000,11.5000000000,22.5000000000),
564             iqr: 18.2500000000,
565         };
566         check(val, summ);
567     }
568     #[test]
569     fn test_exp10b() {
570         let val = &[
571             24.0000000000,
572             17.0000000000,
573             6.0000000000,
574             38.0000000000,
575             25.0000000000,
576             7.0000000000,
577             51.0000000000,
578             2.0000000000,
579             61.0000000000,
580             32.0000000000,
581         ];
582         let summ = &Summary {
583             sum: 263.0000000000,
584             min: 2.0000000000,
585             max: 61.0000000000,
586             mean: 26.3000000000,
587             median: 24.5000000000,
588             var: 383.5666666667,
589             std_dev: 19.5848580967,
590             std_dev_pct: 74.4671410520,
591             median_abs_dev: 22.9803000000,
592             median_abs_dev_pct: 93.7971428571,
593             quartiles: (9.5000000000,24.5000000000,36.5000000000),
594             iqr: 27.0000000000,
595         };
596         check(val, summ);
597     }
598     #[test]
599     fn test_exp10c() {
600         let val = &[
601             71.0000000000,
602             2.0000000000,
603             32.0000000000,
604             1.0000000000,
605             6.0000000000,
606             28.0000000000,
607             13.0000000000,
608             37.0000000000,
609             16.0000000000,
610             36.0000000000,
611         ];
612         let summ = &Summary {
613             sum: 242.0000000000,
614             min: 1.0000000000,
615             max: 71.0000000000,
616             mean: 24.2000000000,
617             median: 22.0000000000,
618             var: 458.1777777778,
619             std_dev: 21.4050876611,
620             std_dev_pct: 88.4507754589,
621             median_abs_dev: 21.4977000000,
622             median_abs_dev_pct: 97.7168181818,
623             quartiles: (7.7500000000,22.0000000000,35.0000000000),
624             iqr: 27.2500000000,
625         };
626         check(val, summ);
627     }
628     #[test]
629     fn test_exp25() {
630         let val = &[
631             3.0000000000,
632             24.0000000000,
633             1.0000000000,
634             19.0000000000,
635             7.0000000000,
636             5.0000000000,
637             30.0000000000,
638             39.0000000000,
639             31.0000000000,
640             13.0000000000,
641             25.0000000000,
642             48.0000000000,
643             1.0000000000,
644             6.0000000000,
645             42.0000000000,
646             63.0000000000,
647             2.0000000000,
648             12.0000000000,
649             108.0000000000,
650             26.0000000000,
651             1.0000000000,
652             7.0000000000,
653             44.0000000000,
654             25.0000000000,
655             11.0000000000,
656         ];
657         let summ = &Summary {
658             sum: 593.0000000000,
659             min: 1.0000000000,
660             max: 108.0000000000,
661             mean: 23.7200000000,
662             median: 19.0000000000,
663             var: 601.0433333333,
664             std_dev: 24.5161851301,
665             std_dev_pct: 103.3565983562,
666             median_abs_dev: 19.2738000000,
667             median_abs_dev_pct: 101.4410526316,
668             quartiles: (6.0000000000,19.0000000000,31.0000000000),
669             iqr: 25.0000000000,
670         };
671         check(val, summ);
672     }
673     #[test]
674     fn test_binom25() {
675         let val = &[
676             18.0000000000,
677             17.0000000000,
678             27.0000000000,
679             15.0000000000,
680             21.0000000000,
681             25.0000000000,
682             17.0000000000,
683             24.0000000000,
684             25.0000000000,
685             24.0000000000,
686             26.0000000000,
687             26.0000000000,
688             23.0000000000,
689             15.0000000000,
690             23.0000000000,
691             17.0000000000,
692             18.0000000000,
693             18.0000000000,
694             21.0000000000,
695             16.0000000000,
696             15.0000000000,
697             31.0000000000,
698             20.0000000000,
699             17.0000000000,
700             15.0000000000,
701         ];
702         let summ = &Summary {
703             sum: 514.0000000000,
704             min: 15.0000000000,
705             max: 31.0000000000,
706             mean: 20.5600000000,
707             median: 20.0000000000,
708             var: 20.8400000000,
709             std_dev: 4.5650848842,
710             std_dev_pct: 22.2037202539,
711             median_abs_dev: 5.9304000000,
712             median_abs_dev_pct: 29.6520000000,
713             quartiles: (17.0000000000,20.0000000000,24.0000000000),
714             iqr: 7.0000000000,
715         };
716         check(val, summ);
717     }
718     #[test]
719     fn test_pois25lambda30() {
720         let val = &[
721             27.0000000000,
722             33.0000000000,
723             34.0000000000,
724             34.0000000000,
725             24.0000000000,
726             39.0000000000,
727             28.0000000000,
728             27.0000000000,
729             31.0000000000,
730             28.0000000000,
731             38.0000000000,
732             21.0000000000,
733             33.0000000000,
734             36.0000000000,
735             29.0000000000,
736             37.0000000000,
737             32.0000000000,
738             34.0000000000,
739             31.0000000000,
740             39.0000000000,
741             25.0000000000,
742             31.0000000000,
743             32.0000000000,
744             40.0000000000,
745             24.0000000000,
746         ];
747         let summ = &Summary {
748             sum: 787.0000000000,
749             min: 21.0000000000,
750             max: 40.0000000000,
751             mean: 31.4800000000,
752             median: 32.0000000000,
753             var: 26.5933333333,
754             std_dev: 5.1568724372,
755             std_dev_pct: 16.3814245145,
756             median_abs_dev: 5.9304000000,
757             median_abs_dev_pct: 18.5325000000,
758             quartiles: (28.0000000000,32.0000000000,34.0000000000),
759             iqr: 6.0000000000,
760         };
761         check(val, summ);
762     }
763     #[test]
764     fn test_pois25lambda40() {
765         let val = &[
766             42.0000000000,
767             50.0000000000,
768             42.0000000000,
769             46.0000000000,
770             34.0000000000,
771             45.0000000000,
772             34.0000000000,
773             49.0000000000,
774             39.0000000000,
775             28.0000000000,
776             40.0000000000,
777             35.0000000000,
778             37.0000000000,
779             39.0000000000,
780             46.0000000000,
781             44.0000000000,
782             32.0000000000,
783             45.0000000000,
784             42.0000000000,
785             37.0000000000,
786             48.0000000000,
787             42.0000000000,
788             33.0000000000,
789             42.0000000000,
790             48.0000000000,
791         ];
792         let summ = &Summary {
793             sum: 1019.0000000000,
794             min: 28.0000000000,
795             max: 50.0000000000,
796             mean: 40.7600000000,
797             median: 42.0000000000,
798             var: 34.4400000000,
799             std_dev: 5.8685603004,
800             std_dev_pct: 14.3978417577,
801             median_abs_dev: 5.9304000000,
802             median_abs_dev_pct: 14.1200000000,
803             quartiles: (37.0000000000,42.0000000000,45.0000000000),
804             iqr: 8.0000000000,
805         };
806         check(val, summ);
807     }
808     #[test]
809     fn test_pois25lambda50() {
810         let val = &[
811             45.0000000000,
812             43.0000000000,
813             44.0000000000,
814             61.0000000000,
815             51.0000000000,
816             53.0000000000,
817             59.0000000000,
818             52.0000000000,
819             49.0000000000,
820             51.0000000000,
821             51.0000000000,
822             50.0000000000,
823             49.0000000000,
824             56.0000000000,
825             42.0000000000,
826             52.0000000000,
827             51.0000000000,
828             43.0000000000,
829             48.0000000000,
830             48.0000000000,
831             50.0000000000,
832             42.0000000000,
833             43.0000000000,
834             42.0000000000,
835             60.0000000000,
836         ];
837         let summ = &Summary {
838             sum: 1235.0000000000,
839             min: 42.0000000000,
840             max: 61.0000000000,
841             mean: 49.4000000000,
842             median: 50.0000000000,
843             var: 31.6666666667,
844             std_dev: 5.6273143387,
845             std_dev_pct: 11.3913245723,
846             median_abs_dev: 4.4478000000,
847             median_abs_dev_pct: 8.8956000000,
848             quartiles: (44.0000000000,50.0000000000,52.0000000000),
849             iqr: 8.0000000000,
850         };
851         check(val, summ);
852     }
853     #[test]
854     fn test_unif25() {
855         let val = &[
856             99.0000000000,
857             55.0000000000,
858             92.0000000000,
859             79.0000000000,
860             14.0000000000,
861             2.0000000000,
862             33.0000000000,
863             49.0000000000,
864             3.0000000000,
865             32.0000000000,
866             84.0000000000,
867             59.0000000000,
868             22.0000000000,
869             86.0000000000,
870             76.0000000000,
871             31.0000000000,
872             29.0000000000,
873             11.0000000000,
874             41.0000000000,
875             53.0000000000,
876             45.0000000000,
877             44.0000000000,
878             98.0000000000,
879             98.0000000000,
880             7.0000000000,
881         ];
882         let summ = &Summary {
883             sum: 1242.0000000000,
884             min: 2.0000000000,
885             max: 99.0000000000,
886             mean: 49.6800000000,
887             median: 45.0000000000,
888             var: 1015.6433333333,
889             std_dev: 31.8691595957,
890             std_dev_pct: 64.1488719719,
891             median_abs_dev: 45.9606000000,
892             median_abs_dev_pct: 102.1346666667,
893             quartiles: (29.0000000000,45.0000000000,79.0000000000),
894             iqr: 50.0000000000,
895         };
896         check(val, summ);
897     }
898
899     #[test]
900     fn test_sum_f64s() {
901         assert_eq!([0.5f64, 3.2321f64, 1.5678f64].sum(), 5.2999);
902     }
903     #[test]
904     fn test_sum_f64_between_ints_that_sum_to_0() {
905         assert_eq!([1e30f64, 1.2f64, -1e30f64].sum(), 1.2);
906     }
907 }
908
909 #[cfg(test)]
910 mod bench {
911     use Bencher;
912     use stats::Stats;
913
914     #[bench]
915     pub fn sum_three_items(b: &mut Bencher) {
916         b.iter(|| {
917             [1e20f64, 1.5f64, -1e20f64].sum();
918         })
919     }
920     #[bench]
921     pub fn sum_many_f64(b: &mut Bencher) {
922         let nums = [-1e30f64, 1e60, 1e30, 1.0, -1e60];
923         let v = (0..500).map(|i| nums[i%5]).collect::<Vec<_>>();
924
925         b.iter(|| {
926             v.sum();
927         })
928     }
929 }