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