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