diff --git a/rustfmt.toml b/rustfmt.toml index d1c82741..2f399e9c 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -12,9 +12,6 @@ use_small_heuristics = "Default" # TODO: single line functions only where short, please? # https://github.com/rust-lang/rustfmt/issues/3358 fn_single_line = false -fn_params_layout = "Compressed" -overflow_delimited_expr = true -where_single_line = true # enum_discrim_align_threshold = 20 # struct_field_align_threshold = 20 @@ -23,7 +20,6 @@ where_single_line = true edition = "2021" # Misc: -inline_attribute_width = 80 blank_lines_upper_bound = 2 reorder_impl_items = true # report_todo = "Unnumbered" diff --git a/src/distribution/bernoulli.rs b/src/distribution/bernoulli.rs index 46648a7a..0af2f101 100644 --- a/src/distribution/bernoulli.rs +++ b/src/distribution/bernoulli.rs @@ -101,7 +101,7 @@ impl DiscreteCDF for Bernoulli { self.b.cdf(x) } - /// Calculates the survival function for the + /// Calculates the survival function for the /// bernoulli distribution at `x`. /// /// # Formula @@ -158,6 +158,7 @@ impl Distribution for Bernoulli { fn mean(&self) -> Option { self.b.mean() } + /// Returns the variance of the bernoulli /// distribution /// @@ -169,6 +170,7 @@ impl Distribution for Bernoulli { fn variance(&self) -> Option { self.b.variance() } + /// Returns the entropy of the bernoulli /// distribution /// @@ -181,6 +183,7 @@ impl Distribution for Bernoulli { fn entropy(&self) -> Option { self.b.entropy() } + /// Returns the skewness of the bernoulli /// distribution /// diff --git a/src/distribution/beta.rs b/src/distribution/beta.rs index 4682948c..39d03598 100644 --- a/src/distribution/beta.rs +++ b/src/distribution/beta.rs @@ -155,7 +155,7 @@ impl ContinuousCDF for Beta { } else if ulps_eq!(self.shape_a, 1.0) && ulps_eq!(self.shape_b, 1.0) { 1. - x } else { - beta::beta_reg(self.shape_b, self.shape_a, 1.0 - x) + beta::beta_reg(self.shape_b, self.shape_a, 1.0 - x) } } } @@ -208,6 +208,7 @@ impl Distribution for Beta { }; Some(mean) } + /// Returns the variance of the beta distribution /// /// # Remarks @@ -230,6 +231,7 @@ impl Distribution for Beta { }; Some(var) } + /// Returns the entropy of the beta distribution /// /// # Formula @@ -251,6 +253,7 @@ impl Distribution for Beta { }; Some(entr) } + /// Returns the skewness of the Beta distribution /// /// # Formula diff --git a/src/distribution/binomial.rs b/src/distribution/binomial.rs index f3bfc76d..4cad7b67 100644 --- a/src/distribution/binomial.rs +++ b/src/distribution/binomial.rs @@ -181,6 +181,7 @@ impl Distribution for Binomial { fn mean(&self) -> Option { Some(self.p * self.n as f64) } + /// Returns the variance of the binomial distribution /// /// # Formula @@ -191,6 +192,7 @@ impl Distribution for Binomial { fn variance(&self) -> Option { Some(self.p * (1.0 - self.p) * self.n as f64) } + /// Returns the entropy of the binomial distribution /// /// # Formula @@ -209,6 +211,7 @@ impl Distribution for Binomial { }; Some(entr) } + /// Returns the skewness of the binomial distribution /// /// # Formula diff --git a/src/distribution/categorical.rs b/src/distribution/categorical.rs index ba3c39de..dfd8a4ca 100644 --- a/src/distribution/categorical.rs +++ b/src/distribution/categorical.rs @@ -12,7 +12,7 @@ use std::f64; /// # Examples /// /// ``` -/// +/// /// use statrs::distribution::{Categorical, Discrete}; /// use statrs::statistics::Distribution; /// use statrs::prec; @@ -25,7 +25,7 @@ use std::f64; pub struct Categorical { norm_pmf: Vec, cdf: Vec, - sf: Vec + sf: Vec, } impl Categorical { @@ -194,6 +194,7 @@ impl Distribution for Categorical { .fold(0.0, |acc, (idx, &val)| acc + idx as f64 * val), ) } + /// Returns the variance of the categorical distribution /// /// # Formula @@ -217,6 +218,7 @@ impl Distribution for Categorical { }); Some(var) } + /// Returns the entropy of the categorical distribution /// /// # Formula @@ -294,7 +296,7 @@ pub fn prob_mass_to_cdf(prob_mass: &[f64]) -> Vec { cdf } -/// Computes the sf from the given cumulative densities. +/// Computes the sf from the given cumulative densities. /// Performs no parameter or bounds checking. pub fn cdf_to_sf(cdf: &[f64]) -> Vec { let max = *cdf.last().unwrap(); diff --git a/src/distribution/chi.rs b/src/distribution/chi.rs index f72376bb..2ca32518 100644 --- a/src/distribution/chi.rs +++ b/src/distribution/chi.rs @@ -185,6 +185,7 @@ impl Distribution for Chi { Some(mean) } } + /// Returns the variance of the chi distribution /// /// # Remarks @@ -203,6 +204,7 @@ impl Distribution for Chi { let mean = self.mean()?; Some(self.freedom - mean * mean) } + /// Returns the entropy of the chi distribution /// /// # Remarks @@ -228,6 +230,7 @@ impl Distribution for Chi { / 2.0; Some(entr) } + /// Returns the skewness of the chi distribution /// /// # Remarks diff --git a/src/distribution/chi_squared.rs b/src/distribution/chi_squared.rs index ab8dc398..cf07f4cf 100644 --- a/src/distribution/chi_squared.rs +++ b/src/distribution/chi_squared.rs @@ -177,6 +177,7 @@ impl Distribution for ChiSquared { fn mean(&self) -> Option { self.g.mean() } + /// Returns the variance of the chi-squared distribution /// /// # Formula @@ -189,6 +190,7 @@ impl Distribution for ChiSquared { fn variance(&self) -> Option { self.g.variance() } + /// Returns the entropy of the chi-squared distribution /// /// # Formula @@ -202,6 +204,7 @@ impl Distribution for ChiSquared { fn entropy(&self) -> Option { self.g.entropy() } + /// Returns the skewness of the chi-squared distribution /// /// # Formula diff --git a/src/distribution/dirac.rs b/src/distribution/dirac.rs index daa081a2..9a66e5e0 100644 --- a/src/distribution/dirac.rs +++ b/src/distribution/dirac.rs @@ -56,7 +56,6 @@ impl ContinuousCDF for Dirac { /// dirac distribution at `x` /// /// Where the value is 1 if x > `v`, 0 otherwise. - /// fn cdf(&self, x: f64) -> f64 { if x < self.0 { 0.0 @@ -69,7 +68,6 @@ impl ContinuousCDF for Dirac { /// dirac distribution at `x` /// /// Where the value is 0 if x > `v`, 1 otherwise. - /// fn sf(&self, x: f64) -> f64 { if x < self.0 { 1.0 @@ -117,6 +115,7 @@ impl Distribution for Dirac { fn mean(&self) -> Option { Some(self.0) } + /// Returns the variance of the dirac distribution /// /// # Formula @@ -129,6 +128,7 @@ impl Distribution for Dirac { fn variance(&self) -> Option { Some(0.0) } + /// Returns the entropy of the dirac distribution /// /// # Formula @@ -141,6 +141,7 @@ impl Distribution for Dirac { fn entropy(&self) -> Option { Some(0.0) } + /// Returns the skewness of the dirac distribution /// /// # Formula diff --git a/src/distribution/dirichlet.rs b/src/distribution/dirichlet.rs index a08b3175..0f703056 100644 --- a/src/distribution/dirichlet.rs +++ b/src/distribution/dirichlet.rs @@ -107,6 +107,7 @@ impl Dirichlet { fn alpha_sum(&self) -> f64 { self.alpha.fold(0.0, |acc, x| acc + x) } + /// Returns the entropy of the dirichlet distribution /// /// # Formula diff --git a/src/distribution/discrete_uniform.rs b/src/distribution/discrete_uniform.rs index 926b1cf3..59b0da4e 100644 --- a/src/distribution/discrete_uniform.rs +++ b/src/distribution/discrete_uniform.rs @@ -84,7 +84,7 @@ impl DiscreteCDF for DiscreteUniform { } fn sf(&self, x: i64) -> f64 { - //1. - self.cdf(x) + // 1. - self.cdf(x) if x < self.min { 1.0 } else if x >= self.max { @@ -137,6 +137,7 @@ impl Distribution for DiscreteUniform { fn mean(&self) -> Option { Some((self.min + self.max) as f64 / 2.0) } + /// Returns the variance of the discrete uniform distribution /// /// # Formula @@ -148,6 +149,7 @@ impl Distribution for DiscreteUniform { let diff = (self.max - self.min) as f64; Some(((diff + 1.0) * (diff + 1.0) - 1.0) / 12.0) } + /// Returns the entropy of the discrete uniform distribution /// /// # Formula @@ -159,6 +161,7 @@ impl Distribution for DiscreteUniform { let diff = (self.max - self.min) as f64; Some((diff + 1.0).ln()) } + /// Returns the skewness of the discrete uniform distribution /// /// # Formula diff --git a/src/distribution/empirical.rs b/src/distribution/empirical.rs index 43588819..0e8c964a 100644 --- a/src/distribution/empirical.rs +++ b/src/distribution/empirical.rs @@ -56,7 +56,6 @@ impl Empirical { /// /// let mut result = Empirical::new(); /// assert!(result.is_ok()); - /// /// ``` pub fn new() -> Result { Ok(Empirical { @@ -65,6 +64,7 @@ impl Empirical { data: BTreeMap::new(), }) } + pub fn from_vec(src: Vec) -> Empirical { let mut empirical = Empirical::new().unwrap(); for elt in src.into_iter() { @@ -72,6 +72,7 @@ impl Empirical { } empirical } + pub fn add(&mut self, data_point: f64) { if !data_point.is_nan() { self.sum += 1.; @@ -89,6 +90,7 @@ impl Empirical { *self.data.entry(NonNan(data_point)).or_insert(0) += 1; } } + pub fn remove(&mut self, data_point: f64) { if !data_point.is_nan() { if let (Some(val), Some((mean, var))) = @@ -111,6 +113,7 @@ impl Empirical { } } } + // Due to issues with rounding and floating-point accuracy the default // implementation may be ill-behaved. // Specialized inverse cdfs should be used whenever possible. @@ -158,7 +161,7 @@ impl ::rand::distributions::Distribution for Empirical { /// Panics if number of samples is zero impl Max for Empirical { fn max(&self) -> f64 { - self.data.keys().rev().map(|key| key.0) .next().unwrap() + self.data.keys().rev().map(|key| key.0).next().unwrap() } } @@ -173,6 +176,7 @@ impl Distribution for Empirical { fn mean(&self) -> Option { self.mean_and_var.map(|(mean, _)| mean) } + fn variance(&self) -> Option { self.mean_and_var.map(|(_, var)| var / (self.sum - 1.)) } @@ -256,8 +260,8 @@ mod tests { let unchanged = empirical.clone(); empirical.add(2.0); empirical.remove(2.0); - //because of rounding errors, this doesn't hold in general - //due to the mean and variance being calculated in a streaming way + // because of rounding errors, this doesn't hold in general + // due to the mean and variance being calculated in a streaming way assert_eq!(unchanged, empirical); } } diff --git a/src/distribution/erlang.rs b/src/distribution/erlang.rs index e0721f24..c959e122 100644 --- a/src/distribution/erlang.rs +++ b/src/distribution/erlang.rs @@ -166,6 +166,7 @@ impl Distribution for Erlang { fn mean(&self) -> Option { self.g.mean() } + /// Returns the variance of the erlang distribution /// /// # Formula @@ -178,6 +179,7 @@ impl Distribution for Erlang { fn variance(&self) -> Option { self.g.variance() } + /// Returns the entropy of the erlang distribution /// /// # Formula @@ -191,6 +193,7 @@ impl Distribution for Erlang { fn entropy(&self) -> Option { self.g.entropy() } + /// Returns the skewness of the erlang distribution /// /// # Formula diff --git a/src/distribution/exponential.rs b/src/distribution/exponential.rs index 0856989c..0c5d076f 100644 --- a/src/distribution/exponential.rs +++ b/src/distribution/exponential.rs @@ -152,6 +152,7 @@ impl Distribution for Exp { fn mean(&self) -> Option { Some(1.0 / self.rate) } + /// Returns the variance of the exponential distribution /// /// # Formula @@ -164,6 +165,7 @@ impl Distribution for Exp { fn variance(&self) -> Option { Some(1.0 / (self.rate * self.rate)) } + /// Returns the entropy of the exponential distribution /// /// # Formula @@ -176,6 +178,7 @@ impl Distribution for Exp { fn entropy(&self) -> Option { Some(1.0 - self.rate.ln()) } + /// Returns the skewness of the exponential distribution /// /// # Formula diff --git a/src/distribution/fisher_snedecor.rs b/src/distribution/fisher_snedecor.rs index da8d9570..c5e2463a 100644 --- a/src/distribution/fisher_snedecor.rs +++ b/src/distribution/fisher_snedecor.rs @@ -144,8 +144,8 @@ impl ContinuousCDF for FisherSnedecor { } else { beta::beta_reg( self.freedom_2 / 2.0, - self.freedom_1 / 2.0, - 1. - ((self.freedom_1 * x) / (self.freedom_1 * x + self.freedom_2)) + self.freedom_1 / 2.0, + 1. - ((self.freedom_1 * x) / (self.freedom_1 * x + self.freedom_2)), ) } } @@ -206,6 +206,7 @@ impl Distribution for FisherSnedecor { Some(self.freedom_2 / (self.freedom_2 - 2.0)) } } + /// Returns the variance of the fisher-snedecor distribution /// /// # Panics @@ -237,6 +238,7 @@ impl Distribution for FisherSnedecor { Some(val) } } + /// Returns the skewness of the fisher-snedecor distribution /// /// # Panics diff --git a/src/distribution/gamma.rs b/src/distribution/gamma.rs index b8e7df44..5f73919c 100644 --- a/src/distribution/gamma.rs +++ b/src/distribution/gamma.rs @@ -132,17 +132,13 @@ impl ContinuousCDF for Gamma { fn sf(&self, x: f64) -> f64 { if x <= 0.0 { 1.0 - } - else if ulps_eq!(x, self.shape) && self.rate.is_infinite() { + } else if ulps_eq!(x, self.shape) && self.rate.is_infinite() { 0.0 - } - else if self.rate.is_infinite() { + } else if self.rate.is_infinite() { 1.0 - } - else if x.is_infinite() { + } else if x.is_infinite() { 0.0 - } - else { + } else { gamma::gamma_ur(self.shape, x * self.rate) } } @@ -191,6 +187,7 @@ impl Distribution for Gamma { fn mean(&self) -> Option { Some(self.shape / self.rate) } + /// Returns the variance of the gamma distribution /// /// # Formula @@ -203,6 +200,7 @@ impl Distribution for Gamma { fn variance(&self) -> Option { Some(self.shape / (self.rate * self.rate)) } + /// Returns the entropy of the gamma distribution /// /// # Formula @@ -219,6 +217,7 @@ impl Distribution for Gamma { + (1.0 - self.shape) * gamma::digamma(self.shape); Some(entr) } + /// Returns the skewness of the gamma distribution /// /// # Formula @@ -456,7 +455,11 @@ mod tests { for &(arg, res) in test.iter() { test_case_special(arg, res, 10e-6, f); } - let test = [((10.0, 10.0), 0.9), ((10.0, 1.0), 9.0), ((10.0, f64::INFINITY), 0.0)]; + let test = [ + ((10.0, 10.0), 0.9), + ((10.0, 1.0), 9.0), + ((10.0, f64::INFINITY), 0.0), + ]; for &(arg, res) in test.iter() { test_case(arg, res, f); } @@ -504,9 +507,9 @@ mod tests { for &(arg, x, res) in test.iter() { test_case(arg, res, f(x)); } - //TODO: test special + // TODO: test special // test_is_nan((10.0, f64::INFINITY), pdf(1.0)); // is this really the behavior we want? - //TODO: test special + // TODO: test special // (10.0, f64::INFINITY, f64::INFINITY, 0.0, pdf(f64::INFINITY)),]; } diff --git a/src/distribution/geometric.rs b/src/distribution/geometric.rs index f87f5ee0..d61b7fc8 100644 --- a/src/distribution/geometric.rs +++ b/src/distribution/geometric.rs @@ -159,6 +159,7 @@ impl Distribution for Geometric { fn mean(&self) -> Option { Some(1.0 / self.p) } + /// Returns the standard deviation of the geometric distribution /// /// # Formula @@ -169,6 +170,7 @@ impl Distribution for Geometric { fn variance(&self) -> Option { Some((1.0 - self.p) / (self.p * self.p)) } + /// Returns the entropy of the geometric distribution /// /// # Formula @@ -180,6 +182,7 @@ impl Distribution for Geometric { let inv = 1.0 / self.p; Some(-inv * (1. - self.p).log(2.0) + (inv - 1.).log(2.0)) } + /// Returns the skewness of the geometric distribution /// /// # Formula diff --git a/src/distribution/hypergeometric.rs b/src/distribution/hypergeometric.rs index 95f44d18..1116ac7a 100644 --- a/src/distribution/hypergeometric.rs +++ b/src/distribution/hypergeometric.rs @@ -258,6 +258,7 @@ impl Distribution for Hypergeometric { Some(self.successes as f64 * self.draws as f64 / self.population as f64) } } + /// Returns the variance of the hypergeometric distribution /// /// # None @@ -281,6 +282,7 @@ impl Distribution for Hypergeometric { Some(val) } } + /// Returns the skewness of the hypergeometric distribution /// /// # None diff --git a/src/distribution/inverse_gamma.rs b/src/distribution/inverse_gamma.rs index 31b1d4f6..b55afd64 100644 --- a/src/distribution/inverse_gamma.rs +++ b/src/distribution/inverse_gamma.rs @@ -190,6 +190,7 @@ impl Distribution for InverseGamma { Some(self.rate / (self.shape - 1.0)) } } + /// Returns the variance of the inverse gamma distribution /// /// # None @@ -212,6 +213,7 @@ impl Distribution for InverseGamma { Some(val) } } + /// Returns the entropy of the inverse gamma distribution /// /// # Formula @@ -227,6 +229,7 @@ impl Distribution for InverseGamma { - (1.0 + self.shape) * gamma::digamma(self.shape); Some(entr) } + /// Returns the skewness of the inverse gamma distribution /// /// # None diff --git a/src/distribution/laplace.rs b/src/distribution/laplace.rs index 66893b46..f04306f1 100644 --- a/src/distribution/laplace.rs +++ b/src/distribution/laplace.rs @@ -193,6 +193,7 @@ impl Distribution for Laplace { fn mean(&self) -> Option { Some(self.location) } + /// Returns the variance of the laplace distribution /// /// # Formula @@ -205,6 +206,7 @@ impl Distribution for Laplace { fn variance(&self) -> Option { Some(2. * self.scale * self.scale) } + /// Returns the entropy of the laplace distribution /// /// # Formula @@ -217,6 +219,7 @@ impl Distribution for Laplace { fn entropy(&self) -> Option { Some((2. * self.scale).ln() + 1.) } + /// Returns the skewness of the laplace distribution /// /// # Formula @@ -386,7 +389,13 @@ mod tests { #[test] fn test_entropy() { let entropy = |x: Laplace| x.entropy().unwrap(); - test_almost(f64::NEG_INFINITY, 0.1, (2.0 * f64::consts::E * 0.1).ln(), 1E-12, entropy); + test_almost( + f64::NEG_INFINITY, + 0.1, + (2.0 * f64::consts::E * 0.1).ln(), + 1E-12, + entropy, + ); test_almost(-6.0, 1.0, (2.0 * f64::consts::E).ln(), 1E-12, entropy); test_almost(1.0, 7.0, (2.0 * f64::consts::E * 7.0).ln(), 1E-12, entropy); test_almost(5., 10., (2. * f64::consts::E * 10.).ln(), 1E-12, entropy); diff --git a/src/distribution/log_normal.rs b/src/distribution/log_normal.rs index 028869e0..def44d0c 100644 --- a/src/distribution/log_normal.rs +++ b/src/distribution/log_normal.rs @@ -156,6 +156,7 @@ impl Distribution for LogNormal { fn mean(&self) -> Option { Some((self.location + self.scale * self.scale / 2.0).exp()) } + /// Returns the variance of the log-normal distribution /// /// # Formula @@ -169,6 +170,7 @@ impl Distribution for LogNormal { let sigma2 = self.scale * self.scale; Some((sigma2.exp() - 1.0) * (self.location + self.location + sigma2).exp()) } + /// Returns the entropy of the log-normal distribution /// /// # Formula @@ -181,6 +183,7 @@ impl Distribution for LogNormal { fn entropy(&self) -> Option { Some(0.5 + self.scale.ln() + self.location + consts::LN_SQRT_2PI) } + /// Returns the skewness of the log-normal distribution /// /// # Formula diff --git a/src/distribution/multivariate_normal.rs b/src/distribution/multivariate_normal.rs index ff4ec6bc..368da0ec 100644 --- a/src/distribution/multivariate_normal.rs +++ b/src/distribution/multivariate_normal.rs @@ -205,6 +205,7 @@ impl<'a> Continuous<&'a DVector, f64> for MultivariateNormal { .unwrap(); self.pdf_const * exp_term.exp() } + /// Calculates the log probability density function for the multivariate /// normal distribution at `x`. Equivalent to pdf(x).ln(). fn ln_pdf(&self, x: &'a DVector) -> f64 { @@ -232,6 +233,7 @@ impl Continuous, f64> for MultivariateNormal { fn pdf(&self, x: Vec) -> f64 { self.pdf(&DVector::from(x)) } + /// Calculates the log probability density function for the multivariate /// normal distribution at `x`. Equivalent to pdf(x).ln(). fn ln_pdf(&self, x: Vec) -> f64 { diff --git a/src/distribution/negative_binomial.rs b/src/distribution/negative_binomial.rs index 4c69a869..a924ee8d 100644 --- a/src/distribution/negative_binomial.rs +++ b/src/distribution/negative_binomial.rs @@ -188,6 +188,7 @@ impl DiscreteDistribution for NegativeBinomial { fn mean(&self) -> Option { Some(self.r * (1.0 - self.p) / self.p) } + /// Returns the variance of the negative binomial distribution. /// /// # Formula @@ -198,6 +199,7 @@ impl DiscreteDistribution for NegativeBinomial { fn variance(&self) -> Option { Some(self.r * (1.0 - self.p) / (self.p * self.p)) } + /// Returns the skewness of the negative binomial distribution. /// /// # Formula diff --git a/src/distribution/normal.rs b/src/distribution/normal.rs index bcd01b81..311e4cc8 100644 --- a/src/distribution/normal.rs +++ b/src/distribution/normal.rs @@ -160,6 +160,7 @@ impl Distribution for Normal { fn mean(&self) -> Option { Some(self.mean) } + /// Returns the variance of the normal distribution /// /// # Formula @@ -172,6 +173,7 @@ impl Distribution for Normal { fn variance(&self) -> Option { Some(self.std_dev * self.std_dev) } + /// Returns the entropy of the normal distribution /// /// # Formula @@ -184,6 +186,7 @@ impl Distribution for Normal { fn entropy(&self) -> Option { Some(self.std_dev.ln() + consts::LN_SQRT_2PIE) } + /// Returns the skewness of the normal distribution /// /// # Formula diff --git a/src/distribution/pareto.rs b/src/distribution/pareto.rs index 031205eb..5a18c03f 100644 --- a/src/distribution/pareto.rs +++ b/src/distribution/pareto.rs @@ -188,6 +188,7 @@ impl Distribution for Pareto { Some((self.shape * self.scale) / (self.shape - 1.0)) } } + /// Returns the variance of the Pareto distribution /// /// # Formula @@ -209,6 +210,7 @@ impl Distribution for Pareto { Some(a * a * self.shape / (self.shape - 2.0)) } } + /// Returns the entropy for the Pareto distribution /// /// # Formula @@ -221,6 +223,7 @@ impl Distribution for Pareto { fn entropy(&self) -> Option { Some(self.shape.ln() - self.scale.ln() - (1.0 / self.shape) - 1.0) } + /// Returns the skewness of the Pareto distribution /// /// # Panics diff --git a/src/distribution/poisson.rs b/src/distribution/poisson.rs index e8f98bef..ce07ce96 100644 --- a/src/distribution/poisson.rs +++ b/src/distribution/poisson.rs @@ -148,6 +148,7 @@ impl Distribution for Poisson { fn mean(&self) -> Option { Some(self.lambda) } + /// Returns the variance of the poisson distribution /// /// # Formula @@ -160,6 +161,7 @@ impl Distribution for Poisson { fn variance(&self) -> Option { Some(self.lambda) } + /// Returns the entropy of the poisson distribution /// /// # Formula @@ -177,6 +179,7 @@ impl Distribution for Poisson { - 19.0 / (360.0 * self.lambda * self.lambda * self.lambda), ) } + /// Returns the skewness of the poisson distribution /// /// # Formula diff --git a/src/distribution/students_t.rs b/src/distribution/students_t.rs index 4f84c489..e8c183f3 100644 --- a/src/distribution/students_t.rs +++ b/src/distribution/students_t.rs @@ -252,6 +252,7 @@ impl Distribution for StudentsT { Some(self.location) } } + /// Returns the variance of the student's t-distribution /// /// # None @@ -280,6 +281,7 @@ impl Distribution for StudentsT { None } } + /// Returns the entropy for the student's t-distribution /// /// # Formula @@ -301,6 +303,7 @@ impl Distribution for StudentsT { + (self.freedom.sqrt() * beta::beta(self.freedom / 2.0, 0.5)).ln(); Some(result + shift) } + /// Returns the skewness of the student's t-distribution /// /// # None @@ -598,7 +601,6 @@ mod tests { test_case((0.0, 1.0, f64::INFINITY), 0.977249868051821, cdf(2.0)); } - #[test] fn test_sf() { let sf = |arg: f64| move |x: StudentsT| x.sf(arg); @@ -1096,7 +1098,7 @@ mod tests { // for p in ps: // q = t.invcdf(p, df) // print(f"({p:5.3f}, {df:5.1f}, {float(q)}),") - // + #[rustfmt::skip] let invcdf_data = [ // p df inverse_cdf(p, df) (0.001, 1.0, -318.30883898555044), diff --git a/src/distribution/triangular.rs b/src/distribution/triangular.rs index a9cb98a9..a94bb0bb 100644 --- a/src/distribution/triangular.rs +++ b/src/distribution/triangular.rs @@ -165,6 +165,7 @@ impl Distribution for Triangular { fn mean(&self) -> Option { Some((self.min + self.max + self.mode) / 3.0) } + /// Returns the variance of the triangular distribution /// /// # Formula @@ -178,6 +179,7 @@ impl Distribution for Triangular { let c = self.mode; Some((a * a + b * b + c * c - a * b - a * c - b * c) / 18.0) } + /// Returns the entropy of the triangular distribution /// /// # Formula @@ -188,6 +190,7 @@ impl Distribution for Triangular { fn entropy(&self) -> Option { Some(0.5 + ((self.max - self.min) / 2.0).ln()) } + /// Returns the skewness of the triangular distribution /// /// # Formula diff --git a/src/distribution/uniform.rs b/src/distribution/uniform.rs index c4abc985..9414222a 100644 --- a/src/distribution/uniform.rs +++ b/src/distribution/uniform.rs @@ -140,6 +140,7 @@ impl Distribution for Uniform { fn mean(&self) -> Option { Some((self.min + self.max) / 2.0) } + /// Returns the variance for the continuous uniform distribution /// /// # Formula @@ -150,6 +151,7 @@ impl Distribution for Uniform { fn variance(&self) -> Option { Some((self.max - self.min) * (self.max - self.min) / 12.0) } + /// Returns the entropy for the continuous uniform distribution /// /// # Formula @@ -160,6 +162,7 @@ impl Distribution for Uniform { fn entropy(&self) -> Option { Some((self.max - self.min).ln()) } + /// Returns the skewness for the continuous uniform distribution /// /// # Formula diff --git a/src/distribution/weibull.rs b/src/distribution/weibull.rs index 4f04403d..4b928aa7 100644 --- a/src/distribution/weibull.rs +++ b/src/distribution/weibull.rs @@ -177,6 +177,7 @@ impl Distribution for Weibull { fn mean(&self) -> Option { Some(self.scale * gamma::gamma(1.0 + 1.0 / self.shape)) } + /// Returns the variance of the weibull distribution /// /// # Formula @@ -191,6 +192,7 @@ impl Distribution for Weibull { let mean = self.mean()?; Some(self.scale * self.scale * gamma::gamma(1.0 + 2.0 / self.shape) - mean * mean) } + /// Returns the entropy of the weibull distribution /// /// # Formula @@ -207,6 +209,7 @@ impl Distribution for Weibull { + 1.0; Some(entr) } + /// Returns the skewness of the weibull distribution /// /// # Formula diff --git a/src/function/beta.rs b/src/function/beta.rs index fec184f2..128406c7 100644 --- a/src/function/beta.rs +++ b/src/function/beta.rs @@ -204,7 +204,6 @@ pub fn checked_beta_reg(a: f64, b: f64, x: f64) -> Result { } /// Computes the inverse of the regularized incomplete beta function -// // This code is based on the implementation in the ["special"][1] crate, // which in turn is based on a [C implementation][2] by John Burkardt. The // original algorithm was published in Applied Statistics and is known as diff --git a/src/statistics/slice_statistics.rs b/src/statistics/slice_statistics.rs index 1d1b79cc..a9cbfdde 100644 --- a/src/statistics/slice_statistics.rs +++ b/src/statistics/slice_statistics.rs @@ -7,6 +7,7 @@ pub struct Data(D); impl> Index for Data { type Output = f64; + fn index(&self, i: usize) -> &f64 { &self.0.as_ref()[i] } @@ -22,18 +23,23 @@ impl + AsRef<[f64]>> Data { pub fn new(data: D) -> Self { Data(data) } + pub fn swap(&mut self, i: usize, j: usize) { self.0.as_mut().swap(i, j) } + pub fn len(&self) -> usize { self.0.as_ref().len() } + pub fn is_empty(&self) -> bool { self.0.as_ref().len() == 0 } + pub fn iter(&self) -> core::slice::Iter<'_, f64> { self.0.as_ref().iter() } + // Selection algorithm from Numerical Recipes // See: https://en.wikipedia.org/wiki/Selection_algorithm fn select_inplace(&mut self, rank: usize) -> f64 { @@ -299,6 +305,7 @@ impl + AsRef<[f64]>> Distribution for Data { fn mean(&self) -> Option { Some(Statistics::mean(self.iter())) } + /// Estimates the unbiased population variance from the provided samples /// /// # Remarks