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