#![doc = include_str!("../README.md")]
use std::f64::consts::PI;
use rand::{random};
const GAMMA: f64 = 0.577215664901532860606512090082;
pub fn sample_mean(x: &[f64]) -> f64 {
if x.is_empty() {
return f64::NAN;
}
let sum: f64 = x.iter().sum();
sum / (x.len() as f64)
}
pub fn sample_var(x: &[f64]) -> f64 {
let n = x.len();
if n < 2 {
return f64::NAN;
}
let xbar = sample_mean(x);
let ss: f64 = x.iter().map(|xx| (xx - xbar).powi(2)).sum();
ss / ((n - 1) as f64)
}
pub fn sample_sd(x: &[f64]) -> f64 {
sample_var(x).sqrt()
}
pub struct BetaDist {
pub alpha: f64,
pub beta: f64,
}
impl BetaDist {
pub fn pdf(&mut self, x: f64) -> f64 {
beta_pdf(x, self.alpha, self.beta)
}
pub fn cdf(&mut self, x: f64) -> f64 {
beta_cdf(x, self.alpha, self.beta)
}
pub fn per(&mut self, x: f64) -> f64 {
beta_per(x,self.alpha, self.beta)
}
pub fn ran(&mut self) -> f64 {
beta_ran(self.alpha, self.beta)
}
pub fn ranvec(&mut self, n: u64) -> Vec<f64> {
beta_ranvec(n, self.alpha, self.beta)
}
pub fn mean(&mut self) -> f64 {
self.alpha / (self.alpha + self.beta)
}
pub fn var(&mut self) -> f64 {
self.alpha * self.beta /
((self.alpha + self.beta).powi(2) * (self.alpha + self.beta + 1.0))
}
pub fn sd(&mut self) -> f64 {
self.var().sqrt()
}
}
pub fn beta_pdf(x: f64, alpha: f64, beta: f64) -> f64 {
if alpha <= 0.0 || beta <= 0.0 {
println!("NAN produced. Error in function beta_pdf");
return f64::NAN;
}
if x <= 0.0 || x >= 1.0 {
return 0.0;
}
((alpha - 1.0)*x.ln() + (beta - 1.0)*(1.0 - x).ln() - beta_fn_ln(alpha, beta)).exp()
}
pub fn beta_cdf(x: f64, alpha: f64, beta: f64) -> f64 {
if alpha <= 0.0 || beta <= 0.0 {
println!("NAN produced. Error in function beta_cdf");
return f64::NAN;
}
if x <= 0.0 {
return 0.0;
}
if x >= 1.0 {
return 1.0;
}
betai(x, alpha, beta)
}
pub fn beta_per(q: f64, alpha: f64, beta: f64) -> f64 {
betai_inv(q, alpha, beta)
}
pub fn beta_ran(alpha: f64, beta: f64) -> f64 {
let x = gamma_ran(alpha, 1.0);
let y = gamma_ran(beta, 1.0);
x / (x+y)
}
pub fn beta_ranvec(n: u64, alpha: f64, beta: f64) -> Vec<f64> {
let mut xvec: Vec<f64> = Vec::new();
for _ in 0..n {
xvec.push(beta_ran(alpha, beta));
}
xvec
}
pub struct ChiSqDist {
pub nu: f64,
}
impl ChiSqDist {
pub fn pdf(&mut self, x: f64) -> f64 {
chisq_pdf(x, self.nu)
}
pub fn cdf(&mut self, x: f64) -> f64 {
chisq_cdf(x, self.nu)
}
pub fn per(&mut self, x: f64) -> f64 {
chisq_per(x, self.nu)
}
pub fn ran(&mut self) -> f64 {
chisq_ran(self.nu)
}
pub fn ranvec(&mut self, n: u64) -> Vec<f64> {
chisq_ranvec(n, self.nu)
}
pub fn mean(&mut self) -> f64 {
self.nu
}
pub fn var(&mut self) -> f64 {
2.0 * self.nu
}
pub fn sd(&mut self) -> f64 {
self.var().sqrt()
}
}
pub fn chisq_pdf(x: f64, nu: f64) -> f64 {
if nu <= 0.0 {
println!("NAN produced. Error in function chisq_pdf");
return f64::NAN;
}
if x <= 0.0 {
return 0.0;
}
gamma_pdf(x, nu/2.0,1.0/2.0)
}
pub fn chisq_cdf(x: f64, nu: f64) -> f64 {
if nu <= 0.0 {
println!("NAN produced. Error in function chisq_cdf");
return f64::NAN;
}
if x <= 0.0 {
return 0.0;
}
gamma_cdf(x, nu / 2.0, 0.5)
}
pub fn chisq_per(p: f64, nu: f64) -> f64 {
gamma_per(p, nu/2.0, 1.0/2.0)
}
pub fn chisq_ran(nu: f64) -> f64 {
gamma_ran(nu/2.0, 1.0/2.0)
}
pub fn chisq_ranvec(n: u64, nu: f64) -> Vec<f64> {
let mut xvec: Vec<f64> = Vec::new();
for _ in 0..n {
xvec.push(chisq_ran(nu));
}
xvec
}
pub struct ExpDist {
pub lambda: f64,
}
impl ExpDist {
pub fn pdf(&mut self, x: f64) -> f64 {
exp_pdf(x, self.lambda)
}
pub fn cdf(&mut self, x: f64) -> f64 {
exp_cdf(x, self.lambda)
}
pub fn per(&mut self, x: f64) -> f64 {
exp_per(x, self.lambda)
}
pub fn ran(&mut self) -> f64 {
exp_ran(self.lambda)
}
pub fn ranvec(&mut self, n: u64) -> Vec<f64> {
exp_ranvec(n, self.lambda)
}
pub fn mean(&mut self) -> f64 {
1.0 / self.lambda
}
pub fn var(&mut self) -> f64 {
1.0 / self.lambda.powi(2)
}
pub fn sd(&mut self) -> f64 {
self.var().sqrt()
}
}
pub fn exp_pdf(x: f64, lambda: f64) -> f64 {
if lambda <= 0.0 {
println!("NAN produced. Error in function exp_pdf");
return f64::NAN;
}
if x <= 0.0 {
return 0.0;
}
lambda * (-lambda*x).exp()
}
pub fn exp_cdf(x: f64, lambda: f64) -> f64 {
if lambda <= 0.0 {
println!("NAN produced. Error in function exp_cdf");
return f64::NAN;
}
if x <= 0.0 {
return 0.0;
}
1.0 - (-lambda * x).exp()
}
pub fn exp_per(p: f64, lambda: f64) -> f64 {
-(1.0-p).ln() / lambda
}
pub fn exp_ran(lambda: f64) -> f64 {
let u: f64;
u = random();
-(1.0-u).ln()/lambda
}
pub fn exp_ranvec(n: u64, lambda: f64) -> Vec<f64> {
let mut xvec: Vec<f64> = Vec::new();
for _ in 0..n {
xvec.push(exp_ran(lambda));
}
xvec
}
pub struct FDist {
pub nu1: f64,
pub nu2: f64,
}
impl FDist {
pub fn pdf(&mut self, x: f64) -> f64 {
f_pdf(x, self.nu1, self.nu2)
}
pub fn cdf(&mut self, x: f64) -> f64 {
f_cdf(x, self.nu1, self.nu2)
}
pub fn per(&mut self, x: f64) -> f64 {
f_per(x, self.nu1, self.nu2)
}
pub fn ran(&mut self) -> f64 {
f_ran(self.nu1, self.nu2)
}
pub fn ranvec(&mut self, n: u64) -> Vec<f64> {
f_ranvec(n, self.nu1, self.nu2)
}
pub fn mean(&mut self) -> f64 {
self.nu2 / (self.nu2-2.0)
}
pub fn var(&mut self) -> f64 {
2.0 * self.nu2.powi(2) * (self.nu1 + self.nu2 - 2.0) /
(self.nu1 * (self.nu2 - 2.0).powi(2) * (self.nu2 - 4.0))
}
pub fn sd(&mut self) -> f64 {
self.var().sqrt()
}
}
pub fn f_pdf(x: f64, nu1: f64, nu2: f64) -> f64 {
if nu1 <= 0.0 || nu2 <= 0.0 {
println!("NAN produced. Error in function f_pdf");
return f64::NAN;
}
if x <= 0.0 {
return 0.0;
}
(0.5*(nu1*(nu1*x).ln() + nu2*nu2.ln() - (nu1+nu2)*(nu1*x + nu2).ln())
- x.ln() - beta_fn_ln(nu1/2.0, nu2/2.0)).exp()
}
pub fn f_cdf(x: f64, nu1: f64, nu2: f64) -> f64 {
if nu1 <= 0.0 || nu2 <= 0.0 {
println!("NAN produced. Error in function f_cdf");
return f64::NAN;
}
if x <= 0.0 {
return 0.0;
}
1.0 - betai(nu2 / (nu2 + nu1 * x), nu2 / 2.0, nu1 / 2.0)
}
pub fn f_per(p: f64, nu1: f64, nu2: f64) -> f64 {
nu2/nu1 * (1.0 / beta_per(1.0-p,nu2/2.0,nu1/2.0) - 1.0)
}
pub fn f_ran(nu1: f64, nu2: f64) -> f64 {
let x = beta_ran(nu1/2.0, nu2/2.0);
nu2 * x / (nu1 * (1.0-x))
}
pub fn f_ranvec(n: u64, nu1: f64, nu2: f64) -> Vec<f64> {
let mut xvec: Vec<f64> = Vec::new();
for _ in 0..n {
xvec.push(f_ran(nu1, nu2));
}
xvec
}
pub struct GammaDist {
pub alpha: f64,
pub beta: f64,
}
impl GammaDist {
pub fn pdf(&mut self, x: f64) -> f64 {
gamma_pdf(x, self.alpha, self.beta)
}
pub fn cdf(&mut self, x: f64) -> f64 {
gamma_cdf(x, self.alpha, self.beta)
}
pub fn per(&mut self, x: f64) -> f64 {
gamma_per(x, self.alpha, self.beta)
}
pub fn ran(&mut self) -> f64 {
gamma_ran(self.alpha, self.beta)
}
pub fn ranvec(&mut self, n: u64) -> Vec<f64> {
gamma_ranvec(n, self.alpha, self.beta)
}
pub fn mean(&mut self) -> f64 {
self.alpha / self.beta
}
pub fn var(&mut self) -> f64 {
self.alpha / self.beta.powi(2)
}
pub fn sd(&mut self) -> f64 {
self.var().sqrt()
}
}
pub fn gamma_pdf(x: f64, alpha: f64, beta: f64) -> f64 {
if alpha <= 0.0 || beta <= 0.0 {
println!("NAN produced. Error in function gamma_pdf");
return f64::NAN;
}
if x <= 0.0 {
return 0.0;
}
(alpha*beta.ln() - gamma_ln(alpha) + (alpha-1.0)*x.ln() - beta*x).exp()
}
pub fn gamma_cdf(x: f64, alpha: f64, beta: f64) -> f64 {
if alpha <= 0.0 || beta <= 0.0 {
println!("NAN produced. Error in function gamma_cdf");
return f64::NAN;
}
if x <= 0.0 {
return 0.0;
}
gammp(x * beta, alpha)
}
pub fn gamma_per(p: f64, alpha: f64, beta: f64) -> f64 {
gammai_inv(p, alpha) / beta
}
pub fn gamma_ran(alpha: f64, beta: f64) -> f64 {
let (d, c, mut x, mut v, mut u): (f64, f64, f64, f64, f64);
d = alpha - 1.0/3.0;
c = 1.0/(9.0*d).sqrt();
loop {
x = normal_ran(0.0, 1.0);
v = 1.0 + c * x;
while v <= 0.0 {
x = normal_ran(0.0, 1.0);
v = 1.0 + c * x;
break;
}
v = v.powi(3);
u = random();
if u < 1.0 - 0.0331 * x.powi(4) {
return d * v / beta;
}
if u.ln() < 0.5 * x.powi(2) + d * (1.0 - v + v.ln()) {
return d * v / beta;
}
}
}
pub fn gamma_ranvec(n: u64, alpha: f64, beta: f64) -> Vec<f64> {
let mut xvec: Vec<f64> = Vec::new();
for _ in 0..n {
xvec.push(gamma_ran(alpha, beta));
}
xvec
}
pub struct GumbelDist {
pub mu: f64, pub beta: f64, }
impl GumbelDist {
pub fn pdf(&mut self, x: f64) -> f64 {
gumbel_pdf(x, self.mu, self.beta)
}
pub fn cdf(&mut self, x: f64) -> f64 {
gumbel_cdf(x, self.mu, self.beta)
}
pub fn per(&mut self, x: f64) -> f64 {
gumbel_per(x, self.mu, self.beta)
}
pub fn ran(&mut self) -> f64 {
gumbel_ran(self.mu, self.beta)
}
pub fn ranvec(&mut self, n: u64) -> Vec<f64> {
gumbel_ranvec(n, self.mu, self.beta)
}
pub fn mean(&mut self) -> f64 {
self.mu + self.beta * GAMMA
}
pub fn var(&mut self) -> f64 {
PI.powi(2)/6.0 * self.beta.powi(2)
}
pub fn sd(&mut self) -> f64 {
self.var().sqrt()
}
}
pub fn gumbel_pdf(x: f64, mu: f64, beta: f64) -> f64 {
if beta <= 0.0 {
println!("NAN produced. Error in function gumbel_pdf");
return f64::NAN;
}
1.0 / beta * (-((x-mu)/beta + (-(x-mu)/beta).exp())).exp()
}
pub fn gumbel_cdf(x: f64, mu: f64, beta: f64) -> f64 {
if beta <= 0.0 {
println!("NAN produced. Error in function gumbel_pdf");
return f64::NAN;
}
(-(-(x-mu)/beta).exp()).exp()
}
pub fn gumbel_per(p: f64, mu: f64, beta: f64) -> f64 {
mu - beta * (-p.ln()).ln()
}
pub fn gumbel_ran(mu: f64, beta: f64) -> f64 {
mu - beta * (-unif_ran(0.0,1.0).ln()).ln()
}
pub fn gumbel_ranvec(n: u64, mu: f64, beta: f64) -> Vec<f64> {
let mut xvec: Vec<f64> = Vec::new();
for _ in 0..n {
xvec.push(mu - beta * (-unif_ran(0.0,1.0).ln()).ln());
}
xvec
}
pub struct LogNormalDist {
pub mu: f64,
pub sigma: f64,
}
impl LogNormalDist {
pub fn pdf(&mut self, x: f64) -> f64 {
lognormal_pdf(x, self.mu, self.sigma)
}
pub fn cdf(&mut self, x: f64) -> f64 {
lognormal_cdf(x, self.mu, self.sigma)
}
pub fn per(&mut self, x: f64) -> f64 {
lognormal_per(x,self.mu, self.sigma)
}
pub fn ran(&mut self) -> f64 {
lognormal_ran(self.mu, self.sigma)
}
pub fn ranvec(&mut self, n: u64) -> Vec<f64> {
lognormal_ranvec(n, self.mu, self.sigma)
}
pub fn mean(&mut self) -> f64 {
(self.mu + 0.5 * self.sigma.powi(2)).exp()
}
pub fn var(&mut self) -> f64 {
(self.sigma.powi(2).exp() - 1.0) *
(2.0 * self.mu + self.sigma.powi(2)).exp()
}
pub fn sd(&mut self) -> f64 {
self.var().sqrt()
}
}
pub fn lognormal_pdf(x: f64, mu: f64, sigma: f64) -> f64 {
if sigma <= 0.0 {
println!("NAN produced. Error in function lognormal_pdf");
return f64::NAN;
}
if x <= 0.0 {
return 0.0;
}
(-(x.ln()-mu).powi(2) / (2.0*sigma.powi(2)) - x.ln() - sigma.ln() -
0.5*(2.0*PI).ln()).exp()
}
pub fn lognormal_cdf(x: f64, mu: f64, sigma: f64) -> f64 {
if sigma <= 0.0 {
println!("NAN produced. Error in function lognormal_cdf");
return f64::NAN;
}
if x <= 0.0 {
return 0.0;
}
0.5 * (1.0 + erf((x.ln() - mu)/(sigma*2.0f64.sqrt())))
}
pub fn lognormal_per(p: f64, mu: f64, sigma: f64) -> f64 {
(2f64.sqrt() * sigma * erf_inv(2.0*p-1.0) + mu).exp()
}
pub fn lognormal_ran(mu: f64, sigma: f64) -> f64 {
normal_ran(mu, sigma).exp()
}
pub fn lognormal_ranvec(n: u64, mu: f64, sigma: f64) -> Vec<f64> {
let mut xvec: Vec<f64> = Vec::new();
for _ in 0..n {
xvec.push(lognormal_ran(mu, sigma));
}
xvec
}
pub struct NormalDist {
pub mu: f64,
pub sigma: f64,
}
impl NormalDist {
pub fn pdf(&mut self, x: f64) -> f64 {
normal_pdf(x, self.mu, self.sigma)
}
pub fn cdf(&mut self, x: f64) -> f64 {
normal_cdf(x, self.mu, self.sigma)
}
pub fn per(&mut self, x: f64) -> f64 {
normal_per(x,self.mu, self.sigma)
}
pub fn ran(&mut self) -> f64 {
normal_ran(self.mu, self.sigma)
}
pub fn ranvec(&mut self, n: u64) -> Vec<f64> {
normal_ranvec(n,self.mu, self.sigma)
}
pub fn mean(&mut self) -> f64 {
self.mu
}
pub fn var(&mut self) -> f64 {
self.sigma * self.sigma
}
pub fn sd(&mut self) -> f64 {
self.sigma
}
}
pub fn normal_pdf(x: f64, mu: f64, sigma: f64) -> f64 {
if sigma <= 0.0 {
println!("NAN produced. Error in function normal_pdf");
return f64::NAN;
}
(-0.5*(2.0*PI*sigma).ln() -0.5*((x-mu)/sigma).powi(2)).exp()
}
pub fn normal_cdf(x: f64, mu: f64, sigma: f64) -> f64 {
if sigma <= 0.0 {
println!("NAN produced. Error in function normal_cdf");
return f64::NAN;
}
0.5 * (1.0 + erf(((x-mu)/sigma) / 2.0f64.sqrt()))
}
pub fn normal_per(p: f64, mu: f64, sigma: f64) -> f64 {
mu + sigma * 2.0f64.sqrt() * erf_inv(2.0*p-1.0)
}
pub fn normal_ran(mu: f64, sigma: f64) -> f64 {
if sigma <= 0.0 {
println!("Bad argument to normal_ran");
return f64::NAN;
}
let u1: f64 = random();
let u2: f64 = random();
mu + sigma * (-2.0 * u1.ln()).sqrt() * (2.0 * PI * u2).cos()
}
pub fn normal_ranvec(n: u64, mu: f64, sigma: f64) -> Vec<f64> {
if n == 0 || sigma <= 0.0 {
println!("Bad argument to normal_ranvec");
return if n == 0 { vec![] } else { vec![f64::NAN] };
}
let mut zvecthr: Vec<f64> = Vec::with_capacity(n as usize);
let niter = (n + 1) / 2;
for _ in 0..niter {
let u1: f64 = random();
let u2: f64 = random();
let r = sigma * (-2.0 * u1.ln()).sqrt();
let theta = 2.0 * PI * u2;
let z1 = mu + r * theta.cos();
let z2 = mu + r * theta.sin();
zvecthr.push(z1);
zvecthr.push(z2);
}
if n % 2 != 0 {
zvecthr.pop();
}
zvecthr
}
pub struct Pareto1Dist {
pub sigma: f64,
pub alpha: f64,
}
impl Pareto1Dist {
pub fn pdf(&mut self, x: f64) -> f64 {
pareto4_pdf(x, self.sigma, self.sigma, 1.0, self.alpha)
}
pub fn cdf(&mut self, x: f64) -> f64 {
pareto4_cdf(x, self.sigma, self.sigma, 1.0, self.alpha)
}
pub fn per(&mut self, x: f64) -> f64 {
pareto4_per(x,self.sigma, self.sigma, 1.0, self.alpha)
}
pub fn ran(&mut self) -> f64 {
pareto4_ran(self.sigma, self.sigma, 1.0, self.alpha)
}
pub fn ranvec(&mut self, n: u64) -> Vec<f64> {
pareto4_ranvec(n, self.sigma, self.sigma, 1.0, self.alpha)
}
pub fn mean(&mut self) -> f64 {
self.sigma + self.sigma * gamma(self.alpha-1.0) *
gamma(1.0 + 1.0) / gamma(self.alpha)
}
pub fn var(&mut self) -> f64 {
self.sigma.powi(2) * gamma(self.alpha - 1.0 * 2.0) *
gamma(1.0 + 1.0 * 2.0) / gamma(self.alpha) - self.mean().powi(2)
}
pub fn sd(&mut self) -> f64 {
self.var().sqrt()
}
}
pub struct Pareto2Dist {
pub mu: f64,
pub sigma: f64,
pub alpha: f64,
}
impl Pareto2Dist {
pub fn pdf(&mut self, x: f64) -> f64 {
pareto4_pdf(x, self.mu, self.sigma, 1.0, self.alpha)
}
pub fn cdf(&mut self, x: f64) -> f64 {
pareto4_cdf(x, self.mu, self.sigma, 1.0, self.alpha)
}
pub fn per(&mut self, x: f64) -> f64 {
pareto4_per(x,self.mu, self.sigma, 1.0, self.alpha)
}
pub fn ran(&mut self) -> f64 {
pareto4_ran(self.mu, self.sigma, 1.0, self.alpha)
}
pub fn ranvec(&mut self, n: u64) -> Vec<f64> {
pareto4_ranvec(n,self.mu, self.sigma, 1.0, self.alpha)
}
pub fn mean(&mut self) -> f64 {
self.mu + self.sigma * gamma(self.alpha-1.0) *
gamma(1.0 + 1.0) / gamma(self.alpha)
}
pub fn var(&mut self) -> f64 {
self.sigma.powi(2) * gamma(self.alpha - 1.0 * 2.0) *
gamma(1.0 + 1.0 * 2.0) / gamma(self.alpha) - self.mean().powi(2)
}
pub fn sd(&mut self) -> f64 {
self.var().sqrt()
}
}
pub struct Pareto3Dist {
pub mu: f64,
pub sigma: f64,
pub gamma: f64,
}
impl Pareto3Dist {
pub fn pdf(&mut self, x: f64) -> f64 {
pareto4_pdf(x, self.mu, self.sigma, self.gamma, 1.0)
}
pub fn cdf(&mut self, x: f64) -> f64 {
pareto4_cdf(x, self.mu, self.sigma, self.gamma, 1.0)
}
pub fn per(&mut self, x: f64) -> f64 {
pareto4_per(x,self.mu, self.sigma, self.gamma, 1.0)
}
pub fn ran(&mut self) -> f64 {
pareto4_ran(self.mu, self.sigma, self.gamma, 1.0)
}
pub fn ranvec(&mut self, n: u64) -> Vec<f64> {
pareto4_ranvec(n,self.mu, self.sigma, self.gamma, 1.0)
}
pub fn mean(&mut self) -> f64 {
self.mu + self.sigma * gamma(1.0-self.gamma) *
gamma(1.0 + self.gamma) / gamma(1.0)
}
pub fn var(&mut self) -> f64 {
self.sigma.powi(2) * gamma(1.0 - self.gamma * 2.0) *
gamma(1.0 + self.gamma * 2.0) / gamma(1.0) - self.mean().powi(2)
}
pub fn sd(&mut self) -> f64 {
self.var().sqrt()
}
}
pub struct Pareto4Dist {
pub mu: f64,
pub sigma: f64,
pub gamma: f64,
pub alpha: f64,
}
impl Pareto4Dist {
pub fn pdf(&mut self, x: f64) -> f64 {
pareto4_pdf(x, self.mu, self.sigma, self.gamma, self.alpha)
}
pub fn cdf(&mut self, x: f64) -> f64 {
pareto4_cdf(x, self.mu, self.sigma, self.gamma, self.alpha)
}
pub fn per(&mut self, x: f64) -> f64 {
pareto4_per(x,self.mu, self.sigma, self.gamma, self.alpha)
}
pub fn ran(&mut self) -> f64 {
pareto4_ran(self.mu, self.sigma, self.gamma, self.alpha)
}
pub fn ranvec(&mut self, n: u64) -> Vec<f64> {
pareto4_ranvec(n,self.mu, self.sigma, self.gamma, self.alpha)
}
pub fn mean(&mut self) -> f64 {
self.mu + self.sigma * gamma(self.alpha-self.gamma) *
gamma(1.0 + self.gamma) / gamma(self.alpha)
}
pub fn var(&mut self) -> f64 {
self.sigma.powi(2) * gamma(self.alpha - self.gamma * 2.0) *
gamma(1.0 + self.gamma * 2.0) / gamma(self.alpha) - self.mean().powi(2)
}
pub fn sd(&mut self) -> f64 {
self.var().sqrt()
}
}
pub fn pareto4_pdf(x: f64, mu: f64, sigma: f64, gamma: f64, alpha: f64) -> f64 {
if sigma <= 0.0 || gamma <= 0.0 || alpha <= 0.0 {
println!("NAN produced. Error in function pareto_pdf");
return f64::NAN;
}
if x < mu {
return 0.0;
}
(alpha/(gamma*sigma))*((x-mu)/sigma).powf(1.0/gamma - 1.0)*
(1.0 + ((x-mu)/sigma).powf(1.0/gamma)).powf(-alpha-1.0)
}
pub fn pareto4_cdf(x: f64, mu: f64, sigma: f64, gamma: f64, alpha: f64) -> f64 {
if sigma <= 0.0 || gamma <= 0.0 || alpha <= 0.0 {
println!("NAN produced. Error in function pareto_cdf");
return f64::NAN;
}
if x < mu {
return 0.0;
}
1.0 - (1.0 + ((x-mu)/sigma).powf(1.0/gamma)).powf(-alpha)
}
pub fn pareto4_per(p: f64, mu: f64, sigma: f64, gamma: f64, alpha: f64) -> f64 {
mu + sigma * ((1.0-p).powf(-1.0/alpha) - 1.0).powf(gamma)
}
pub fn pareto4_ran(mu: f64, sigma: f64, gamma: f64, alpha: f64) -> f64 {
mu + sigma * ((1.0-unif_ran(0.0, 1.0)).powf(-1.0/alpha) - 1.0).powf(gamma)
}
pub fn pareto4_ranvec(n: u64, mu: f64, sigma: f64, gamma: f64, alpha: f64) -> Vec<f64> {
let mut xvec: Vec<f64> = Vec::new();
for _ in 0..n {
xvec.push(pareto4_ran(mu, sigma, gamma, alpha));
}
xvec
}
pub struct TDist {
pub nu: f64,
}
impl TDist {
pub fn pdf(&mut self, x: f64) -> f64 {
t_pdf(x, self.nu)
}
pub fn cdf(&mut self, x: f64) -> f64 {
t_cdf(x, self.nu)
}
pub fn per(&mut self, p: f64) -> f64 {
t_per(p,self.nu)
}
pub fn ran(&mut self) -> f64 {
t_ran(self.nu)
}
pub fn ranvec(&mut self, n: u64) -> Vec<f64> {
t_ranvec(n, self.nu)
}
pub fn mean(&mut self) -> f64 {
0.0
}
pub fn var(&mut self) -> f64 {
if self.nu > 2.0 {
self.nu / (self.nu - 2.0)
} else {
f64::NAN
}
}
pub fn sd(&mut self) -> f64 {
if self.nu > 2.0 {
self.var().sqrt()
} else {
f64::NAN
}
}
}
pub fn t_pdf(x: f64, nu: f64) -> f64 {
if nu <= 0.0 {
println!("NAN produced. Error in function t_pdf");
return f64::NAN;
}
(gamma_ln((nu+1.0)/2.0) - ((nu+1.0)/2.0)*(1.0 + x.powi(2)/nu).ln() -
0.5*(nu * PI).ln() - gamma_ln(nu/2.0)).exp()
}
pub fn t_cdf(x: f64, nu: f64) -> f64 {
if nu <= 0.0 {
println!("NAN produced. Error in function t_cdf");
return f64::NAN;
}
if x <= 0.0 {
0.5 * betai(nu / (nu + x * x), nu / 2.0, 0.5)
} else {
1.0 - 0.5 * betai(nu / (nu + x * x), nu / 2.0, 0.5)
}
}
pub fn t_per(p: f64, nu: f64) -> f64 {
let (a, x): (f64, f64);
if p <= 0.5 {
a = betai_inv(2.0 * p, nu / 2.0, 1.0 / 2.0);
x = (nu / a - nu).sqrt();
-x
} else {
a = betai_inv(2.0 * (1.0 - p), nu / 2.0, 1.0 / 2.0);
x = (nu / a - nu).sqrt();
x
}
}
pub fn t_ran(nu: f64) -> f64 {
normal_ran(0.0, 1.0) *
(nu / gamma_ran(nu/2.0, 1.0/2.0)).sqrt()
}
pub fn t_ranvec(n: u64, nu: f64) -> Vec<f64> {
let mut xvec: Vec<f64> = Vec::new();
for _ in 0..n {
xvec.push(t_ran(nu));
}
xvec
}
pub struct UnifDist {
pub a: f64,
pub b: f64,
}
impl UnifDist {
pub fn pdf(&mut self, x: f64) -> f64 {
unif_pdf(x, self.a, self.b)
}
pub fn cdf(&mut self, x: f64) -> f64 {
unif_cdf(x, self.a, self.b)
}
pub fn per(&mut self, x: f64) -> f64 {
unif_per(x,self.a, self.b)
}
pub fn ran(&mut self) -> f64 {
unif_ran(self.a, self.b)
}
pub fn ranvec(&mut self, n: u64) -> Vec<f64> {
unif_ranvec(n, self.a, self.b)
}
pub fn mean(&mut self) -> f64 {
(self.a + self.b) / 2.0
}
pub fn var(&mut self) -> f64 {
(self.b - self.a).powi(2) / 12.0
}
pub fn sd(&mut self) -> f64 {
self.var().sqrt()
}
}
pub fn unif_pdf(x: f64, a: f64, b: f64) -> f64 {
if a >= b {
println!("NAN produced. Error in function unif_pdf");
return f64::NAN;
}
if x < a || x > b {
return 0.0;
}
1.0 / (b - a)
}
pub fn unif_cdf(x: f64, a: f64, b: f64) -> f64 {
if a >= b {
println!("NAN produced. Error in function unif_cdf");
return f64::NAN;
}
if x < a {
return 0.0;
}
if x > b {
return 1.0;
}
(x - a) / (b - a)
}
pub fn unif_per(p: f64, a: f64, b: f64) -> f64 {
if a >= b || p < 0.0 || p > 1.0 {
println!("NAN produced. Error in function unif_per");
return f64::NAN;
}
a + p * (b - a)
}
pub fn unif_ran(a: f64, b: f64) -> f64 {
let u: f64;
u = random();
a + u * (b-a)
}
pub fn unif_ranvec(n: u64, a: f64, b: f64) -> Vec<f64> {
let mut xvec: Vec<f64> = Vec::with_capacity(n as usize);
for _ in 0..n {
xvec.push(unif_ran(a, b));
}
xvec
}
pub struct BinDist {
pub n: u64,
pub p: f64,
}
impl BinDist {
pub fn pmf(&mut self, x: u64) -> f64 {
bin_pmf(x, self.n, self.p)
}
pub fn cdf(&mut self, x: u64) -> f64 {
bin_cdf(x, self.n, self.p)
}
pub fn per(&mut self, q: f64) -> u64 {
bin_per(q, self.n, self.p)
}
pub fn ran(&mut self) -> u64 {
bin_ran(self.n, self.p)
}
pub fn ranvec(&mut self, n: u64) -> Vec<u64> {
bin_ranvec(n, self.n, self.p)
}
pub fn mean(&mut self) -> f64 {
(self.n as f64) * self.p
}
pub fn var(&mut self) -> f64 {
(self.n as f64) * self.p * (1.0-self.p)
}
pub fn sd(&mut self) -> f64 {
self.var().sqrt()
}
}
pub fn bin_pmf(x: u64, n: u64, p: f64) -> f64 {
if n <= 0 || p < 0.0 || p > 1.0 {
println!("NAN produced. Error in function bin_pmf");
return f64::NAN;
}
if x > n {
return 0.0;
}
if p == 0.0 {
return if x == 0 { 1.0 } else { 0.0 };
}
if p == 1.0 {
return if x == n { 1.0 } else { 0.0 };
}
(factln_i(n) - factln_i(x) - factln_i(n-x) + x as f64 * p.ln() + (n-x) as f64 * (1.0-p).ln()).exp()
}
pub fn bin_cdf(x: u64, n: u64, p: f64) -> f64 {
if n <= 0 || p < 0.0 || p > 1.0 {
println!("NAN produced. Error in function bin_cdf");
return f64::NAN;
}
if x >= n { return 1.0; }
if p == 0.0 { return 1.0; }
if p == 1.0 { return 0.0; }
betai(1.0 - p, (n - x) as f64, (x + 1) as f64)
}
pub fn bin_per(q: f64, n: u64, p: f64) -> u64 {
if n <= 0 || p < 0.0 || p > 1.0 || q < 0.0 || q > 1.0 {
println!("NAN produced. Error in function bin_per");
return f64::NAN as u64;
}
if q == 0.0 { return 0; }
if q == 1.0 { return n; }
let mut x = 0;
let mut sum = bin_pmf(0, n, p);
while sum < q && x < n {
x += 1;
sum += bin_pmf(x, n, p);
}
x
}
pub fn bin_ran(n: u64, p: f64) -> u64 {
if n <= 0 || p < 0.0 || p > 1.0 {
println!("NAN produced. Error in function bin_ran");
return f64::NAN as u64;
}
if p == 0.0 {
return 0;
}
if p == 1.0 {
return n;
}
let u : f64;
u = unif_ran(0.0, 1.0);
let c = p / (1.0 - p);
let mut i = 0;
let mut pr = (1.0 - p).powi(n as i32);
let mut f = pr;
loop {
if u < f {
return i;
}
pr = c * ((n - i) as f64 / (i + 1) as f64) * pr;
f = f + pr;
i = i + 1;
}
}
pub fn bin_ranvec(nn: u64, n: u64, p: f64) -> Vec<u64> {
let mut xvec: Vec<u64> = Vec::new();
for _ in 0..nn {
xvec.push(bin_ran(n,p));
}
xvec
}
pub struct GeoDist {
pub p: f64,
}
impl GeoDist {
pub fn pmf(&mut self, x: u64) -> f64 {
geo_pmf(x, self.p)
}
pub fn cdf(&mut self, x: u64) -> f64 {
geo_cdf(x, self.p)
}
pub fn per(&mut self, q: f64) -> u64 {
geo_per(q, self.p)
}
pub fn ran(&mut self) -> u64 {
geo_ran(self.p)
}
pub fn ranvec(&mut self, n: u64) -> Vec<u64> {
geo_ranvec(n, self.p)
}
pub fn mean(&mut self) -> f64 {
(1.0 - self.p) / self.p
}
pub fn var(&mut self) -> f64 {
(1.0 - self.p) / self.p.powi(2)
}
pub fn sd(&mut self) -> f64 {
self.var().sqrt()
}
}
pub fn geo_pmf(x: u64, p: f64) -> f64 {
if p < 0.0 || p > 1.0 { println!("NAN produced. Error in function geo_pmf");
return f64::NAN;
}
if p == 0.0 {
return 0.0;
}
if p == 1.0 {
return if x == 0 { 1.0 } else { 0.0 };
}
(1.0-p).powi(x as i32) * p
}
pub fn geo_cdf(x: u64, p: f64) -> f64 {
if p <= 0.0 || p > 1.0 {
println!("NAN produced. Error in function geo_cdf");
return f64::NAN;
}
1.0 - (1.0 - p).powi((x + 1) as i32)
}
pub fn geo_per(q: f64, p: f64) -> u64 {
let mut x = 0;
if p <= 0.0 || p > 1.0 || q < 0.0 || q > 1.0 {
println!("NAN produced. Error in function geo1_per");
return f64::NAN as u64;
}
if q == 0.0 {
return 0;
}
if q == 1.0 {
return u64::MAX;
}
while geo_cdf(x, p) < q {
x += 1;
}
x
}
pub fn geo_ran(p: f64) -> u64 {
if p <= 0.0 || p > 1.0 {
println!("NAN produced. Error in function geo1_ran");
return f64::NAN as u64;
}
let u = unif_ran(0.0, 1.0);
(u.ln() / (1.0-p).ln()).floor() as u64
}
pub fn geo_ranvec(nn: u64, p: f64) -> Vec<u64> {
let mut xvec: Vec<u64> = Vec::new();
for _ in 0..nn {
xvec.push(geo_ran(p));
}
xvec
}
pub struct Geo2Dist {
pub p: f64,
}
impl Geo2Dist {
pub fn pmf(&mut self, x: u64) -> f64 {
geo2_pmf(x, self.p)
}
pub fn cdf(&mut self, x: u64) -> f64 {
geo2_cdf(x, self.p)
}
pub fn per(&mut self, q: f64) -> u64 {
geo2_per(q, self.p)
}
pub fn ran(&mut self) -> u64 {
geo2_ran(self.p)
}
pub fn ranvec(&mut self, n: u64) -> Vec<u64> {
geo2_ranvec(n, self.p)
}
pub fn mean(&mut self) -> f64 {
1.0 / self.p
}
pub fn var(&mut self) -> f64 {
(1.0 - self.p) / self.p.powi(2)
}
pub fn sd(&mut self) -> f64 {
self.var().sqrt()
}
}
pub fn geo2_pmf(x: u64, p: f64) -> f64 {
if p < 0.0 || p > 1.0 { println!("NAN produced. Error in function geo2_pmf");
return f64::NAN;
}
if x < 1 {
return 0.0;
}
if p == 0.0 {
return 0.0;
}
if p == 1.0 {
return if x == 1 { 1.0 } else { 0.0 };
}
(1.0-p).powi((x-1) as i32) * p
}
pub fn geo2_cdf(x: u64, p: f64) -> f64 {
if p <= 0.0 || p > 1.0 {
println!("NAN produced. Error in function geo2_cdf");
return f64::NAN;
}
if x < 1 { return 0.0; }
1.0 - (1.0 - p).powi(x as i32)
}
pub fn geo2_per(q: f64, p: f64) -> u64 {
let mut x = 1;
if p <= 0.0 || p > 1.0 || q < 0.0 || q > 1.0 {
println!("NAN produced. Error in function geo2_per");
return f64::NAN as u64;
}
if q == 0.0 {
return 1;
}
if q == 1.0 {
return u64::MAX;
}
while geo2_cdf(x, p) < q {
x += 1;
}
x
}
pub fn geo2_ran(p: f64) -> u64 {
if p <= 0.0 || p > 1.0 {
println!("NAN produced. Error in function geo2_ran");
return f64::NAN as u64;
}
let u = unif_ran(0.0, 1.0);
(u.ln() / (1.0-p).ln()).floor() as u64 + 1
}
pub fn geo2_ranvec(nn: u64, p: f64) -> Vec<u64> {
let mut xvec: Vec<u64> = Vec::new();
for _ in 0..nn {
xvec.push(geo2_ran(p));
}
xvec
}
#[allow(non_snake_case)]
pub struct HGDist {
pub n: u64,
pub N: u64,
pub M: u64,
}
impl HGDist {
pub fn pmf(&mut self, x: u64) -> f64 {
hg_pmf(x, self.n, self.N, self.M)
}
pub fn cdf(&mut self, x: u64) -> f64 {
hg_cdf(x, self.n, self.N, self.M)
}
pub fn per(&mut self, q: f64) -> u64 {
hg_per(q, self.n, self.N, self.M)
}
pub fn ran(&mut self) -> u64 {
hg_ran(self.n, self.N, self.M)
}
pub fn ranvec(&mut self, n: u64) -> Vec<u64> {
hg_ranvec(n, self.n, self.N, self.M)
}
pub fn mean(&mut self) -> f64 {
(self.n as f64) * (self.M as f64) / (self.N as f64)
}
pub fn var(&mut self) -> f64 {
(self.n as f64) *
(self.M as f64) / (self.N as f64) *
(1.0 - (self.M as f64) / (self.N as f64)) *
(self.N as f64 - self.n as f64) / (self.N as f64 - 1.0)
}
pub fn sd(&mut self) -> f64 {
self.var().sqrt()
}
}
#[allow(non_snake_case)]
pub fn hg_pmf(x: u64, n: u64, N: u64, M: u64) -> f64 {
if n < 1 || N < 1 || M > N || n > N { println!("NAN produced. Error in function hg_pmf");
return f64::NAN;
}
if x > n || x > M || (n-x) > (N-M) {
return 0.0;
}
if M == 0 {
return if x == 0 { 1.0 } else { 0.0 };
}
if M == N {
return if x == n { 1.0 } else { 0.0 };
}
(fact_ln_u(M) - fact_ln_u(x) - fact_ln_u(M-x) +
fact_ln_u(N-M) - fact_ln_u(n-x) - fact_ln_u(N-M-n+x) -
fact_ln_u(N) + fact_ln_u(n) + fact_ln_u(N-n)).exp()
}
#[allow(non_snake_case)]
pub fn hg_cdf(x: u64, n: u64, N: u64, M: u64) -> f64 {
if n < 1 || N < 1 || M < 1 || M > N || n > N {
println!("NAN produced. Error in function hg_cdf");
return f64::NAN;
}
if x > M || (n-x) > (N-M) {
return 0.0;
}
if x > n {
return 1.0;
}
let mut sum = 0.0;
for i in 0..=x {
sum += hg_pmf(i, n, N, M);
}
sum
}
#[allow(non_snake_case)]
pub fn hg_per(q: f64, n: u64, N: u64, M: u64) -> u64 {
if n < 1 || N < 1 || M > N || n > N || q < 0.0 || q > 1.0 {
println!("NAN produced. Error in function hg_per");
return f64::NAN as u64;
}
let min_x = if n > N - M { n - (N - M) } else { 0 };
let max_x = n.min(M);
if q == 0.0 { return min_x; }
if q == 1.0 { return max_x; }
let mut x = min_x;
let mut sum = hg_pmf(x, n, N, M);
while sum < q && x < max_x {
x += 1;
sum += hg_pmf(x, n, N, M);
}
x
}
#[allow(non_snake_case)]
pub fn hg_ran(n: u64, N: u64, M: u64) -> u64 {
if n < 1 || N < 1 || M > N || n > N {
println!("NAN produced. Error in function hg_ran");
return f64::NAN as u64;
}
let u = unif_ran(0.0, 1.0);
let mut x = if n > N - M { n - (N - M) } else { 0 };
while hg_cdf(x, n, N, M) < u {
x += 1;
}
x
}
#[allow(non_snake_case)]
pub fn hg_ranvec(nn: u64, n: u64, N: u64, M: u64) -> Vec<u64> {
let mut xvec: Vec<u64> = Vec::new();
for _ in 0..nn {
xvec.push(hg_ran(n,N,M));
}
xvec
}
pub struct NBDist {
pub r: u64,
pub p: f64,
}
impl NBDist {
pub fn pmf(&mut self, x: u64) -> f64 {
nb_pmf(x, self.r, self.p)
}
pub fn cdf(&mut self, x: u64) -> f64 {
nb_cdf(x, self.r, self.p)
}
pub fn per(&mut self, q: f64) -> u64 {
nb_per(q, self.r, self.p)
}
pub fn ran(&mut self) -> u64 {
nb_ran(self.r, self.p)
}
pub fn ranvec(&mut self, n: u64) -> Vec<u64> {
nb_ranvec(n, self.r, self.p)
}
pub fn mean(&mut self) -> f64 {
(self.r as f64) * (1.0 - self.p) / self.p
}
pub fn var(&mut self) -> f64 {
(self.r as f64) * (1.0 - self.p) / self.p.powi(2)
}
pub fn sd(&mut self) -> f64 {
self.var().sqrt()
}
}
pub fn nb_pmf(x: u64, r: u64, p: f64) -> f64 {
if r < 1 || p <= 0.0 || p > 1.0 {
println!("NAN produced. Error in function nb_pmf");
return f64::NAN;
}
if p == 1.0 {
return if x == 0 { 1.0 } else { 0.0 };
}
(fact_ln_u(x+r-1) - fact_ln_u(r-1) - fact_ln_u(x) + (r as f64)*p.ln() +
(x as f64)*(1.0-p).ln()).exp()
}
pub fn nb_cdf(x: u64, r: u64, p: f64) -> f64 {
if r < 1 || p <= 0.0 || p > 1.0 {
println!("NAN produced. Error in function nb_cdf");
return f64::NAN;
}
if p == 1.0 { return 1.0; }
betai(p, r as f64, (x + 1) as f64)
}
pub fn nb_per(q: f64, r: u64, p: f64) -> u64 {
if p <= 0.0 || p > 1.0 || q < 0.0 || q > 1.0 {
println!("NAN produced. Error in function nb_per");
return f64::NAN as u64;
}
if q == 0.0 { return 0; }
if q == 1.0 { return u64::MAX; }
let mut x = 0;
let mut sum = nb_pmf(x, r, p);
while sum < q {
x += 1;
sum += nb_pmf(x, r, p);
}
x
}
pub fn nb_ran(r: u64, p: f64) -> u64 {
if p <= 0.0 || p > 1.0 {
println!("NAN produced. Error in function nb_ran");
return f64::NAN as u64;
}
let mut geo_vec = Vec::new();
for _ in 0..r {
geo_vec.push(geo_ran(p));
}
geo_vec.iter().sum()
}
pub fn nb_ranvec(nn: u64, r: u64, p: f64) -> Vec<u64> {
let mut xvec: Vec<u64> = Vec::new();
for _ in 0..nn {
xvec.push(nb_ran(r,p));
}
xvec
}
pub struct NB2Dist {
pub r: u64,
pub p: f64,
}
impl NB2Dist {
pub fn pmf(&mut self, x: u64) -> f64 {
nb2_pmf(x, self.r, self.p)
}
pub fn cdf(&mut self, x: u64) -> f64 {
nb2_cdf(x, self.r, self.p)
}
pub fn per(&mut self, q: f64) -> u64 {
nb2_per(q, self.r, self.p)
}
pub fn ran(&mut self) -> u64 {
nb2_ran(self.r, self.p)
}
pub fn ranvec(&mut self, n: u64) -> Vec<u64> {
nb2_ranvec(n, self.r, self.p)
}
pub fn mean(&mut self) -> f64 {
(self.r as f64) / self.p
}
pub fn var(&mut self) -> f64 {
(self.r as f64) * (1.0 - self.p) / self.p.powi(2)
}
pub fn sd(&mut self) -> f64 {
self.var().sqrt()
}
}
pub fn nb2_pmf(x: u64, r: u64, p: f64) -> f64 {
if r < 1 || p <= 0.0 || p > 1.0 {
println!("NAN produced. Error in function nb2_pmf");
return f64::NAN;
}
if x < r {
return 0.0;
}
if p == 1.0 {
return if x == r { 1.0 } else { 0.0 };
}
(fact_ln_u(x-1) - fact_ln_u(r-1) - fact_ln_u(x-r) + (r as f64)*p.ln() +
((x-r) as f64)*(1.0-p).ln()).exp()
}
pub fn nb2_cdf(x: u64, r: u64, p: f64) -> f64 {
if r < 1 || p <= 0.0 || p > 1.0 {
println!("NAN produced. Error in function nb2_cdf");
return f64::NAN;
}
if x < r { return 0.0; }
if p == 1.0 { return 1.0; }
betai(p, r as f64, (x - r + 1) as f64)
}
pub fn nb2_per(q: f64, r: u64, p: f64) -> u64 {
if r < 1 || p <= 0.0 || p > 1.0 || q < 0.0 || q > 1.0 {
println!("NAN produced. Error in function nb2_per");
return f64::NAN as u64;
}
if q == 0.0 { return r; }
if q == 1.0 { return u64::MAX; }
let mut x = r;
let mut sum = nb2_pmf(x, r, p);
while sum < q {
x += 1;
sum += nb2_pmf(x, r, p);
}
x
}
pub fn nb2_ran(r: u64, p: f64) -> u64 {
if r < 1 || p <= 0.0 || p > 1.0 {
println!("NAN produced. Error in function nb2_ran");
return f64::NAN as u64;
}
let mut geo2_vec = Vec::new();
for _ in 0..r {
geo2_vec.push(geo2_ran(p));
}
geo2_vec.iter().sum()
}
pub fn nb2_ranvec(nn: u64, r: u64, p: f64) -> Vec<u64> {
let mut xvec: Vec<u64> = Vec::new();
for _ in 0..nn {
xvec.push(nb2_ran(r,p));
}
xvec
}
pub struct PoisDist {
pub lambda: f64,
}
impl PoisDist {
pub fn pmf(&mut self, x: u64) -> f64 {
pois_pmf(x, self.lambda)
}
pub fn cdf(&mut self, x: u64) -> f64 {
pois_cdf(x, self.lambda)
}
pub fn per(&mut self, q: f64) -> u64 {
pois_per(q, self.lambda)
}
pub fn ran(&mut self) -> u64 {
pois_ran(self.lambda)
}
pub fn ranvec(&mut self, n: u64) -> Vec<u64> {
pois_ranvec(n, self.lambda)
}
pub fn mean(&mut self) -> f64 {
self.lambda
}
pub fn var(&mut self) -> f64 {
self.lambda
}
pub fn sd(&mut self) -> f64 {
self.var().sqrt()
}
}
pub fn pois_pmf(x: u64, lambda: f64) -> f64 {
if lambda <= 0.0 {
println!("NAN produced. Error in function pois_pmf");
return f64::NAN;
}
(-lambda + (x as f64)*lambda.ln() - fact_ln_u(x)).exp()
}
pub fn pois_cdf(x: u64, lambda: f64) -> f64 {
if lambda <= 0.0 {
println!("NAN produced. Error in function pois_cdf");
return f64::NAN;
}
gammq(lambda, (x+1) as f64)
}
pub fn pois_per(q: f64, lambda: f64) -> u64 {
let mut x = 0;
if lambda <= 0.0 || q < 0.0 || q > 1.0 {
println!("NAN produced. Error in function pois_per");
return f64::NAN as u64;
}
if q == 0.0 {
return 0;
}
if q == 1.0 {
return u64::MAX;
}
while pois_cdf(x, lambda) < q {
x += 1;
}
x
}
pub fn pois_ran(lambda: f64) -> u64 {
if lambda <= 0.0 {
println!("NAN produced. Error in function pois_ran");
return f64::NAN as u64;
}
let u = unif_ran(0.0, 1.0);
let mut i = 0;
let mut p = (-lambda).exp();
let mut f = p;
loop {
if u < f {
return i;
}
p = lambda*p / (i+1) as f64;
f = f + p;
i = i + 1;
}
}
pub fn pois_ranvec(nn: u64, lambda: f64) -> Vec<u64> {
let mut xvec: Vec<u64> = Vec::new();
for _ in 0..nn {
xvec.push(pois_ran(lambda));
}
xvec
}
pub fn betai(x: f64, a: f64, b: f64) -> f64 {
let bt: f64;
if x < 0.0 || x > 1.0 {
println!("Bad x in function betai");
return f64::NAN;
}
if x == 0.0 || x == 1.0 {
bt=0.0;
}
else {
bt=(gamma_ln(a+b)-gamma_ln(a)-gamma_ln(b) +
a*x.ln() +
b*(1.0-x).ln()).exp();
}
if x < ((a + 1.0) / (a + b + 2.0)) {
bt * betacf(x, a, b) / a
} else {
1.0 - bt * betacf(1.0 - x, b, a) / b
}
}
fn betacf(x: f64, a: f64, b: f64) -> f64 {
let imax = 100;
let eps = 3.0e-7;
let fpmin = 1.0e-30;
let mut m2: u64;
let mut aa: f64;
let mut c: f64;
let mut d: f64;
let mut del: f64;
let mut h: f64;
let qab: f64;
let qam: f64;
let qap: f64;
qab=a+b;
qap=a+1.0;
qam=a-1.0;
c=1.0;
d=1.0-qab*x/qap;
if d.abs() < fpmin {
d=fpmin;
}
d=1.0/d;
h=d;
for m in 1..=imax {
m2=2*m;
aa=(m as f64)*(b-m as f64)*x/((qam+m2 as f64)*(a+m2 as f64));
d=1.0+aa*d;
if d.abs() < fpmin {
d=fpmin;
}
c=1.0+aa/c;
if c.abs() < fpmin {
c=fpmin;
}
d=1.0/d;
h *= d*c;
aa = -(a+m as f64)*(qab+m as f64)*x/((a+m2 as f64)*(qap+m2 as f64));
d=1.0+aa*d;
if d.abs() < fpmin {
d=fpmin;
}
c=1.0+aa/c;
if c.abs() < fpmin {
c=fpmin;
}
d=1.0/d;
del=d*c;
h *= del;
if (del-1.0).abs() < eps {
break;
}
}
h
}
pub fn gamma_ln(x: f64) -> f64 {
let cof = vec![57.1562356658629235,-59.5979603554754912,
14.1360979747417471,-0.491913816097620199,0.339946499848118887e-4,
0.465236289270485756e-4,-0.983744753048795646e-4,0.158088703224912494e-3,
-0.210264441724104883e-3,0.217439618115212643e-3,-0.164318106536763890e-3,
0.844182239838527433e-4,-0.261908384015814087e-4,0.368991826595316234e-5];
if x <= 0.0 {
println!("Bad argument in gamma_ln; returning f64::NAN");
return f64::NAN;
}
let mut y= x;
let z = x;
let mut tmp = z + 5.24218750000000000;
tmp = (z + 0.5) * tmp.ln() - tmp;
let mut ser = 0.999999999999997092;
for j in 0..14 {
ser += cof[j] / { y += 1.0; y};
}
tmp + (2.5066282746310005 * ser / z).ln()
}
pub fn gamma(x: f64) -> f64 {
gamma_ln(x).exp()
}
pub fn fact_i(x: u64) -> u64 {
let mut res = 1;
for i in 2..=x {
res *= i;
}
res
}
pub fn factln_i(x: u64) -> f64 {
gamma_ln(x as f64 + 1.0)
}
pub fn fact_ln_u(x: u64) -> f64 {
gamma_ln(x as f64 + 1.0)
}
pub fn fact_f(x: f64) -> f64 {
gamma(x + 1.0)
}
pub fn factln_f(x: f64) -> f64 {
gamma_ln(x + 1.0)
}
pub fn comb(n: u64, x: u64) -> f64 {
(0.5 + (factln_i(n) - factln_i(x) - factln_i(n-x)).exp()).floor()
}
pub fn combln(n: u64, x: u64) -> f64 {
factln_i(n) - factln_i(x) - factln_i(n-x)
}
pub fn beta_fn(a: f64, b:f64) -> f64 {
(gamma_ln(a) + gamma_ln(b) - gamma_ln(a+b)).exp()
}
pub fn beta_fn_ln(a: f64, b:f64) -> f64 {
gamma_ln(a) + gamma_ln(b) - gamma_ln(a+b)
}
pub fn gser(x: f64, a: f64) -> f64 {
let imax = 100;
let eps = 3.0e-7;
let gln = gamma_ln(a);
if x <= 0.0 {
if x < 0.0 {
println!("x less than 0 in routine gser");
}
return 0.0;
}
else {
let mut ap = a;
let mut del = 1.0 / a;
let mut sum = 1.0 / a;
for _ in 1..imax {
ap = ap + 1.0;
del = del * x / ap;
sum = sum + del;
if del.abs() < sum.abs() * eps {
return sum * (-x + a * x.ln() - gln).exp();
}
}
println!("a too large, ITMAX too small in routine gser");
}
0.0
}
pub fn gcf(x: f64, a: f64) -> f64 {
let imax = 100;
let eps = 3.0e-7;
let fpmin = 1.0e-30;
let gln = gamma_ln(a);
let mut b= x + 1.0 - a;
let mut c = 1.0 / fpmin;
let mut d= 1.0 / b;
let mut h= d;
let mut an: f64;
let mut del: f64;
for i in 1..=imax {
an = -(i as f64) * (i as f64 - a);
b += 2.0;
d = an * d + b;
if d.abs() < fpmin {
d = fpmin;
}
c = b + an / c;
if c.abs() < fpmin {
c=fpmin;
}
d = 1.0 / d;
del = d * c;
h *= del;
if (del-1.0).abs() < eps {
break;
}
}
(-x + a * x.ln() - gln).exp() * h
}
pub fn gcf_ln(x: f64, a: f64) -> f64 {
let imax = 100;
let eps = 3.0e-7;
let fpmin = 1.0e-30;
let gln = gamma_ln(a);
let mut b= x + 1.0 - a;
let mut c = 1.0 / fpmin;
let mut d= 1.0 / b;
let mut h= d;
let mut an: f64;
let mut del: f64;
for i in 1..=imax {
an = -(i as f64) * (i as f64 - a);
b += 2.0;
d = an * d + b;
if d.abs() < fpmin {
d = fpmin;
}
c = b + an / c;
if c.abs() < fpmin {
c=fpmin;
}
d = 1.0 / d;
del = d * c;
h *= del;
if (del-1.0).abs() < eps {
break;
}
}
(-x + a * x.ln() - gln) + h.ln()
}
pub fn gammp(x: f64, a: f64) -> f64 {
if x < 0.0 || a <= 0.0 {
println!("Invalid arguments in routine gammp");
return f64::NAN;
}
if x == 0.0 {
0.0
} else if a >= 100.0 {
return 1.0 - gammapprox(x, a); } else if x < (a + 1.0) {
return gser(x, a);
} else {
return 1.0 - gcf(x, a);
}
}
pub fn gammq(x: f64, a: f64) -> f64 {
if x < 0.0 || a <= 0.0 {
println!("Invalid arguments in routine gammq");
}
if x == 0.0 {
1.0
} else if a >= 100.0 {
gammapprox(x, a)
} else if x < (a + 1.0) {
1.0 - gser(x, a)
} else {
gcf(x, a)
}
}
pub fn gammapprox(x: f64, a: f64) -> f64 {
const Y_VEC: [f64; 18] = [
0.0021695375159141994, 0.011413521097787704,0.027972308950302116,
0.051727015600492421, 0.082502225484340941, 0.12007019910960293,
0.16415283300752470, 0.21442376986779355, 0.27051082840644336,
0.33199876341447887, 0.39843234186401943, 0.46931971407375483,
0.54413605556657973, 0.62232745288031077, 0.70331500465597174,
0.78649910768313447, 0.87126389619061517, 0.95698180152629142];
const W_VEC: [f64; 18] = [
0.0055657196642445571, 0.012915947284065419, 0.020181515297735382,
0.027298621498568734, 0.034213810770299537,0.040875750923643261,
0.047235083490265582, 0.053244713977759692,0.058860144245324798,
0.064039797355015485, 0.068745323835736408,0.072941885005653087,
0.076598410645870640, 0.079687828912071670,0.082187266704339706,
0.084078218979661945, 0.085346685739338721,0.085983275670394821];
let (xu,mut t,mut sum,ans,a1,lna1,sqrta1): (f64,f64,f64,f64,f64,f64,f64);
a1 = a-1.0;
lna1 = a1.ln();
sqrta1 = a1.sqrt();
if x > a1 {
xu = f64::max(a1 + 11.5*sqrta1, x + 6.0*sqrta1);
}
else {
xu = f64::max(0.0,f64::min(a1 - 7.5*sqrta1, x - 5.0*sqrta1));
}
sum = 0.0;
for j in 0..18 { t = x + (xu-x)*Y_VEC[j];
sum += W_VEC[j]*(-(t-a1)+a1*(t.ln()-lna1)).exp();
}
ans = sum*(xu-x)*(a1*(a1.ln()-1.0)-gamma_ln(a)).exp();
if ans >= 0.0 {
ans
} else {
1.0 + ans
}
}
pub fn erf2(x: f64) -> f64 {
if x < 0.0 {
-gammp(x * x, 0.5)
} else {
gammp(x * x, 0.5)
}
}
pub fn betai_inv(p: f64, a:f64, b: f64) -> f64 {
let eps = 1.0e-8;
let (pp,mut t,mut u,mut err,mut x,al,h,w,afac,a1,b1,lna,lnb):
(f64,f64,f64,f64,f64,f64,f64,f64,f64,f64,f64,f64,f64);
a1=a-1.0;
b1=b-1.0;
if p <= 0.0 {
return 0.;
}
else if p >= 1.0 {
return 1.0;
}
else if a >= 1.0 && b >= 1.0 {
if p < 0.5 {
pp = p
}
else {
pp = 1.0 - p;
}
t = (-2.0*pp.ln()).sqrt();
x = (2.30753 + t*0.27061) / (1.0 + t*(0.99229 + t*0.04481)) - t;
if p < 0.5 {
x = -x;
}
al = (x.powi(2)-3.0)/6.0;
h = 2.0 / (1.0/(2.0*a-1.0)+1.0/(2.0*b-1.0));
w = (x*(al+h).sqrt()/h)-(1.0/(2.0*b-1.0)-1.0/(2.0*a-1.0))*(al+5.0/6.0-2.0/(3.0*h));
x = a/(a+b*(2.0*w).exp());
}
else {
lna = (a/(a+b)).ln();
lnb = (b/(a+b)).ln();
t = (a*lna).exp()/a;
u = (b*lnb).exp()/b;
w = t + u;
if p < t/w {
x = (a*w*p).powf(1.0/a);
}
else {
x = 1.0 - (b*w*(1.-p)).powf(1.0/b);
}
}
afac = -gamma_ln(a)-gamma_ln(b)+gamma_ln(a+b);
for j in 0..10 {
if x == 0.0 || x == 1.0 {
return x;
}
err = betai(x, a, b) - p;
t = (a1 * x.ln() + b1 * (1.0 - x).ln() + afac).exp();
u = err / t;
t = u / (1.0 - 0.5 * f64::min(1.0, u * (a1 / x - b1 / (1.0 - x))));
x -= t;
if x <= 0.0 {
x = 0.5 * (x + t);
}
if x >= 1.0 {
x = 0.5 * (x + t + 1.0);
}
if t.abs() < eps*x && j>0 {
break;
}
}
x
}
pub fn gammai_inv(p: f64, alpha:f64) -> f64 {
let (mut x,mut err,mut t,mut u,pp,lna1,afac,a1): (f64,f64,f64,f64,f64,f64,f64,f64);
a1 = alpha-1.0;
let eps = 1.0e-8; let gln = gamma_ln(alpha);
if alpha <= 0.0 {
println!("a must be pos in invgammap");
}
if p >= 1.0 {
return f64::max(100.0,alpha + 100.0*alpha.sqrt());
}
if p <= 0.0 {
return 0.0;
}
lna1 = a1.ln();
afac = (a1*(lna1-1.0)-gln).exp();
if alpha > 1.0 {
if p < 0.5 {
pp = p;
}
else {
pp = 1.0 - p;
}
t = (-2.0*pp.ln()).sqrt();
x = (2.30753+t*0.27061) /
(1.0+t*(0.99229+t*0.04481)) - t;
if p < 0.5 {
x = -x;
}
x = f64::max(1.0e-3, alpha * (1.0 - 1.0 / (9.0 * alpha) - x / (3.0 * alpha.sqrt())).powi(3)); }
else {
t = 1.0 - alpha*(0.253+alpha*0.12);
if p < t {
x = (p/t).powf(1.0/alpha);
}
else {
x = 1.0-(1.0-(p-t)/(1.0-t)).ln();
}
}
for _ in 0..12 {
if x <= 0.0 {
return 0.0;
}
err = gammp(x,alpha) - p;
if alpha > 1.0 {
t = afac*(-(x-a1)+a1*(x.ln()-lna1)).exp();
}
else {
t = (-x+a1*x.ln()-gln).exp();
}
u = err/t;
t = u/(1.0-0.5*f64::min(1.0,u*((alpha-1.0)/x - 1.0)));
x -= t; if x <= 0.0 {
x = 0.5*(x + t);
} if t.abs() < eps *x {
break;
}
}
x
}
fn erfc_cheb(z: f64) -> f64 {
const NCOEF: usize = 28;
const COEF: [f64; 28] = [
-1.3026537197817094, 6.4196979235649026e-1, 1.9476473204185836e-2, -9.561514786808631e-3,
-9.46595344482036e-4, 3.66839497852761e-4, 4.2523324806907e-5, -2.0278578112534e-5,
-1.624290004647e-6, 1.303655835580e-6, 1.5626441722e-8, -8.5238095915e-8,
6.529054439e-9, 5.059343495e-9, -9.91364156e-10, -2.27365122e-10,
9.6467911e-11, 2.394038e-12, -6.886027e-12, 8.94487e-13,
3.13092e-13, -1.12708e-13, 3.81e-16, 7.106e-15,
-1.523e-15, -9.4e-17, 1.21e-16,-2.8e-17 ];
let (mut d, mut dd, t, ty, mut tmp) : (f64, f64, f64, f64, f64);
d = 0.0;
dd = 0.0;
assert!(z >= 0f64, "erfccheb requires nonnegative argument");
t = 2.0 / (2.0 + z);
ty = 4.0 * t - 2.0;
for j in (1..NCOEF-1).rev() {
tmp = d;
d = ty * d - dd + COEF[j];
dd = tmp;
}
t * (-z.powi(2) + 0.5 * (COEF[0] + ty * d) - dd).exp()
}
pub fn erf(x: f64) -> f64 {
if x >= 0.0 {
1.0 - erfc_cheb(x)
} else {
erfc_cheb(-x) - 1.0
}
}
pub fn erfc(x: f64) -> f64 {
if x >= 0.0 {
erfc_cheb(x)
} else {
2.0 - erfc_cheb(-x)
}
}
pub fn erfc_inv(p: f64) -> f64 {
let (pp, t, mut x): (f64, f64, f64);
if p >= 2.0 {
return -100.0;
}
else if p <= 0.0 {
return 100.0;
}
if p < 1.0 {
pp = p
}
else {
pp = 2.0 - p;
}
t = (-2.0 * (pp / 2.0).ln()).sqrt();
x = -std::f64::consts::FRAC_1_SQRT_2 * ((2.30753 + t * 0.27061) /
(1f64 + t * (0.99229 + t * 0.04481)) - t);
for _ in 0..2 {
let err = erfc(x) - pp;
x += err / (std::f64::consts::FRAC_2_SQRT_PI * (-x.powi(2)).exp() - x * err);
}
if p < 1.0 {
x
} else {
-x
}
}
pub fn erf_inv(p: f64) -> f64 {
erfc_inv(1.0 - p)
}
#[cfg(test)]
mod tests {
use super::*;
macro_rules! assert_approx_eq {
($a:expr, $b:expr, $eps:expr) => {{
let (a, b) = (&$a, &$b);
let diff = (*a - *b).abs();
assert!(
diff < $eps,
"Assertion failed: values not approximately equal.\n Expected: {:?}\n Actual: {:?}\n Difference: {:?}",
*a, *b, diff
);
}};
}
#[test]
fn test_gamma_large_parameter_regression() {
let alpha = 500.0;
let beta = 0.5;
let target_p = 0.2;
let x = gamma_per(target_p, alpha, beta);
assert!(x > 0.0, "Root finder failed and returned {}", x);
let calc_p = gamma_cdf(x, alpha, beta);
assert_approx_eq!(target_p, calc_p, 1e-6);
}
#[test]
fn test_distribution_percentile_roundtrips() {
let test_percentiles = vec![0.01, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99];
let tolerance = 1e-5;
for &p in &test_percentiles {
let x_beta = beta_per(p, 0.5, 2.0);
let p_beta = beta_cdf(x_beta, 0.5, 2.0);
assert_approx_eq!(p, p_beta, tolerance);
let x_norm = normal_per(p, 100.0, 16.0);
let p_norm = normal_cdf(x_norm, 100.0, 16.0);
assert_approx_eq!(p, p_norm, tolerance);
let x_exp = exp_per(p, 3.5);
let p_exp = exp_cdf(x_exp, 3.5);
assert_approx_eq!(p, p_exp, tolerance);
}
}
#[test]
fn test_chisq_large_parameter_regression() {
let nu = 500.0;
let target_p = 0.2;
let x = chisq_per(target_p, nu);
assert!(x > 0.0, "Root finder failed and returned {}", x);
let calc_p = chisq_cdf(x, nu);
assert_approx_eq!(target_p, calc_p, 1e-6);
}
#[test]
fn test_normal_ran_statistical_properties() {
let mu = 100.0;
let sigma = 16.0;
let n = 100_000;
let draws = normal_ranvec(n, mu, sigma);
let calc_mean = sample_mean(&draws);
let calc_var = sample_var(&draws);
let theoretical_var = sigma.powi(2);
assert_approx_eq!(mu, calc_mean, 0.5);
assert_approx_eq!(theoretical_var, calc_var, 3.0);
}
macro_rules! assert_approx_eq {
($a:expr, $b:expr, $eps:expr) => {{
let (a, b) = (&$a, &$b);
let diff = (*a - *b).abs();
assert!(
diff < $eps,
"Assertion failed: values not approximately equal.\n Expected: {:?}\n Actual: {:?}\n Difference: {:?}",
*a, *b, diff
);
}};
}
const TOL: f64 = 1e-6;
#[test]
fn test_beta_correctness() {
assert_approx_eq!(beta_pdf(0.5, 1.0, 1.0), 1.0, TOL);
assert_approx_eq!(beta_cdf(0.5, 1.0, 1.0), 0.5, TOL);
assert_approx_eq!(beta_per(0.5, 1.0, 1.0), 0.5, TOL);
}
#[test]
fn test_normal_correctness() {
let one_over_sqrt_2pi = 0.3989422804014327;
assert_approx_eq!(normal_pdf(0.0, 0.0, 1.0), one_over_sqrt_2pi, TOL);
assert_approx_eq!(normal_cdf(0.0, 0.0, 1.0), 0.5, TOL);
assert_approx_eq!(normal_per(0.5, 0.0, 1.0), 0.0, TOL);
let cdf_1 = normal_cdf(1.0, 0.0, 1.0);
let cdf_neg1 = normal_cdf(-1.0, 0.0, 1.0);
assert_approx_eq!(cdf_1 - cdf_neg1, 0.682689492, TOL);
}
#[test]
fn test_exponential_correctness() {
let lambda = 2.0;
let x = 1.0;
let expected_pdf = 2.0 * std::f64::consts::E.powf(-2.0);
let expected_cdf = 1.0 - std::f64::consts::E.powf(-2.0);
assert_approx_eq!(exp_pdf(x, lambda), expected_pdf, TOL);
assert_approx_eq!(exp_cdf(x, lambda), expected_cdf, TOL);
}
#[test]
fn test_uniform_correctness() {
assert_approx_eq!(unif_pdf(2.0, 1.5, 4.5), 0.333333333333, TOL);
assert_approx_eq!(unif_cdf(3.0, 1.5, 4.5), 0.5, TOL);
assert_approx_eq!(unif_per(0.5, 1.5, 4.5), 3.0, TOL);
}
#[test]
fn test_binomial_correctness() {
assert_approx_eq!(bin_pmf(5, 10, 0.5), 0.24609375, TOL);
assert_approx_eq!(bin_pmf(100, 100, 0.9), 0.9_f64.powi(100), TOL);
assert_approx_eq!(bin_cdf(100, 100, 0.9), 1.0, TOL);
}
#[test]
fn test_poisson_correctness() {
assert_approx_eq!(pois_pmf(3, 2.0), 0.180447044315, TOL);
assert_approx_eq!(pois_pmf(0, 2.0), std::f64::consts::E.powf(-2.0), TOL);
}
#[test]
fn test_geometric_correctness() {
assert_approx_eq!(geo_pmf(0, 0.05), 0.05, TOL);
assert_approx_eq!(geo_pmf(1, 0.05), 0.0475, TOL);
assert_approx_eq!(geo2_pmf(1, 0.05), 0.05, TOL);
assert_approx_eq!(geo2_pmf(2, 0.05), 0.0475, TOL);
}
#[test]
fn test_chisq_correctness() {
let x = 2.0;
let expected_pdf = 0.5 * std::f64::consts::E.powf(-1.0);
assert_approx_eq!(chisq_pdf(x, 2.0), expected_pdf, TOL);
}
#[test]
fn test_hypergeometric_correctness() {
let expected_prob = 0.000000017402868; assert_approx_eq!(hg_pmf(20, 20, 100, 50), expected_prob, TOL);
}
#[test]
fn test_gamma_correctness() {
assert_approx_eq!(gamma(5.0), 24.0, TOL);
assert_approx_eq!(gamma(6.0), 120.0, TOL);
let sqrt_pi = PI.sqrt();
assert_approx_eq!(gamma(0.5), sqrt_pi, TOL);
assert_approx_eq!(gamma_ln(5.0), 24.0_f64.ln(), TOL);
}
#[test]
fn test_factorial_correctness() {
assert_eq!(fact_i(1), 1);
assert_eq!(fact_i(5), 120);
assert_eq!(fact_i(10), 3_628_800);
assert_approx_eq!(fact_f(5.0), 120.0, TOL);
let half_fact = 0.5 * PI.sqrt();
assert_approx_eq!(fact_f(0.5), half_fact, TOL);
}
#[test]
fn test_combinations_correctness() {
assert_approx_eq!(comb(10, 5), 252.0, TOL);
assert_approx_eq!(comb(50, 2), 1225.0, TOL);
assert_approx_eq!(comb(20, 0), 1.0, TOL);
assert_approx_eq!(comb(20, 20), 1.0, TOL);
}
#[test]
fn test_beta_function_correctness() {
assert_approx_eq!(beta_fn(1.0, 1.0), 1.0, TOL);
assert_approx_eq!(beta_fn(2.0, 2.0), 1.0 / 6.0, TOL);
assert_approx_eq!(beta_fn(3.5, 7.2), beta_fn(7.2, 3.5), TOL);
}
#[test]
fn test_incomplete_beta_correctness() {
assert_approx_eq!(betai(0.25, 1.0, 1.0), 0.25, TOL);
assert_approx_eq!(betai(0.75, 1.0, 1.0), 0.75, TOL);
assert_approx_eq!(betai(0.0, 2.0, 5.0), 0.0, TOL);
assert_approx_eq!(betai(1.0, 2.0, 5.0), 1.0, TOL);
assert_approx_eq!(betai(0.5, 3.0, 3.0), 0.5, TOL);
}
#[test]
fn test_incomplete_gamma_correctness() {
let x = 1.0;
let expected = 1.0 - std::f64::consts::E.powf(-x);
assert_approx_eq!(gammp(x, 1.0), expected, TOL);
assert_approx_eq!(gammp(2.5, 3.0) + gammq(2.5, 3.0), 1.0, TOL);
}
#[test]
fn test_error_function_correctness() {
assert_approx_eq!(erf(0.0), 0.0, TOL);
assert_approx_eq!(erf(1.0), 0.8427007929497148, TOL);
assert_approx_eq!(erf(-1.0), -erf(1.0), TOL);
assert_approx_eq!(erf(0.5) + erfc(0.5), 1.0, TOL);
}
#[test]
fn test_error_function_inverses() {
let x = 0.5;
let p = erf(x);
assert_approx_eq!(erf_inv(p), x, TOL);
assert_approx_eq!(erf_inv(0.0), 0.0, TOL);
let p_comp = erfc(x);
assert_approx_eq!(erfc_inv(p_comp), x, TOL);
}
#[test]
pub fn it_works() {
println!("Testing each distribution function...");
println!("\nBeta");
println!("pdf: {}", beta_pdf(0.7, 0.5, 1.5));
println!("cdf: {}", beta_cdf(0.7, 0.5, 1.5));
println!("per: {}", beta_per(0.1, 0.5, 1.5));
println!("ran: {}", beta_ran(0.5, 1.5));
println!("ran_vec: {:?}", beta_ranvec(3, 0.5, 1.5));
let mut mybeta = BetaDist { alpha: 0.5, beta: 1.5 };
println!("pdf: {}", mybeta.pdf(0.7));
println!("cdf: {}", mybeta.cdf(0.7));
println!("per: {}", mybeta.per(0.1));
println!("ran: {}", mybeta.ran());
println!("ranvec: {:?}", mybeta.ranvec(5));
println!("mean: {}", mybeta.mean());
println!("var: {}", mybeta.var());
println!("sd: {}", mybeta.sd());
println!("---------------------");
println!("\nChi-Square");
println!("pdf: {}", chisq_pdf(0.7, 1.5));
println!("cdf: {}", chisq_cdf(0.1, 5000.0));
println!("per: {}", chisq_per(0.1, 5000.0));
println!("ran: {}", chisq_ran(1.5));
println!("ran_vec: {:?}", chisq_ranvec(3, 1.5));
let mut mychisq = ChiSqDist { nu: 1.5 };
println!("pdf: {}", mychisq.pdf(0.7));
println!("cdf: {}", mychisq.cdf(0.7));
println!("per: {}", mychisq.per(0.1));
println!("ran: {}", mychisq.ran());
println!("ranvec: {:?}", mychisq.ranvec(5));
println!("mean: {}", mychisq.mean());
println!("var: {}", mychisq.var());
println!("sd: {}", mychisq.sd());
println!("---------------------");
println!("\nExp");
println!("pdf: {}", exp_pdf(0.7, 1.5));
println!("cdf: {}", exp_cdf(0.7, 1.5));
println!("per: {}", exp_per(0.1, 1.5));
println!("ran: {}", exp_ran(1.5));
println!("ran_vec: {:?}", exp_ranvec(3, 1.5));
let mut myexp = ExpDist { lambda: 1.5 };
println!("pdf: {}", myexp.pdf(0.7));
println!("cdf: {}", myexp.cdf(0.7));
println!("per: {}", myexp.per(0.1));
println!("ran: {}", myexp.ran());
println!("ranvec: {:?}", myexp.ranvec(5));
println!("mean: {}", myexp.mean());
println!("var: {}", myexp.var());
println!("sd: {}", myexp.sd());
println!("---------------------");
println!("\nF Dist");
println!("pdf: {}", f_pdf(0.7, 1.5, 4.5));
println!("cdf: {}", f_cdf(0.7, 1.5, 4.5));
println!("per: {}", f_per(0.1, 1.5, 4.5));
println!("ran: {}", f_ran(1.5, 4.5));
println!("ran_vec: {:?}", f_ranvec(3, 1.5, 4.5));
let mut mydist = FDist { nu1: 1.5, nu2: 4.5 };
println!("pdf: {}", mydist.pdf(0.7));
println!("cdf: {}", mydist.cdf(0.7));
println!("per: {}", mydist.per(0.1));
println!("ran: {}", mydist.ran());
println!("ranvec: {:?}", mydist.ranvec(5));
println!("mean: {}", mydist.mean());
println!("var: {}", mydist.var());
println!("sd: {}", mydist.sd());
println!("---------------------");
println!("\nGamma Dist");
println!("pdf: {}", gamma_pdf(0.7, 1.5, 4.5));
println!("cdf: {}", gamma_cdf(0.7, 1.5, 4.5));
println!("per: {}", gamma_per(0.2, 500.0, 0.5));
println!("ran: {}", gamma_ran(1.5, 4.5));
println!("ran_vec: {:?}", gamma_ranvec(3, 1.5, 4.5));
let mut mydist = GammaDist { alpha: 1.5, beta: 4.5 };
println!("pdf: {}", mydist.pdf(0.7));
println!("cdf: {}", mydist.cdf(0.7));
println!("per: {}", mydist.per(0.99));
println!("ran: {}", mydist.ran());
println!("ranvec: {:?}", mydist.ranvec(5));
println!("mean: {}", mydist.mean());
println!("var: {}", mydist.var());
println!("sd: {}", mydist.sd());
println!("---------------------");
println!("\nLog-Normal");
println!("pdf: {}", lognormal_pdf(0.7, 1.5, 4.5));
println!("cdf: {}", lognormal_cdf(0.7, 1.5, 4.5));
println!("per: {}", lognormal_per(0.1, 1.5, 4.5));
println!("ran: {}", lognormal_ran(1.5, 4.5));
println!("ran_vec: {:?}", lognormal_ranvec(3, 1.5, 5.5));
let mut mydist = LogNormalDist { mu: 1.5, sigma: 4.5 };
println!("pdf: {}", mydist.pdf(0.7));
println!("cdf: {}", mydist.cdf(0.7));
println!("per: {}", mydist.per(0.99));
println!("ran: {}", mydist.ran());
println!("ranvec: {:?}", mydist.ranvec(5));
println!("mean: {}", mydist.mean());
println!("var: {}", mydist.var());
println!("sd: {}", mydist.sd());
println!("---------------------");
println!("\nNormal");
println!("pdf: {}", normal_pdf(0.7, 1.5, 4.5));
println!("cdf: {}", normal_cdf(0.7, 1.5, 4.5));
println!("per: {}", normal_per(0.1, 1.5, 4.5));
println!("ran: {}", normal_ran(1.5, 4.5));
println!("ran_vec: {:?}", normal_ranvec(3, 1.5, 4.5));
let mut mydist = NormalDist { mu: 1.5, sigma: 4.5 };
println!("pdf: {}", mydist.pdf(0.7));
println!("cdf: {}", mydist.cdf(0.7));
println!("per: {}", mydist.per(0.99));
println!("ran: {}", mydist.ran());
println!("ranvec: {:?}", mydist.ranvec(5));
println!("mean: {}", mydist.mean());
println!("var: {}", mydist.var());
println!("sd: {}", mydist.sd());
println!("---------------------");
println!("\nt Dist");
println!("pdf: {}", t_pdf(0.7, 4.5));
println!("cdf: {}", t_cdf(0.7, 4.5));
println!("per: {}", t_per(0.1, 4.5));
println!("ran: {}", t_ran(4.5));
println!("ran_vec: {:?}", t_ranvec(3, 4.5));
let mut mydist = TDist { nu: 4.5 };
println!("pdf: {}", mydist.pdf(0.7));
println!("cdf: {}", mydist.cdf(0.7));
println!("per: {}", mydist.per(0.99));
println!("ran: {}", mydist.ran());
println!("ranvec: {:?}", mydist.ranvec(5));
println!("mean: {}", mydist.mean());
println!("var: {}", mydist.var());
println!("sd: {}", mydist.sd());
println!("---------------------");
println!("\nUnif");
println!("pdf: {}", unif_pdf(1.7, 1.5, 4.5));
println!("cdf: {}", unif_cdf(1.7, 1.5, 4.5));
println!("per: {}", unif_per(0.1, 1.5, 4.5));
println!("ran: {}", unif_ran(1.5, 4.5));
println!("ran_vec: {:?}", unif_ranvec(3, 1.5, 4.5));
let mut mydist = UnifDist { a: 1.5, b: 4.5 };
println!("pdf: {}", mydist.pdf(0.7));
println!("cdf: {}", mydist.cdf(0.7));
println!("per: {}", mydist.per(0.99));
println!("ran: {}", mydist.ran());
println!("ranvec: {:?}", mydist.ranvec(5));
println!("mean: {}", mydist.mean());
println!("var: {}", mydist.var());
println!("sd: {}", mydist.sd());
println!("---------------------");
println!("\nBinomial");
println!("bin_pmf: {}", bin_pmf(99, 100, 0.9));
println!("bin_cdf: {}", bin_cdf(99, 100, 0.9));
println!("bin_per: {}", bin_per(1.0, 100, 0.9));
println!("bin_ran: {}", bin_ran(100, 0.9));
println!("ran_vec: {:?}", bin_ranvec(3, 100, 0.9));
let mut mybin = BinDist { n: 100, p: 0.9 };
println!("bin pmf: {}", mybin.pmf(80));
println!("bin cdf: {}", mybin.cdf(80));
println!("bin per: {}", mybin.per(0.99));
println!("bin ran: {}", mybin.ran());
println!("ranvec: {:?}", mybin.ranvec(5));
println!("bin mean: {}", mybin.mean());
println!("bin var: {}", mybin.var());
println!("bin sd: {}", mybin.sd());
println!("\nGeo");
println!("geo_pmf: {}", geo_pmf(0, 0.05));
println!("geo_cdf: {}", geo_cdf(0, 0.05));
println!("geo_per: {}", geo_per(1.0, 0.05));
println!("geo_ran: {}", geo_ran(0.05));
println!("ran_vec: {:?}", geo_ranvec(3, 0.05));
let mut mygeo = GeoDist { p: 0.05 };
println!("geo pmf: {}", mygeo.pmf(2));
println!("geo cdf: {}", mygeo.cdf(2));
println!("geo per: {}", mygeo.per(0.99));
println!("geo ran: {}", mygeo.ran());
println!("ranvec: {:?}", mygeo.ranvec(5));
println!("geo mean: {}", mygeo.mean());
println!("geo var: {}", mygeo.var());
println!("geo sd: {}", mygeo.sd());
println!("\nGeo2");
println!("geo2_pmf: {}", geo2_pmf(1, 0.05));
println!("geo2_cdf: {}", geo2_cdf(1, 0.05));
println!("geo2_per: {}", geo2_per(0.99, 0.05));
println!("geo2_ran: {}", geo2_ran(0.05));
println!("ran_vec: {:?}", geo2_ranvec(3, 0.05));
let mut mygeo2 = Geo2Dist { p: 0.05 };
println!("geo2 pmf: {}", mygeo2.pmf(2));
println!("geo2 cdf: {}", mygeo2.cdf(2));
println!("geo2 per: {}", mygeo2.per(0.99));
println!("geo2 ran: {}", mygeo2.ran());
println!("ranvec: {:?}", mygeo2.ranvec(5));
println!("geo2 mean: {}", mygeo2.mean());
println!("geo2 var: {}", mygeo2.var());
println!("geo2 sd: {}", mygeo2.sd());
println!("\nHG");
println!("hg_pmf: {}", hg_pmf(80, 100, 1000, 900));
println!("hg_cdf: {}", hg_cdf(80, 100, 1000, 900));
println!("hg_per: {}", hg_per(0.26, 100, 1000, 900));
println!("hg_ran: {}", hg_ran(100, 1000, 900));
println!("ran_vec: {:?}", hg_ranvec(3, 100, 1000, 900));
let mut myhg = HGDist { n: 100, N: 1000, M: 900 };
println!("hg pmf: {}", myhg.pmf(80));
println!("hg cdf: {}", myhg.cdf(80));
println!("hg per: {}", myhg.per(0.26));
println!("hg ran: {}", myhg.ran());
println!("ranvec: {:?}", myhg.ranvec(5));
println!("hg mean: {}", myhg.mean());
println!("hg var: {}", myhg.var());
println!("hg sd: {}", myhg.sd());
println!("\nNB");
println!("NB_pmf: {}", nb_pmf(10, 5, 0.1));
println!("NB_cdf: {}", nb_cdf(10, 5, 0.1));
println!("NB_per: {}", nb_per(0.0, 5, 0.1));
println!("NB_ran: {}", nb_ran(5, 0.1));
println!("ran_vec: {:?}", nb_ranvec(3, 5, 0.1));
let mut mynb = NBDist { r: 5, p: 0.1 };
println!("NB pmf: {}", mynb.pmf(2));
println!("NB cdf: {}", mynb.cdf(2));
println!("NB per: {}", mynb.per(0.99));
println!("NB ran: {}", mynb.ran());
println!("ranvec: {:?}", mynb.ranvec(5));
println!("NB mean: {}", mynb.mean());
println!("NB var: {}", mynb.var());
println!("NB sd: {}", mynb.sd());
println!("\nNB2");
println!("NB2_pmf: {}", nb2_pmf(10, 5, 0.1));
println!("NB2_cdf: {}", nb2_cdf(10, 5, 0.1));
println!("NB2_per: {}", nb2_per(1.0, 5, 0.1));
println!("NB2_ran: {}", nb2_ran(5, 0.1));
println!("ran_vec: {:?}", nb2_ranvec(3, 5, 0.1));
let mut mynb2 = NB2Dist { r: 5, p: 0.1 };
println!("NB2 pmf: {}", mynb2.pmf(2));
println!("NB2 cdf: {}", mynb2.cdf(2));
println!("NB2 per: {}", mynb2.per(0.99));
println!("NB2 ran: {}", mynb2.ran());
println!("ranvec: {:?}", mynb2.ranvec(5));
println!("NB2 mean: {}", mynb2.mean());
println!("NB2 var: {}", mynb2.var());
println!("NB2 sd: {}", mynb2.sd());
println!("\nPois");
println!("pois_pmf: {}", pois_pmf(3, 2.0));
println!("pois_cdf: {}", pois_cdf(3, 2.0));
println!("pois_per: {}", pois_per(1.0, 2.0));
println!("pois_ran: {}", pois_ran(2.0));
println!("ran_vec: {:?}", pois_ranvec(3, 2.0));
let mut mypois = PoisDist { lambda: 2.0 };
println!("pois pmf: {}", mypois.pmf(3));
println!("pois cdf: {}", mypois.cdf(3));
println!("pois per: {}", mypois.per(0.26));
println!("pois ran: {}", mypois.ran());
println!("ranvec: {:?}", mypois.ranvec(5));
println!("pois mean: {}", mypois.mean());
println!("pois var: {}", mypois.var());
println!("pois sd: {}", mypois.sd());
use crate::erf;
println!("\nerf: {}", erf(1.0));
use crate::erf2;
println!("erf2: {}", erf2(1.0));
}
}