(index<- )        ./libtest/stats.rs

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


libtest/stats.rs:290:78-290:78 -fn- definition:
// linear interpolation. If samples are not sorted, return nonsensical value.
fn percentile_of_sorted<T: Float + FromPrimitive>(sorted_samples: &[T],
                                                             pct: T) -> T {
references:- 6
273:         let first = FromPrimitive::from_uint(25).unwrap();
274:         let a = percentile_of_sorted(tmp.as_slice(), first);
275:         let secound = FromPrimitive::from_uint(50).unwrap();
--
325:     let hundred: T = FromPrimitive::from_uint(100).unwrap();
326:     let hi = percentile_of_sorted(tmp.as_slice(), hundred-pct);
327:     for samp in samples.mut_iter() {


libtest/stats.rs:35:1-35:1 -fn- definition:
fn local_sort<T: Float>(v: &mut [T]) {
    v.sort_by(|x: &T, y: &T| local_cmp(*x, *y));
}
references:- 3
271:         let mut tmp = Vec::from_slice(self);
272:         local_sort(tmp.as_mut_slice());
273:         let first = FromPrimitive::from_uint(25).unwrap();
--
322:     let mut tmp = Vec::from_slice(samples);
323:     local_sort(tmp.as_mut_slice());
324:     let lo = percentile_of_sorted(tmp.as_slice(), pct);


libtest/stats.rs:320:50-320:50 -fn- definition:
/// See: http://en.wikipedia.org/wiki/Winsorising
pub fn winsorize<T: Float + FromPrimitive>(samples: &mut [T], pct: T) {
    let mut tmp = Vec::from_slice(samples);
references:- 2
libtest/lib.rs:
1290:             stats::winsorize(samples, 5.0);
1291:             let summ5 = stats::Summary::new(samples);


libtest/stats.rs:130:22-130:22 -struct- definition:
pub struct Summary<T> {
    pub sum: T,
    pub min: T,
references:- 18
149:     pub fn new(samples: &[T]) -> Summary<T> {
150:         Summary {
151:             sum: samples.sum(),
--
361:                      w: &mut io::Writer,
362:                      s: &Summary<T>,
363:                      width_hint: uint)
libtest/lib.rs:
415: pub struct BenchSamples {
416:     ns_iter_summ: stats::Summary<f64>,
417:     mb_s: uint,
--
1251:     // This is a more statistics-driven benchmark algorithm
1252:     pub fn auto_bench(&mut self, f: |&mut Bencher|) -> stats::Summary<f64> {
libtest/stats.rs:
146: impl<T: Float + FromPrimitive> Summary<T> {