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