blob: d07633ef96120ec6f983b4b8ed370e8fcc4787b6 [file] [log] [blame]
Jeff Vander Stoepd036b622020-12-17 19:59:02 +01001// 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