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