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