aboutsummaryrefslogtreecommitdiff
path: root/src/stats
diff options
context:
space:
mode:
Diffstat (limited to 'src/stats')
-rwxr-xr-xsrc/stats/bivariate/mod.rs53
-rwxr-xr-xsrc/stats/univariate/kde/mod.rs10
-rwxr-xr-xsrc/stats/univariate/mixed.rs61
-rwxr-xr-xsrc/stats/univariate/mod.rs55
-rwxr-xr-xsrc/stats/univariate/percentiles.rs22
-rwxr-xr-xsrc/stats/univariate/sample.rs57
6 files changed, 172 insertions, 86 deletions
diff --git a/src/stats/bivariate/mod.rs b/src/stats/bivariate/mod.rs
index d1e8df7..2351c9e 100755
--- a/src/stats/bivariate/mod.rs
+++ b/src/stats/bivariate/mod.rs
@@ -8,6 +8,7 @@ use crate::stats::bivariate::resamples::Resamples;
use crate::stats::float::Float;
use crate::stats::tuple::{Tuple, TupledDistributionsBuilder};
use crate::stats::univariate::Sample;
+#[cfg(feature = "rayon")]
use rayon::iter::{IntoParallelIterator, ParallelIterator};
/// Bivariate `(X, Y)` data
@@ -72,27 +73,41 @@ where
T::Distributions: Send,
T::Builder: Send,
{
- (0..nresamples)
- .into_par_iter()
- .map_init(
- || Resamples::new(*self),
- |resamples, _| statistic(resamples.next()),
- )
- .fold(
- || T::Builder::new(0),
- |mut sub_distributions, sample| {
+ #[cfg(feature = "rayon")]
+ {
+ (0..nresamples)
+ .into_par_iter()
+ .map_init(
+ || Resamples::new(*self),
+ |resamples, _| statistic(resamples.next()),
+ )
+ .fold(
+ || T::Builder::new(0),
+ |mut sub_distributions, sample| {
+ sub_distributions.push(sample);
+ sub_distributions
+ },
+ )
+ .reduce(
+ || T::Builder::new(0),
+ |mut a, mut b| {
+ a.extend(&mut b);
+ a
+ },
+ )
+ .complete()
+ }
+ #[cfg(not(feature = "rayon"))]
+ {
+ let mut resamples = Resamples::new(*self);
+ (0..nresamples)
+ .map(|_| statistic(resamples.next()))
+ .fold(T::Builder::new(0), |mut sub_distributions, sample| {
sub_distributions.push(sample);
sub_distributions
- },
- )
- .reduce(
- || T::Builder::new(0),
- |mut a, mut b| {
- a.extend(&mut b);
- a
- },
- )
- .complete()
+ })
+ .complete()
+ }
}
/// Returns a view into the `X` data
diff --git a/src/stats/univariate/kde/mod.rs b/src/stats/univariate/kde/mod.rs
index 9b0836d..c54de55 100755
--- a/src/stats/univariate/kde/mod.rs
+++ b/src/stats/univariate/kde/mod.rs
@@ -5,6 +5,7 @@ pub mod kernel;
use self::kernel::Kernel;
use crate::stats::float::Float;
use crate::stats::univariate::Sample;
+#[cfg(feature = "rayon")]
use rayon::prelude::*;
/// Univariate kernel density estimator
@@ -42,8 +43,13 @@ where
///
/// - Multihreaded
pub fn map(&self, xs: &[A]) -> Box<[A]> {
- xs.par_iter()
- .map(|&x| self.estimate(x))
+ #[cfg(feature = "rayon")]
+ let iter = xs.par_iter();
+
+ #[cfg(not(feature = "rayon"))]
+ let iter = xs.iter();
+
+ iter.map(|&x| self.estimate(x))
.collect::<Vec<_>>()
.into_boxed_slice()
}
diff --git a/src/stats/univariate/mixed.rs b/src/stats/univariate/mixed.rs
index 5c0a59f..d6b845d 100755
--- a/src/stats/univariate/mixed.rs
+++ b/src/stats/univariate/mixed.rs
@@ -4,6 +4,7 @@ use crate::stats::float::Float;
use crate::stats::tuple::{Tuple, TupledDistributionsBuilder};
use crate::stats::univariate::Resamples;
use crate::stats::univariate::Sample;
+#[cfg(feature = "rayon")]
use rayon::prelude::*;
/// Performs a *mixed* two-sample bootstrap
@@ -27,31 +28,51 @@ where
c.extend_from_slice(b);
let c = Sample::new(&c);
- (0..nresamples)
- .into_par_iter()
- .map_init(
- || Resamples::new(c),
- |resamples, _| {
+ #[cfg(feature = "rayon")]
+ {
+ (0..nresamples)
+ .into_par_iter()
+ .map_init(
+ || Resamples::new(c),
+ |resamples, _| {
+ let resample = resamples.next();
+ let a: &Sample<A> = Sample::new(&resample[..n_a]);
+ let b: &Sample<A> = Sample::new(&resample[n_a..]);
+
+ statistic(a, b)
+ },
+ )
+ .fold(
+ || T::Builder::new(0),
+ |mut sub_distributions, sample| {
+ sub_distributions.push(sample);
+ sub_distributions
+ },
+ )
+ .reduce(
+ || T::Builder::new(0),
+ |mut a, mut b| {
+ a.extend(&mut b);
+ a
+ },
+ )
+ .complete()
+ }
+ #[cfg(not(feature = "rayon"))]
+ {
+ let mut resamples = Resamples::new(c);
+ (0..nresamples)
+ .map(|_| {
let resample = resamples.next();
let a: &Sample<A> = Sample::new(&resample[..n_a]);
let b: &Sample<A> = Sample::new(&resample[n_a..]);
statistic(a, b)
- },
- )
- .fold(
- || T::Builder::new(0),
- |mut sub_distributions, sample| {
+ })
+ .fold(T::Builder::new(0), |mut sub_distributions, sample| {
sub_distributions.push(sample);
sub_distributions
- },
- )
- .reduce(
- || T::Builder::new(0),
- |mut a, mut b| {
- a.extend(&mut b);
- a
- },
- )
- .complete()
+ })
+ .complete()
+ }
}
diff --git a/src/stats/univariate/mod.rs b/src/stats/univariate/mod.rs
index 8dfb5f8..5b22127 100755
--- a/src/stats/univariate/mod.rs
+++ b/src/stats/univariate/mod.rs
@@ -11,6 +11,7 @@ pub mod outliers;
use crate::stats::float::Float;
use crate::stats::tuple::{Tuple, TupledDistributionsBuilder};
+#[cfg(feature = "rayon")]
use rayon::prelude::*;
use std::cmp;
@@ -42,11 +43,42 @@ where
let nresamples_sqrt = (nresamples as f64).sqrt().ceil() as usize;
let per_chunk = (nresamples + nresamples_sqrt - 1) / nresamples_sqrt;
- (0..nresamples_sqrt)
- .into_par_iter()
- .map_init(
- || (Resamples::new(a), Resamples::new(b)),
- |(a_resamples, b_resamples), i| {
+ #[cfg(feature = "rayon")]
+ {
+ (0..nresamples_sqrt)
+ .into_par_iter()
+ .map_init(
+ || (Resamples::new(a), Resamples::new(b)),
+ |(a_resamples, b_resamples), i| {
+ let start = i * per_chunk;
+ let end = cmp::min((i + 1) * per_chunk, nresamples);
+ let a_resample = a_resamples.next();
+
+ let mut sub_distributions: T::Builder =
+ TupledDistributionsBuilder::new(end - start);
+
+ for _ in start..end {
+ let b_resample = b_resamples.next();
+ sub_distributions.push(statistic(a_resample, b_resample));
+ }
+ sub_distributions
+ },
+ )
+ .reduce(
+ || T::Builder::new(0),
+ |mut a, mut b| {
+ a.extend(&mut b);
+ a
+ },
+ )
+ .complete()
+ }
+ #[cfg(not(feature = "rayon"))]
+ {
+ let mut a_resamples = Resamples::new(a);
+ let mut b_resamples = Resamples::new(b);
+ (0..nresamples_sqrt)
+ .map(|i| {
let start = i * per_chunk;
let end = cmp::min((i + 1) * per_chunk, nresamples);
let a_resample = a_resamples.next();
@@ -59,14 +91,11 @@ where
sub_distributions.push(statistic(a_resample, b_resample));
}
sub_distributions
- },
- )
- .reduce(
- || T::Builder::new(0),
- |mut a, mut b| {
+ })
+ .fold(T::Builder::new(0), |mut a, mut b| {
a.extend(&mut b);
a
- },
- )
- .complete()
+ })
+ .complete()
+ }
}
diff --git a/src/stats/univariate/percentiles.rs b/src/stats/univariate/percentiles.rs
index be6bcf3..39def18 100755
--- a/src/stats/univariate/percentiles.rs
+++ b/src/stats/univariate/percentiles.rs
@@ -54,27 +54,23 @@ where
/// Returns the interquartile range
pub fn iqr(&self) -> A {
- unsafe {
- let q1 = self.at_unchecked(A::cast(25));
- let q3 = self.at_unchecked(A::cast(75));
+ let q1 = self.at(A::cast(25));
+ let q3 = self.at(A::cast(75));
- q3 - q1
- }
+ q3 - q1
}
/// Returns the 50th percentile
pub fn median(&self) -> A {
- unsafe { self.at_unchecked(A::cast(50)) }
+ self.at(A::cast(50))
}
/// Returns the 25th, 50th and 75th percentiles
pub fn quartiles(&self) -> (A, A, A) {
- unsafe {
- (
- self.at_unchecked(A::cast(25)),
- self.at_unchecked(A::cast(50)),
- self.at_unchecked(A::cast(75)),
- )
- }
+ (
+ self.at(A::cast(25)),
+ self.at(A::cast(50)),
+ self.at(A::cast(75)),
+ )
}
}
diff --git a/src/stats/univariate/sample.rs b/src/stats/univariate/sample.rs
index 8f10db7..6fbb4fb 100755
--- a/src/stats/univariate/sample.rs
+++ b/src/stats/univariate/sample.rs
@@ -4,6 +4,7 @@ use crate::stats::float::Float;
use crate::stats::tuple::{Tuple, TupledDistributionsBuilder};
use crate::stats::univariate::Percentiles;
use crate::stats::univariate::Resamples;
+#[cfg(feature = "rayon")]
use rayon::prelude::*;
/// A collection of data points drawn from a population
@@ -12,6 +13,7 @@ use rayon::prelude::*;
///
/// - The sample contains at least 2 data points
/// - The sample contains no `NaN`s
+#[repr(transparent)]
pub struct Sample<A>([A]);
// TODO(rust-lang/rfcs#735) move this `impl` into a private percentiles module
@@ -127,7 +129,10 @@ where
}
let mut v = self.to_vec().into_boxed_slice();
+ #[cfg(feature = "rayon")]
v.par_sort_unstable_by(cmp);
+ #[cfg(not(feature = "rayon"))]
+ v.sort_unstable_by(cmp);
// NB :-1: to intra-crate privacy rules
unsafe { mem::transmute(v) }
@@ -206,27 +211,41 @@ where
T::Distributions: Send,
T::Builder: Send,
{
- (0..nresamples)
- .into_par_iter()
- .map_init(
- || Resamples::new(self),
- |resamples, _| statistic(resamples.next()),
- )
- .fold(
- || T::Builder::new(0),
- |mut sub_distributions, sample| {
+ #[cfg(feature = "rayon")]
+ {
+ (0..nresamples)
+ .into_par_iter()
+ .map_init(
+ || Resamples::new(self),
+ |resamples, _| statistic(resamples.next()),
+ )
+ .fold(
+ || T::Builder::new(0),
+ |mut sub_distributions, sample| {
+ sub_distributions.push(sample);
+ sub_distributions
+ },
+ )
+ .reduce(
+ || T::Builder::new(0),
+ |mut a, mut b| {
+ a.extend(&mut b);
+ a
+ },
+ )
+ .complete()
+ }
+ #[cfg(not(feature = "rayon"))]
+ {
+ let mut resamples = Resamples::new(self);
+ (0..nresamples)
+ .map(|_| statistic(resamples.next()))
+ .fold(T::Builder::new(0), |mut sub_distributions, sample| {
sub_distributions.push(sample);
sub_distributions
- },
- )
- .reduce(
- || T::Builder::new(0),
- |mut a, mut b| {
- a.extend(&mut b);
- a
- },
- )
- .complete()
+ })
+ .complete()
+ }
}
#[cfg(test)]