bencher/
stats.rs

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