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