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