ruststat/lib.rs
1#![doc = include_str!("../README.md")]
2
3// ==========================================
4// ==========================================
5// ruststat
6// ==========================================
7// ==========================================
8
9//! Utilities for working with many common random variables.
10//! - probability mass function (pmf), probability density function (pdf)
11//! - cumulative distribution function (cdf)
12//! - percentiles (inverse cdf)
13//! - random number generation
14//! - mean, variance
15//!
16//! Distributions:
17//! - Continuous: beta, chi-square, exponential, F, gamma, normal, log-normal, Pareto (1 thru 4),
18//! Student's t, continuous uniform
19//! - Discrete: binomial, geometric, hypergeometric, negative binomial, poisson
20//!
21//! # Quick Start
22//! ```
23//! use ruststat::*;
24//! // X~N(mu=0,sigma=1.0), find 97.5th percentile
25//! println!("normal percentile: {}", normal_per(0.975, 0.0, 1.0));
26//! // X~Bin(n=10,p=0.7), compute P(X=4)
27//! println!("binomial probability: {}", bin_pmf(4, 10, 0.7));
28//! ```
29//! For convenience, functions can also be accessed via `Structs`.
30//! ```
31//! use ruststat::*;
32//! // X~Beta(alpha=0.5,beta=2.0)
33//! let mut mybeta = BetaDist{alpha:0.5, beta:2.0};
34//! // 30th percentile
35//! println!("percentile: {}", mybeta.per(0.3));
36//! // P(X <= 0.4)
37//! println!("cdf: {}", mybeta.cdf(0.4));
38//! // Random draw
39//! println!("random draw: {}", mybeta.ran());
40//! // Variance
41//! println!("variance: {}", mybeta.var());
42//! ```
43
44// use std::collections::btree_set::Iter;
45use std::f64::consts::PI;
46use rand::{random, Rng};
47use rand::prelude::IndexedRandom;
48// use rand::prelude::IndexedRandom;
49
50const GAMMA: f64 = 0.577215664901532860606512090082;
51
52
53/// Computes sample mean of elements in a Vec
54///
55/// # Example
56/// ```
57/// use ruststat::sample_mean;
58/// let x = vec![1.5, 2.0, 3.5];
59/// println!("Sample mean: {}", sample_mean(&x));
60/// ```
61pub fn sample_mean(x: &Vec<f64>) -> f64 {
62 let x_iter= x.into_iter();
63 let n = x_iter.len();
64 let sum: f64 = x_iter.sum();
65 return sum / n as f64;
66}
67
68/// Computes sample variance of elements in a Vec
69///
70/// # Example
71/// ```
72/// use ruststat::sample_var;
73/// let x = vec![1.5, 2.0, 3.5];
74/// println!("Sample variance: {}", sample_var(&x));
75/// ```
76pub fn sample_var(x: &Vec<f64>) -> f64 {
77 let n = x.len();
78 let xbar = sample_mean(&x);
79 let ss = x.iter().map(|xx| (xx - xbar).powi(2)).sum::<f64>();
80 return ss / (n-1) as f64;
81}
82
83/// Computes sample standard deviation of elements in a Vec
84///
85/// # Example
86/// ```
87/// use ruststat::sample_sd;
88/// let x = vec![1.5, 2.0, 3.5];
89/// println!("Sample SD: {}", sample_sd(&x));
90/// ```
91pub fn sample_sd(x: &Vec<f64>) -> f64 {
92 return sample_var(&x).sqrt();
93}
94
95// ==========================================
96// ==========================================
97// ==========================================
98// Continuous RVs
99// ==========================================
100// ==========================================
101// ==========================================
102
103
104// ==========================================
105// ==========================================
106// Beta Distribution
107// ==========================================
108// ==========================================
109
110/// Struct for the beta distribution `X ~ Beta(alpha, beta)`.
111///
112/// # Parameters
113/// - `alpha > 0`
114/// - `beta > 0`
115/// # Support
116/// - `0 < x < 1`
117/// # Example
118/// Suppose `X ~ Beta(alpha=0.5, beta=2.0)`.
119/// ```
120/// use ruststat::BetaDist;
121/// let mut mybeta = BetaDist{alpha:0.5, beta:2.0};
122/// println!("Probability density function f(0.7): {}", mybeta.pdf(0.7));
123/// println!("Cumulative distribution function P(X<=0.7): {}", mybeta.cdf(0.7));
124/// println!("99th percentile: {}", mybeta.per(0.99));
125/// println!("Random draw: {}", mybeta.ran());
126/// println!("Random vector: {:?}", mybeta.ranvec(5));
127/// println!("Mean: {}", mybeta.mean());
128/// println!("Variance: {}", mybeta.var());
129/// println!("Standard deviation: {}", mybeta.sd());
130/// ```
131pub struct BetaDist {
132 pub alpha: f64,
133 pub beta: f64,
134}
135impl BetaDist {
136 pub fn pdf(&mut self, x: f64) -> f64 {
137 return beta_pdf(x, self.alpha, self.beta);
138 }
139 pub fn cdf(&mut self, x: f64) -> f64 {
140 return beta_cdf(x, self.alpha, self.beta);
141 }
142 pub fn per(&mut self, x: f64) -> f64 {
143 return beta_per(x,self.alpha, self.beta);
144 }
145 pub fn ran(&mut self) -> f64 {
146 return beta_ran(self.alpha, self.beta);
147 }
148 pub fn ranvec(&mut self, n: i32) -> Vec<f64> {
149 return beta_ranvec(n, self.alpha, self.beta);
150 }
151 pub fn mean(&mut self) -> f64 {
152 return self.alpha / (self.alpha + self.beta);
153 }
154 pub fn var(&mut self) -> f64 {
155 return self.alpha * self.beta /
156 ((self.alpha + self.beta).powi(2) * (self.alpha + self.beta + 1.0));
157 }
158 pub fn sd(&mut self) -> f64 {
159 return self.var().sqrt();
160 }
161}
162
163
164/// Computes probability density function (pdf) for `X ~ Beta(alpha, beta)`.
165///
166/// # Parameters
167/// - `alpha > 0`
168/// - `beta > 0`
169/// # Support
170/// - `0 < x < 1`
171/// # Example
172/// Suppose `X ~ Beta(alpha=0.5, beta=2.0)`.
173/// ```
174/// use ruststat::beta_pdf;
175/// println!("Probability density function f(0.7): {}", beta_pdf(0.7, 0.5, 2.0));
176/// ```
177pub fn beta_pdf(x: f64, alpha: f64, beta: f64) -> f64 {
178 if alpha <= 0.0 || beta <= 0.0 {
179 println!("NAN produced. Error in function beta_pdf");
180 return f64::NAN;
181 }
182 if x <= 0.0 || x >= 1.0 {
183 return 0.0;
184 }
185 return x.powf(alpha - 1.0) * (1.0 - x).powf(beta - 1.0) / beta_fn(alpha, beta);
186}
187
188
189/// Computes cumulative distribution function (cdf) for `X ~ Beta(alpha, beta)`.
190///
191/// # Parameters
192/// - `alpha > 0`
193/// - `beta > 0`
194/// # Support
195/// - `0 < x < 1`
196/// # Example
197/// Suppose `X ~ Beta(alpha=0.5, beta=2.0)`.
198/// ```
199/// use ruststat::beta_cdf;
200/// println!("P(X <= 0.7): {}", beta_cdf(0.7, 0.5, 2.0));
201/// ```
202pub fn beta_cdf(x: f64, alpha: f64, beta: f64) -> f64 {
203 if alpha <= 0.0 || beta <= 0.0 {
204 println!("NAN produced. Error in function beta_cdf");
205 return f64::NAN;
206 }
207 if x <= 0.0 {
208 return 0.0;
209 }
210 if x >= 1.0 {
211 return 1.0;
212 }
213 return betai(x, alpha, beta);
214}
215
216
217/// Computes a percentile for `X ~ Beta(alpha,beta)`
218/// # Note
219/// Determines the value of `x` such that `P(X <= x) = q`.
220/// # Parameters
221/// - `alpha > 0`
222/// - `beta > 0`
223/// # Support
224/// - `0 < x < 1`
225/// # Example
226/// Suppose `X ~ Beta(alpha=0.5, beta=2.0)`. To find the 80th percentile, use `q=0.80` and
227/// ```
228/// use ruststat::beta_per;
229/// println!("Percentile: {}", beta_per(0.8, 0.5, 2.0));
230/// ```
231pub fn beta_per(q: f64, alpha: f64, beta: f64) -> f64 {
232 return betai_inv(q, alpha, beta);
233
234}
235
236
237/// Random draw from `X ~ Beta(alpha,beta)` distribution.
238///
239/// # Parameters
240/// - `alpha > 0`
241/// - `beta > 0`
242/// # Support
243/// - `0 < x < 1`
244/// # Example
245/// Suppose `X ~ Beta(alpha=0.5, beta=2.0)`. Use
246/// ```
247/// use ruststat::beta_ran;
248/// println!("Random draw: {}", beta_ran(0.5, 2.0));
249/// ```
250pub fn beta_ran(alpha: f64, beta: f64) -> f64 {
251 let x = gamma_ran(alpha, 1.0);
252 let y = gamma_ran(beta, 1.0);
253 return x / (x+y);
254}
255
256
257/// Save random draws from `X ~ Beta(alpha, beta)` distribution into a `Vec`
258///
259/// # Parameters
260/// - `alpha > 0`
261/// - `beta > 0`
262/// # Support
263/// - `0 < x < 1`
264/// # Example
265/// Suppose `X ~ Beta(alpha=0.5, beta=2.0)`. Use
266/// ```
267/// use ruststat::beta_ranvec;
268/// println!("Random Vec: {:?}", beta_ranvec(10, 0.5, 2.0));
269/// ```
270pub fn beta_ranvec(n: i32, alpha: f64, beta: f64) -> Vec<f64> {
271 let mut xvec: Vec<f64> = Vec::new();
272 for _ in 0..n {
273 xvec.push(beta_ran(alpha, beta));
274 }
275 return xvec;
276}
277
278
279// ==========================================
280// ==========================================
281// ChiSquare Distribution
282// ==========================================
283// ==========================================
284
285/// Struct for the chi-square distribution `X ~ ChiSq(nu)`.
286///
287/// # Parameters
288/// - `nu > 0`
289/// # Support
290/// - `x > 0`
291/// # Example
292/// Suppose `X ~ ChiSq(nu=8.0)`. Use.
293/// ```
294/// use ruststat::ChiSqDist;
295/// let mut mychisq = ChiSqDist{nu:8.0};
296/// println!("Probability density function f(4.5): {}", mychisq.pdf(4.5));
297/// println!("Cumulative distribution function P(X<=4.5): {}", mychisq.cdf(4.5));
298/// println!("99th percentile: {}", mychisq.per(0.99));
299/// println!("Random draw: {}", mychisq.ran());
300/// println!("Random vector: {:?}", mychisq.ranvec(5));
301/// println!("Mean: {}", mychisq.mean());
302/// println!("Variance: {}", mychisq.var());
303/// println!("Standard deviation: {}", mychisq.sd());
304/// ```
305pub struct ChiSqDist {
306 pub nu: f64,
307}
308impl ChiSqDist {
309 pub fn pdf(&mut self, x: f64) -> f64 {
310 return chisq_pdf(x, self.nu);
311 }
312 pub fn cdf(&mut self, x: f64) -> f64 {
313 return chisq_cdf(x, self.nu);
314 }
315 pub fn per(&mut self, x: f64) -> f64 {
316 return chisq_per(x, self.nu);
317 }
318 pub fn ran(&mut self) -> f64 {
319 return chisq_ran(self.nu);
320 }
321 pub fn ranvec(&mut self, n: i32) -> Vec<f64> {
322 return chisq_ranvec(n, self.nu);
323 }
324 pub fn mean(&mut self) -> f64 {
325 return self.nu;
326 }
327 pub fn var(&mut self) -> f64 {
328 return 2.0 * self.nu;
329 }
330 pub fn sd(&mut self) -> f64 {
331 return self.var().sqrt();
332 }
333}
334
335
336/// Computes probability density function (pdf) for `X ~ ChiSq(nu)`.
337///
338/// # Parameters
339/// - `nu > 0`
340/// # Support
341/// - `x > 0`
342/// # Example
343/// Suppose `X ~ ChiSq(nu=8.0)`.
344/// ```
345/// use ruststat::chisq_pdf;
346/// println!("Probability density function f(5.2): {}", chisq_pdf(5.2, 8.0));
347/// ```
348pub fn chisq_pdf(x: f64, nu: f64) -> f64 {
349 if nu <= 0.0 {
350 println!("NAN produced. Error in function chisq_pdf");
351 return f64::NAN;
352 }
353 if x <= 0.0 {
354 return 0.0;
355 }
356 return gamma_pdf(x, nu/2.0,1.0/2.0);
357}
358
359
360/// Computes cumulative distribution function (cdf) for `X ~ ChiSq(nu)`.
361///
362/// # Parameters
363/// - `nu > 0`
364/// # Support
365/// - `x > 0`
366/// # Example
367/// Suppose `X ~ ChiSq(nu=8.0)`.
368/// ```
369/// use ruststat::chisq_cdf;
370/// println!("P(X<=5.2): {}", chisq_cdf(5.2, 8.0));
371/// ```
372pub fn chisq_cdf(x: f64, nu: f64) -> f64 {
373 if nu <= 0.0 {
374 println!("NAN produced. Error in function chisq_cdf");
375 return f64::NAN;
376 }
377 if x <= 0.0 {
378 return 0.0;
379 }
380 gamma_cdf(x, nu / 2.0, 0.5)
381}
382
383
384/// Computes a percentile for `X ~ ChiSq(nu)`
385/// # Note
386/// Determines the value of `x` such that `P(X <= x) = q`.
387/// # Parameters
388/// - `nu > 0`
389/// # Support
390/// - `x > 0`
391/// # Example
392/// Suppose `X ~ ChiSq(nu=8.0)`. To find the 80th percentile, use `q=0.80` and
393/// ```
394/// use ruststat::chisq_per;
395/// println!("Percentile: {}", chisq_per(0.8, 8.0));
396/// ```
397pub fn chisq_per(p: f64, nu: f64) -> f64 {
398 return gamma_per(p, nu/2.0, 1.0/2.0);
399
400 // let f = |x| { chisq_cdf(x, nu) - p};
401 // let eps = 1.0e-15;
402 // let mut convergency = SimpleConvergency { eps, max_iter:30 };
403 //
404 // let percentile = find_root_secant(eps, 1.0-eps, &f, &mut convergency);
405 //
406 // if p < 0.0 || p > 1.0 || nu <= 0.0 || percentile.is_err() {
407 // println!("Error in function gamma_percentile");
408 // return f64::NAN;
409 // }
410 //
411 // return percentile.unwrap();
412}
413
414
415/// Random draw from `X ~ ChiSq(nu)` distribution.
416///
417/// # Parameters
418/// - `nu > 0`
419/// # Support
420/// - `x > 0`
421/// # Example
422/// Suppose `X ~ ChiSq(nu=8.0)`. Use
423/// ```
424/// use ruststat::chisq_ran;
425/// println!("Random draw: {}", chisq_ran(8.0));
426/// ```
427pub fn chisq_ran(nu: f64) -> f64 {
428 return gamma_ran(nu/2.0, 1.0/2.0);
429}
430
431
432/// Save random draws from `X ~ ChiSq(nu)` into a `Vec`.
433///
434/// # Parameters
435/// - `nu > 0`
436/// # Support
437/// - `x > 0`
438/// # Example
439/// Suppose `X ~ ChiSq(nu=8.0)`. Use
440/// ```
441/// use ruststat::chisq_ranvec;
442/// println!("Random Vec: {:?}", chisq_ranvec(10, 8.0));
443/// ```
444pub fn chisq_ranvec(n: i32, nu: f64) -> Vec<f64> {
445 let mut xvec: Vec<f64> = Vec::new();
446 for _ in 0..n {
447 xvec.push(chisq_ran(nu));
448 }
449 return xvec;
450}
451
452
453// ==========================================
454// ==========================================
455// Exponential Distribution
456// ==========================================
457// ==========================================
458
459/// Struct for the exponential distribution `X ~ Exp(lambda)`.
460///
461/// # Parameters
462/// - `lambda > 0`
463/// # Support
464/// - `x > 0`
465/// # Example
466/// Suppose `X ~ Exp(lambda=3.5)`. Use.
467/// ```
468/// use ruststat::ExpDist;
469/// let mut myexp = ExpDist{lambda:3.5};
470/// println!("Probability density function f(1.2): {}", myexp.pdf(1.2));
471/// println!("Cumulative distribution function P(X<=1.2): {}", myexp.cdf(1.2));
472/// println!("99th percentile: {}", myexp.per(0.99));
473/// println!("Random draw: {}", myexp.ran());
474/// println!("Random vector: {:?}", myexp.ranvec(5));
475/// println!("Mean: {}", myexp.mean());
476/// println!("Variance: {}", myexp.var());
477/// println!("Standard deviation: {}", myexp.sd());
478/// ```
479pub struct ExpDist {
480 pub lambda: f64,
481}
482impl ExpDist {
483 pub fn pdf(&mut self, x: f64) -> f64 {
484 return exp_pdf(x, self.lambda);
485 }
486 pub fn cdf(&mut self, x: f64) -> f64 {
487 return exp_cdf(x, self.lambda);
488 }
489 pub fn per(&mut self, x: f64) -> f64 {
490 return exp_per(x, self.lambda);
491 }
492 pub fn ran(&mut self) -> f64 {
493 return exp_ran(self.lambda);
494 }
495 pub fn ranvec(&mut self, n: i32) -> Vec<f64> {
496 return exp_ranvec(n, self.lambda);
497 }
498 pub fn mean(&mut self) -> f64 {
499 return 1.0 / self.lambda;
500 }
501 pub fn var(&mut self) -> f64 {
502 return 1.0 / self.lambda.powi(2);
503 }
504 pub fn sd(&mut self) -> f64 {
505 return self.var().sqrt();
506 }
507}
508
509
510/// Computes probability density function (pdf) for `X ~ Exp(lambda)`.
511///
512/// # Parameters
513/// - `lambda > 0`
514/// # Support
515/// - `x > 0`
516/// # Example
517/// Suppose `X ~ Exp(lambda=8.0)`.
518/// ```
519/// use ruststat::exp_pdf;
520/// println!("Probability density function f(0.2): {}", exp_pdf(0.2, 8.0));
521/// ```
522pub fn exp_pdf(x: f64, lambda: f64) -> f64 {
523 if lambda <= 0.0 {
524 println!("NAN produced. Error in function exp_pdf");
525 return f64::NAN;
526 }
527 if x <= 0.0 {
528 return 0.0;
529 }
530 return lambda * (-lambda*x).exp();
531}
532
533
534/// Computes cumulative distribution function (cdf) for `X ~ Exp(lambda)`.
535///
536/// # Parameters
537/// - `lambda > 0`
538/// # Support
539/// - `x > 0`
540/// # Example
541/// Suppose `X ~ Exp(lambda=8.0)`.
542/// ```
543/// use ruststat::exp_cdf;
544/// println!("P(X<=0.8): {}", exp_cdf(0.8, 8.0));
545/// ```
546pub fn exp_cdf(x: f64, lambda: f64) -> f64 {
547 if lambda <= 0.0 {
548 println!("NAN produced. Error in function exp_cdf");
549 return f64::NAN;
550 }
551 if x <= 0.0 {
552 return 0.0;
553 }
554
555 return if x < 2.0 {
556 gser(x * lambda, 1.0)
557 } else {
558 1.0 - gcf(x * lambda, 1.0)
559 }
560}
561
562/// Computes a percentile for `X ~ Exp(lambda)`
563/// # Note
564/// Determines the value of `x` such that `P(X <= x) = q`.
565/// # Parameters
566/// - `lambda > 0`
567/// # Support
568/// - `x > 0`
569/// # Example
570/// Suppose `X ~ Exp(lambda=8.0)`. To find the 80th percentile, use `q=0.80` and
571/// ```
572/// use ruststat::exp_per;
573/// println!("Percentile: {}", exp_per(0.8, 8.0));
574/// ```
575pub fn exp_per(p: f64, lambda: f64) -> f64 {
576 return -(1.0-p).ln() / lambda;
577
578 // let f = |x| { exp_cdf(x,lambda) - p};
579 // let eps = 1.0e-15;
580 // let mut convergency = SimpleConvergency { eps, max_iter:30 };
581 //
582 // let percentile = find_root_secant(0.0, 1.0/lambda, &f, &mut convergency);
583 //
584 // if p < 0.0 || p > 1.0 || lambda <= 0.0 || percentile.is_err() {
585 // println!("Error in function ficdf");
586 // return f64::NAN;
587 // }
588 //
589 // return percentile.unwrap();
590}
591
592
593/// Random draw from `X ~ Exp(lambda)` distribution.
594///
595/// # Parameters
596/// - `lambda > 0`
597/// # Support
598/// - `x > 0`
599/// # Example
600/// Suppose `X ~ Exp(lambda=8.0)`. Use
601/// ```
602/// use ruststat::exp_ran;
603/// println!("Random draw: {}", exp_ran(8.0));
604/// ```
605pub fn exp_ran(lambda: f64) -> f64 {
606 let u: f64;
607 u = random();
608 // u = rand::thread_rng().gen();
609 return -(1.0-u).ln()/lambda;
610}
611
612
613/// Save random draws from `X ~ Exp(lambda)` into a `Vec`.
614///
615/// # Parameters
616/// - `lambda > 0`
617/// # Support
618/// - `x > 0`
619/// # Example
620/// Suppose `X ~ Exp(lambda=8.0)`. Use
621/// ```
622/// use ruststat::exp_ranvec;
623/// println!("Random vector: {:?}", exp_ranvec(10, 8.0));
624/// ```
625pub fn exp_ranvec(n: i32, lambda: f64) -> Vec<f64> {
626 let mut xvec: Vec<f64> = Vec::new();
627 for _ in 0..n {
628 xvec.push(exp_ran(lambda));
629 }
630 return xvec;
631}
632
633
634// ==========================================
635// ==========================================
636// F Distribution
637// ==========================================
638// ==========================================
639
640/// Struct for the F distribution `X ~ F(nu1, nu2)`.
641///
642/// # Parameters
643/// - `nu1 > 0`
644/// - `nu2 > 0`
645/// # Support
646/// - `x > 0`
647/// # Example
648/// Suppose `X ~ F(nu1=4.0, nu2=18.0)`. Use.
649/// ```
650/// use ruststat::FDist;
651/// let mut myf = FDist{nu1:4.0, nu2:18.0};
652/// println!("Probability density function f(2.5): {}", myf.pdf(2.5));
653/// println!("Cumulative distribution function P(X<=2.5): {}", myf.cdf(2.5));
654/// println!("99th percentile: {}", myf.per(0.99));
655/// println!("Random draw: {}", myf.ran());
656/// println!("Random vector: {:?}", myf.ranvec(5));
657/// println!("Mean: {}", myf.mean());
658/// println!("Variance: {}", myf.var());
659/// println!("Standard deviation: {}", myf.sd());
660/// ```
661pub struct FDist {
662 pub nu1: f64,
663 pub nu2: f64,
664}
665impl FDist {
666 pub fn pdf(&mut self, x: f64) -> f64 {
667 return f_pdf(x, self.nu1, self.nu2);
668 }
669 pub fn cdf(&mut self, x: f64) -> f64 {
670 return f_cdf(x, self.nu1, self.nu2);
671 }
672 pub fn per(&mut self, x: f64) -> f64 {
673 return f_per(x, self.nu1, self.nu2);
674 }
675 pub fn ran(&mut self) -> f64 {
676 return f_ran(self.nu1, self.nu2);
677 }
678 pub fn ranvec(&mut self, n: i32) -> Vec<f64> {
679 return f_ranvec(n, self.nu1, self.nu2);
680 }
681 pub fn mean(&mut self) -> f64 {
682 return self.nu2 / (self.nu2-2.0);
683 }
684 pub fn var(&mut self) -> f64 {
685 return 2.0 * self.nu2.powi(2) * (self.nu1 + self.nu2 - 2.0) /
686 (self.nu1 * (self.nu2 - 2.0).powi(2) * (self.nu2 - 4.0));
687 }
688 pub fn sd(&mut self) -> f64 {
689 return self.var().sqrt();
690 }
691}
692
693
694/// Computes probability density function (pdf) for `X ~ F(nu1, nu2)`.
695///
696/// # Parameters
697/// - `nu1 > 0`
698/// - `nu2 > 0`
699/// # Support
700/// - `x > 0`
701/// # Example
702/// Suppose `X ~ F(nu1=4.0, nu2=18.0)`. Use.
703/// ```
704/// use ruststat::f_pdf;
705/// println!("Probability density function f(2.5): {}", f_pdf(2.5, 4.0, 18.0));
706/// ```
707pub fn f_pdf(x: f64, nu1: f64, nu2: f64) -> f64 {
708 if nu1 <= 0.0 || nu2 <= 0.0 {
709 println!("NAN produced. Error in function f_pdf");
710 return f64::NAN;
711 }
712 if x <= 0.0 {
713 return 0.0;
714 }
715 return ((nu1*x).powf(nu1) * nu2.powf(nu2) / (nu1*x + nu2).powf(nu1+nu2)).sqrt() /
716 (x * beta_fn(nu1/2.0, nu2/2.0));
717}
718
719
720/// Computes cumulative distribution function (cdf) for `X ~ F(nu1, nu2)`.
721///
722/// # Parameters
723/// - `nu1 > 0`
724/// - `nu2 > 0`
725/// # Support
726/// - `x > 0`
727/// # Example
728/// Suppose `X ~ F(nu1=4.0, nu2=18.0)`. Use.
729/// ```
730/// use ruststat::f_cdf;
731/// println!("P(X<=2.5): {}", f_cdf(2.5, 4.0, 18.0));
732/// ```
733pub fn f_cdf(x: f64, nu1: f64, nu2: f64) -> f64 {
734 if nu1 <= 0.0 || nu2 <= 0.0 {
735 println!("NAN produced. Error in function f_cdf");
736 return f64::NAN;
737 }
738 if x <= 0.0 {
739 return 0.0;
740 }
741 return 1.0 - betai(nu2 / (nu2 + nu1 * x), nu2 / 2.0, nu1 / 2.0);
742}
743
744
745/// Computes a percentile for `X ~ F(nu1, nu2)`.
746///
747/// # Note
748/// Determines the value of `x` such that `P(X <= x) = q`.
749/// # Parameters
750/// - `nu1 > 0`
751/// - `nu2 > 0`
752/// # Support
753/// - `x > 0`
754/// # Example
755/// Suppose `X ~ F(nu1=4.0, nu2=18.0)`. To find the 80th percentile, use `q=0.80` and
756/// ```
757/// use ruststat::f_per;
758/// println!("Percentile: {}", f_per(0.8, 4.0, 18.0));
759/// ```
760pub fn f_per(p: f64, nu1: f64, nu2: f64) -> f64 {
761 return nu2/nu1 * (1.0 / beta_per(1.0-p,nu2/2.0,nu1/2.0) - 1.0);
762 // let f = |x| { f_cdf(x,nu1, nu2) - p};
763 // let eps = 1.0e-30;
764 // let mut convergency = SimpleConvergency { eps, max_iter:30 };
765 //
766 // let percentile = find_root_secant(0f64, 1f64, &f, &mut convergency);
767 //
768 // if p < 0.0 || p > 1.0 || nu1 <= 0.0 || nu2 <= 0.0 || percentile.is_err() {
769 // println!("Error in function ficdf");
770 // return f64::NAN;
771 // }
772 //
773 // return percentile.unwrap();
774}
775
776
777/// Random draw from `X ~ F(nu1, nu2)` distribution.
778///
779/// # Parameters
780/// - `nu1 > 0`
781/// - `nu2 > 0`
782/// # Support
783/// - `x > 0`
784/// # Example
785/// Suppose `X ~ F(nu1=4.0, nu2=18.0)`. Use
786/// ```
787/// use ruststat::f_ran;
788/// println!("Random draw: {}", f_ran(4.0, 18.0));
789/// ```
790pub fn f_ran(nu1: f64, nu2: f64) -> f64 {
791 let x = beta_ran(nu1/2.0, nu2/2.0);
792 return nu2 * x / (nu1 * (1.0-x));
793}
794
795/// Save random draws from `X ~ F(nu1, nu2)` distribution into a `Vec`
796///
797/// # Parameters
798/// - `nu1 > 0`
799/// - `nu2 > 0`
800/// # Support
801/// - `x > 0`
802/// # Example
803/// Suppose `X ~ F(alpha=4.0, beta=18.0)`. Use
804/// ```
805/// use ruststat::f_ranvec;
806/// println!("Random Vec: {:?}", f_ranvec(10, 4.0, 18.0));
807/// ```
808pub fn f_ranvec(n: i32, nu1: f64, nu2: f64) -> Vec<f64> {
809 let mut xvec: Vec<f64> = Vec::new();
810 for _ in 0..n {
811 xvec.push(f_ran(nu1, nu2));
812 }
813 return xvec;
814}
815
816
817// ==========================================
818// ==========================================
819// Gamma Distribution
820// ==========================================
821// ==========================================
822
823/// Struct for the gamma distribution `X ~ Gamma(alpha, beta)`.
824///
825/// # Parameters
826/// - `alpha > 0`
827/// - `beta > 0`
828/// # Support
829/// - `x > 0`
830/// # Example
831/// Suppose `X ~ Gamma(alpha=4.0, beta=2.7)`. Use.
832/// ```
833/// use ruststat::GammaDist;
834/// let mut mygamma = GammaDist{alpha:4.0, beta:2.7};
835/// println!("Probability density function f(3.9): {}", mygamma.pdf(3.9));
836/// println!("Cumulative distribution function P(X<=3.9): {}", mygamma.cdf(3.9));
837/// println!("99th percentile: {}", mygamma.per(0.99));
838/// println!("Random draw: {}", mygamma.ran());
839/// println!("Random vector: {:?}", mygamma.ranvec(5));
840/// println!("Mean: {}", mygamma.mean());
841/// println!("Variance: {}", mygamma.var());
842/// println!("Standard deviation: {}", mygamma.sd());
843/// ```
844pub struct GammaDist {
845 pub alpha: f64,
846 pub beta: f64,
847}
848impl GammaDist {
849 pub fn pdf(&mut self, x: f64) -> f64 {
850 return gamma_pdf(x, self.alpha, self.beta);
851 }
852 pub fn cdf(&mut self, x: f64) -> f64 {
853 return gamma_cdf(x, self.alpha, self.beta);
854 }
855 pub fn per(&mut self, x: f64) -> f64 {
856 return gamma_per(x, self.alpha, self.beta);
857 }
858 pub fn ran(&mut self) -> f64 {
859 return gamma_ran(self.alpha, self.beta);
860 }
861 pub fn ranvec(&mut self, n: i32) -> Vec<f64> {
862 return gamma_ranvec(n, self.alpha, self.beta);
863 }
864 pub fn mean(&mut self) -> f64 {
865 return self.alpha / self.beta;
866 }
867 pub fn var(&mut self) -> f64 {
868 return self.alpha / self.beta.powi(2);
869 }
870 pub fn sd(&mut self) -> f64 {
871 return self.var().sqrt();
872 }
873}
874
875
876/// Computes probability density function (pdf) for `X ~ Gamma(alpha, beta)`.
877///
878/// # Parameters
879/// - `alpha > 0`
880/// - `beta > 0`
881/// # Support
882/// - `x > 0`
883/// # Example
884/// Suppose `X ~ Gamma(alpha=4.0, beta=2.7)`. Use.
885/// ```
886/// use ruststat::gamma_pdf;
887/// println!("Probability density function f(3.9): {}", gamma_pdf(3.9, 4.0, 2.7));
888pub fn gamma_pdf(x: f64, alpha: f64, beta: f64) -> f64 {
889 if alpha <= 0.0 || beta <= 0.0 {
890 println!("NAN produced. Error in function gamma_pdf");
891 return f64::NAN;
892 }
893 if x <= 0.0 {
894 return 0.0;
895 }
896 return beta.powf(alpha) / gamma(alpha) * x.powf(alpha-1.0) * (-beta*x).exp();
897}
898
899
900/// Computes cumulative distribution function (cdf) for `X ~ Gamma(alpha, beta)`.
901///
902/// # Parameters
903/// - `alpha > 0`
904/// - `beta > 0`
905/// # Support
906/// - `x > 0`
907/// # Example
908/// Suppose `X ~ Gamma(alpha=4.0, beta=2.7)`. Use.
909/// ```
910/// use ruststat::gamma_cdf;
911/// println!("P(X<=3.9): {}", gamma_cdf(3.9, 4.0, 2.7));
912/// ```
913pub fn gamma_cdf(x: f64, alpha: f64, beta: f64) -> f64 {
914 if alpha <= 0.0 || beta <= 0.0 {
915 println!("NAN produced. Error in function gamma_pdf");
916 return f64::NAN;
917 }
918 if x <= 0.0 {
919 return 0.0;
920 }
921
922 return if x < (alpha + 1.0) {
923 gser(x * beta, alpha)
924 } else {
925 1.0 - gcf(x * beta, alpha)
926 }
927}
928
929
930/// Computes a percentile for `X ~ Gamma(alpha, beta)`.
931///
932/// # Note
933/// Determines the value of `x` such that `P(X <= x) = q`.
934/// # Parameters
935/// - `alpha > 0`
936/// - `beta > 0`
937/// # Support
938/// - `x > 0`
939/// # Example
940/// Suppose `X ~ Gamma(alpha=4.0, beta=2.7)`. To find the 80th percentile, use `q=0.80` and
941/// ```
942/// use ruststat::gamma_per;
943/// println!("Percentile: {}", gamma_per(0.8, 4.0, 2.7));
944/// ```
945pub fn gamma_per(p: f64, alpha: f64, beta: f64) -> f64 {
946 return gammai_inv(p, alpha) / beta;
947 // let f = |x| { gamma_cdf(x,a,b) - p};
948 // let eps = 1.0e-15;
949 // let mut convergency = SimpleConvergency { eps, max_iter:30 };
950 //
951 // let percentile = find_root_secant(eps, a/b, &f, &mut convergency);
952 //
953 // if p < 0.0 || p > 1.0 || a <= 0.0 || b <= 0.0 ||percentile.is_err() {
954 // println!("Error in function gamma_percentile");
955 // return f64::NAN;
956 // }
957 //
958 // return percentile.unwrap();
959}
960
961
962/// Random draw from `X ~ Gamma(alpha, beta)` distribution.
963///
964/// # Parameters
965/// - `alpha > 0`
966/// - `beta > 0`
967/// # Support
968/// - `x > 0`
969/// # Example
970/// Suppose `X ~ Gamma(alpha=4.0, beta=2.7)`. Use
971/// ```
972/// use ruststat::gamma_ran;
973/// println!("Random draw: {}", gamma_ran(4.0, 2.7));
974/// ```
975pub fn gamma_ran(alpha: f64, beta: f64) -> f64 {
976
977 let (d, c, mut x, mut v, mut u): (f64, f64, f64, f64, f64);
978 d = alpha - 1.0/3.0;
979 c = 1.0/(9.0*d).sqrt();
980
981 loop {
982 x = normal_ran(0.0, 1.0);
983 v = 1.0 + c * x;
984 while v <= 0.0 {
985 x = normal_ran(0.0, 1.0);
986 v = 1.0 + c * x;
987 break;
988 }
989
990 v = v.powi(3);
991 u = random();
992 // u = rand::thread_rng().gen();
993
994 if u < 1.0 - 0.0331 * x.powi(4) {
995 return d * v / beta;
996 }
997 if u.ln() < 0.5 * x.powi(2) + d * (1.0 - v + v.ln()) {
998 return d * v / beta;
999 }
1000 }
1001}
1002
1003
1004/// Save random draws from `X ~ Gamma(alpha, beta)` distribution into a `Vec`
1005///
1006/// # Parameters
1007/// - `alpha > 0`
1008/// - `beta > 0`
1009/// # Support
1010/// - `x > 0`
1011/// # Example
1012/// Suppose `X ~ Gamma(alpha=4.0, beta=2.7)`. Use
1013/// ```
1014/// use ruststat::gamma_ranvec;
1015/// println!("Random Vec: {:?}", gamma_ranvec(10, 4.0, 2.7));
1016/// ```
1017pub fn gamma_ranvec(n: i32, alpha: f64, beta: f64) -> Vec<f64> {
1018 let mut xvec: Vec<f64> = Vec::new();
1019 for _ in 0..n {
1020 xvec.push(gamma_ran(alpha, beta));
1021 }
1022 return xvec;
1023}
1024
1025
1026// ==========================================
1027// ==========================================
1028// Gumbel Distribution
1029// ==========================================
1030// ==========================================
1031
1032/// Struct for the Gumbel distribution `X ~ Gumbel(mu, beta)`.
1033///
1034/// # Parameters
1035/// - Location: `-infinity < mu < infinity`
1036/// - Scale: `beta > 0`
1037/// # Support
1038/// - `-infinity < x < infinity`
1039/// # Example
1040/// Suppose `X ~ Gumbel(mu=4.2, beta=1.8)`. Use.
1041/// ```
1042/// use ruststat::GumbelDist;
1043/// let mut mygum = GumbelDist{mu:4.2, beta:1.8};
1044/// println!("Probability density function f(3.9): {}", mygum.pdf(3.9));
1045/// println!("Cumulative distribution function P(X<=3.9): {}", mygum.cdf(3.9));
1046/// println!("99th percentile: {}", mygum.per(0.99));
1047/// println!("Random draw: {}", mygum.ran());
1048/// println!("Random vector: {:?}", mygum.ranvec(5));
1049/// println!("Mean: {}", mygum.mean());
1050/// println!("Variance: {}", mygum.var());
1051/// println!("Standard deviation: {}", mygum.sd());
1052/// ```
1053pub struct GumbelDist {
1054 pub mu: f64, //location
1055 pub beta: f64, //scale
1056}
1057impl GumbelDist {
1058 pub fn pdf(&mut self, x: f64) -> f64 {
1059 return gumbel_pdf(x, self.mu, self.beta);
1060 }
1061 pub fn cdf(&mut self, x: f64) -> f64 {
1062 return gumbel_cdf(x, self.mu, self.beta);
1063 }
1064 pub fn per(&mut self, x: f64) -> f64 {
1065 return gumbel_per(x, self.mu, self.beta);
1066 }
1067 pub fn ran(&mut self) -> f64 {
1068 return gumbel_ran(self.mu, self.beta);
1069 }
1070 pub fn ranvec(&mut self, n: i32) -> Vec<f64> {
1071 return gumbel_ranvec(n, self.mu, self.beta);
1072 }
1073 pub fn mean(&mut self) -> f64 {
1074 return self.mu + self.beta * GAMMA;
1075 }
1076 pub fn var(&mut self) -> f64 {
1077 return PI.powi(2)/6.0 * self.beta.powi(2);
1078 }
1079 pub fn sd(&mut self) -> f64 {
1080 return self.var().sqrt();
1081 }
1082}
1083
1084
1085/// Computes probability density function (pdf) for `X ~ Gumbel(mu, beta)`.
1086///
1087/// # Parameters
1088/// - Location: `-infinity < mu < infinity`
1089/// - Scale: `beta > 0`
1090/// # Support
1091/// - `-infinity < x < infinity`
1092/// # Example
1093/// Suppose `X ~ Gumbel(mu=5.5, beta=2.0)`. Use.
1094/// ```
1095/// use ruststat::gumbel_pdf;
1096/// println!("Probability density function f(3.9): {}", gumbel_pdf(3.9, 5.5, 2.0));
1097pub fn gumbel_pdf(x: f64, mu: f64, beta: f64) -> f64 {
1098 if beta <= 0.0 {
1099 println!("NAN produced. Error in function gumbel_pdf");
1100 return f64::NAN;
1101 }
1102 return 1.0 / beta * (-((x-mu)/beta + (-(x-mu)/beta).exp())).exp();
1103}
1104
1105
1106/// Computes cumulative distribution function (cdf) for `X ~ Gumbel(mu, beta)`.
1107///
1108/// # Parameters
1109/// - Location: `-infinity < mu < infinity`
1110/// - Scale: `beta > 0`
1111/// # Support
1112/// - `-infinity < x < infinity`
1113/// # Example
1114/// Suppose `X ~ Gumbel(mu=5.5, beta=2.0)`. Use.
1115/// ```
1116/// use ruststat::gumbel_cdf;
1117/// println!("P(X<=3.9): {}", gumbel_cdf(3.9, 5.5, 2.0));
1118/// ```
1119pub fn gumbel_cdf(x: f64, mu: f64, beta: f64) -> f64 {
1120 if beta <= 0.0 {
1121 println!("NAN produced. Error in function gumbel_pdf");
1122 return f64::NAN;
1123 }
1124
1125 return (-(-(x-mu)/beta).exp()).exp();
1126}
1127
1128
1129/// Computes a percentile for `X ~ Gumbel(mu, beta)`.
1130///
1131/// # Note
1132/// Determines the value of `x` such that `P(X <= x) = q`.
1133/// # Parameters
1134/// - Location: `-infinity < mu < infinity`
1135/// - Scale: `beta > 0`
1136/// # Support
1137/// - `-infinity < x < infinity`
1138/// # Example
1139/// Suppose `X ~ Gumbel(mu=5.5, beta=2.0)`. To find the 80th percentile, use `q=0.80` and
1140/// ```
1141/// use ruststat::gumbel_per;
1142/// println!("Percentile: {}", gumbel_per(0.8, 5.5, 2.0));
1143/// ```
1144pub fn gumbel_per(p: f64, mu: f64, beta: f64) -> f64 {
1145 return mu - beta * (-p.ln()).ln();
1146}
1147
1148
1149/// Random draw from `X ~ Gumbel(mu, beta)` distribution.
1150///
1151/// # Parameters
1152/// - Location: `-infinity < mu < infinity`
1153/// - Scale: `beta > 0`
1154/// # Support
1155/// - `-infinity < x < infinity`
1156/// # Example
1157/// Suppose `X ~ Gumbel(mu=5.5, beta=2.0)`. Use
1158/// ```
1159/// use ruststat::gumbel_ran;
1160/// println!("Random draw: {:?}", gumbel_ran(5.5, 2.0));
1161/// ```
1162pub fn gumbel_ran(mu: f64, beta: f64) -> f64 {
1163 return mu - beta * (-unif_ran(0.0,1.0).ln()).ln();
1164}
1165
1166
1167/// Random Vector taken from `X ~ Gumbel(mu, beta)` distribution.
1168///
1169/// # Parameters
1170/// - Location: `-infinity < mu < infinity`
1171/// - Scale: `beta > 0`
1172/// # Support
1173/// - `-infinity < x < infinity`
1174/// # Example
1175/// Suppose `X ~ Gumbel(mu=5.5, beta=2.0)`. Use
1176/// ```
1177/// use ruststat::gumbel_ranvec;
1178/// println!("Random Vec: {:?}", gumbel_ranvec(10, 5.5, 2.0));
1179/// ```
1180pub fn gumbel_ranvec(n: i32, mu: f64, beta: f64) -> Vec<f64> {
1181 let mut xvec: Vec<f64> = Vec::new();
1182 for _ in 0..n {
1183 xvec.push(mu - beta * (-unif_ran(0.0,1.0).ln()).ln());
1184 }
1185 return xvec;
1186}
1187
1188
1189// ==========================================
1190// ==========================================
1191// LogNormal Distribution
1192// ==========================================
1193// ==========================================
1194
1195/// Struct for the log-normal distribution `X ~ LogNormal(mu, sigma)`.
1196///
1197/// # Parameters
1198/// - `-infinity < mu < infinity`
1199/// - `sigma > 0`
1200/// # Support
1201/// - `x > 0`
1202/// # Example
1203/// Suppose `X ~ LogNormal(mu=0.0, sigma=1.0)`. Use
1204/// ```
1205/// use ruststat::LogNormalDist;
1206/// let mut mylogn = LogNormalDist{mu:0.0, sigma:1.0};
1207/// println!("Probability density function f(5.2): {}", mylogn.pdf(5.2));
1208/// println!("Cumulative distribution function P(X<=5.2): {}", mylogn.cdf(5.2));
1209/// println!("99th percentile: {}", mylogn.per(0.99));
1210/// println!("Random draw: {}", mylogn.ran());
1211/// println!("Random vector: {:?}", mylogn.ranvec(5));
1212/// println!("Mean: {}", mylogn.mean());
1213/// println!("Variance: {}", mylogn.var());
1214/// println!("Standard deviation: {}", mylogn.sd());
1215/// ```
1216pub struct LogNormalDist {
1217 pub mu: f64,
1218 pub sigma: f64,
1219}
1220impl LogNormalDist {
1221 pub fn pdf(&mut self, x: f64) -> f64 {
1222 return lognormal_pdf(x, self.mu, self.sigma);
1223 }
1224 pub fn cdf(&mut self, x: f64) -> f64 {
1225 return lognormal_cdf(x, self.mu, self.sigma);
1226 }
1227 pub fn per(&mut self, x: f64) -> f64 {
1228 return lognormal_per(x,self.mu, self.sigma);
1229 }
1230 pub fn ran(&mut self) -> f64 {
1231 return lognormal_ran(self.mu, self.sigma);
1232 }
1233 pub fn ranvec(&mut self, n: i32) -> Vec<f64> {
1234 return lognormal_ranvec(n, self.mu, self.sigma);
1235 }
1236 pub fn mean(&mut self) -> f64 {
1237 return (self.mu + 0.5 * self.sigma.powi(2)).exp();
1238 }
1239 pub fn var(&mut self) -> f64 {
1240 return (self.sigma.powi(2).exp() - 1.0) *
1241 (2.0 * self.mu + self.sigma.powi(2)).exp();
1242 }
1243 pub fn sd(&mut self) -> f64 {
1244 return self.var().sqrt();
1245 }
1246}
1247
1248
1249/// Computes probability density function (pdf) for `X ~ LogNormal(mu, sigma)`.
1250///
1251/// # Parameters
1252/// - `-infinity < mu < infinity`
1253/// - `sigma > 0`
1254/// # Support
1255/// - `x > 0`
1256/// # Example
1257/// Suppose `X ~ LogNormal(mu=0.0, sigma=1.0)`. Use.
1258/// ```
1259/// use ruststat::lognormal_pdf;
1260/// println!("Probability density function f(2.1): {}", lognormal_pdf(2.0, 0.0, 1.0));
1261pub fn lognormal_pdf(x: f64, mu: f64, sigma: f64) -> f64 {
1262 if sigma <= 0.0 {
1263 println!("NAN produced. Error in function lognormal_pdf");
1264 return f64::NAN;
1265 }
1266 if x <= 0.0 {
1267 return 0.0;
1268 }
1269 return (-(x.ln()-mu).powi(2) / (2.0*sigma.powi(2))).exp() /
1270 (x * sigma * (2.0 * PI).sqrt());
1271}
1272
1273
1274/// Computes cumulative distribution function (cdf) for `X ~ LogNormal(mu, sigma)`.
1275///
1276/// # Parameters
1277/// - `-infinity < mu < infinity`
1278/// - `sigma > 0`
1279/// # Support
1280/// - `x > 0`
1281/// # Example
1282/// Suppose `X ~ LogNormal(mu=0.0, sigma=1.0)`. Use.
1283/// ```
1284/// use ruststat::lognormal_cdf;
1285/// println!("P(X<=2.1): {}", lognormal_cdf(2.0, 0.0, 1.0));
1286/// ```
1287pub fn lognormal_cdf(x: f64, mu: f64, sigma: f64) -> f64 {
1288 if sigma <= 0.0 {
1289 println!("NAN produced. Error in function lognormal_cdf");
1290 return f64::NAN;
1291 }
1292 if x <= 0.0 {
1293 return 0.0;
1294 }
1295
1296 return 0.5 * (1.0 + erf((x.ln() - mu)/(sigma*2.0f64.sqrt())));
1297}
1298
1299
1300/// Computes a percentile for `X ~ LogNormal(mu, sigma)`.
1301///
1302/// # Note
1303/// Determines the value of `x` such that `P(X <= x) = q`.
1304/// # Parameters
1305/// - `-infinity < mu < infinity`
1306/// - `sigma > 0`
1307/// # Support
1308/// - `x > 0`
1309/// # Example
1310/// Suppose `X ~ LogNormal(mu=0.0, sigma=1.0)`. To find the 80th percentile, use `q=0.80` and
1311/// ```
1312/// use ruststat::lognormal_per;
1313/// println!("Percentile: {}", lognormal_per(0.8, 0.0, 1.0));
1314/// ```
1315pub fn lognormal_per(p: f64, mu: f64, sigma: f64) -> f64 {
1316 return (2f64.sqrt() * sigma * erf_inv(2.0*p-1.0) + mu).exp();
1317}
1318
1319
1320/// Random draw from `X ~ LogNormal(mu, sig)` distribution.
1321///
1322/// # Parameters
1323/// - `-infinity < mu < infinity`
1324/// - `sigma > 0`
1325/// # Support
1326/// - `x > 0`
1327/// # Example
1328/// Suppose `X ~ LogNormal(mu=0.0, sigma=1.0)`. Use
1329/// ```
1330/// use ruststat::lognormal_ran;
1331/// println!("Random draw: {}", lognormal_ran(0.0, 1.0));
1332/// ```
1333pub fn lognormal_ran(mu: f64, sigma: f64) -> f64 {
1334 return normal_ran(mu, sigma).exp();
1335}
1336
1337
1338/// Save random draws from `X ~ LogNormal(mu, sigma)` distribution into a `Vec`
1339///
1340/// # Parameters
1341/// - `-infinity < mu < infinity`
1342/// - `sigma > 0`
1343/// # Support
1344/// - `x > 0`
1345/// # Example
1346/// Suppose `X ~ LogNormal(mu=0.0, sigma=1.0)`. Use
1347/// ```
1348/// use ruststat::lognormal_ranvec;
1349/// println!("Random Vec: {:?}", lognormal_ranvec(10, 0.5, 2.0));
1350/// ```
1351pub fn lognormal_ranvec(n: i32, mu: f64, sigma: f64) -> Vec<f64> {
1352 let mut xvec: Vec<f64> = Vec::new();
1353 for _ in 0..n {
1354 xvec.push(lognormal_ran(mu, sigma));
1355 }
1356 return xvec;
1357}
1358
1359
1360// ==========================================
1361// ==========================================
1362// Normal Distribution
1363// ==========================================
1364// ==========================================
1365
1366/// Struct for the normal distribution `X ~ Normal(mu, sigma)`.
1367///
1368/// # Parameters
1369/// - `-infinity < mu < infinity`
1370/// - `sigma > 0`
1371/// # Support
1372/// - `-infinity < x < infinity`
1373/// # Example
1374/// Suppose `X ~ Normal(mu=100.0, sigma=16.0)`. Use
1375/// ```
1376/// use ruststat::NormalDist;
1377/// let mut mynormal = NormalDist{mu:100.0, sigma:16.0};
1378/// println!("Probability density function f(110.0): {}", mynormal.pdf(110.0));
1379/// println!("Cumulative distribution function P(X<=110.0): {}", mynormal.cdf(110.0));
1380/// println!("99th percentile: {}", mynormal.per(0.99));
1381/// println!("Random draw: {}", mynormal.ran());
1382/// println!("Random vector: {:?}", mynormal.ranvec(5));
1383/// println!("Mean: {}", mynormal.mean());
1384/// println!("Variance: {}", mynormal.var());
1385/// println!("Standard deviation: {}", mynormal.sd());
1386/// ```
1387pub struct NormalDist {
1388 pub mu: f64,
1389 pub sigma: f64,
1390}
1391impl NormalDist {
1392 pub fn pdf(&mut self, x: f64) -> f64 {
1393 return normal_pdf(x, self.mu, self.sigma);
1394 }
1395 pub fn cdf(&mut self, x: f64) -> f64 {
1396 return normal_cdf(x, self.mu, self.sigma);
1397 }
1398 pub fn per(&mut self, x: f64) -> f64 {
1399 return normal_per(x,self.mu, self.sigma);
1400 }
1401 pub fn ran(&mut self) -> f64 {
1402 return normal_ran(self.mu, self.sigma);
1403 }
1404 pub fn ranvec(&mut self, n: i32) -> Vec<f64> {
1405 return normal_ranvec(n,self.mu, self.sigma);
1406 }
1407 pub fn mean(&mut self) -> f64 {
1408 return self.mu;
1409 }
1410 pub fn var(&mut self) -> f64 {
1411 return self.sigma * self.sigma;
1412 }
1413 pub fn sd(&mut self) -> f64 {
1414 return self.sigma;
1415 }
1416}
1417
1418
1419/// Computes probability density function (pdf) for `X ~ Normal(mu, sigma)`.
1420///
1421/// # Parameters
1422/// - `-infinity < mu < infinity`
1423/// - `sigma > 0`
1424/// # Support
1425/// - `-infinity < x < infinity`
1426/// # Example
1427/// Suppose `X ~ Normal(mu=100.0, sigma=16.0)`. Use.
1428/// ```
1429/// use ruststat::normal_pdf;
1430/// println!("Probability density function f(110.0): {}", normal_pdf(110.0, 100.0, 16.0));
1431pub fn normal_pdf(x: f64, mu: f64, sigma: f64) -> f64 {
1432 if sigma <= 0.0 {
1433 println!("NAN produced. Error in function normal_pdf");
1434 return f64::NAN;
1435 }
1436 return 1.0 / (2.0 * PI * sigma.powi(2)).sqrt() *
1437 (-0.5*((x-mu)/sigma).powi(2)).exp();
1438}
1439
1440
1441/// Computes cumulative distribution function (cdf) for `X ~ Normal(mu, sigma)`.
1442///
1443/// # Parameters
1444/// - `-infinity < mu < infinity`
1445/// - `sigma > 0`
1446/// # Support
1447/// - `-infinity < x < infinity`
1448/// # Example
1449/// Suppose `X ~ Normal(mu=100.0, sigma=16.0)`. Use.
1450/// ```
1451/// use ruststat::normal_cdf;
1452/// println!("P(X<=110.0): {}", normal_cdf(110.0, 100.0, 16.0));
1453/// ```
1454pub fn normal_cdf(x: f64, mu: f64, sigma: f64) -> f64 {
1455 if sigma <= 0.0 {
1456 println!("NAN produced. Error in function normal_cdf");
1457 return f64::NAN;
1458 }
1459
1460 return 0.5 * (1.0 + erf(((x-mu)/sigma) / 2.0f64.sqrt()));
1461}
1462
1463
1464/// Computes a percentile for `X ~ Normal(mu, sigma)`.
1465///
1466/// # Note
1467/// Determines the value of `x` such that `P(X <= x) = q`.
1468/// # Parameters
1469/// - `-infinity < mu < infinity`
1470/// - `sigma > 0`
1471/// # Support
1472/// - `-infinity < x < infinity`
1473/// # Example
1474/// Suppose `X ~ Normal(mu=100.0, sigma=16.0)`. To find the 80th percentile, use `q=0.80` and
1475/// ```
1476/// use ruststat::normal_per;
1477/// println!("Percentile: {}", normal_per(0.8, 100.0, 16.0));
1478/// ```
1479pub fn normal_per(p: f64, mu: f64, sigma: f64) -> f64 {
1480 return mu + sigma * 2.0f64.sqrt() * erf_inv(2.0*p-1.0);
1481}
1482
1483
1484/// Random draw from `X ~ Normal(mu, sigma)` distribution.
1485///
1486/// # Parameters
1487/// - `-infinity < mu < infinity`
1488/// - `sigma > 0`
1489/// # Support
1490/// - `-infinity < x < infinity`
1491/// # Example
1492/// Suppose `X ~ Normal(mu=100.0, sigma=16.0)`. Use
1493/// ```
1494/// use ruststat::normal_ran;
1495/// println!("Random draw: {}", normal_ran(100.0, 16.0));
1496/// ```
1497pub fn normal_ran(mu: f64, sigma: f64) -> f64 {
1498 let mut rng = rand::rng();
1499 let u1: f64;
1500 let u2: f64;
1501 let z1: f64;
1502 // let mut z2: f64;
1503
1504 if sigma <= 0.0 {
1505 println!("Bad argument to normal_rand");
1506 return f64::NAN;
1507 }
1508
1509 u1 = rng.random();
1510 u2 = rng.random();
1511 z1 = mu + sigma * (-2.0 * u1.ln()).sqrt() * (2.0 * PI * u2).cos();
1512 // z2 = mu + sig * (-2.0 * u1.ln()).sqrt() * (2.0 * PI * u2).sin();
1513
1514 return z1;
1515}
1516
1517
1518/// Save random draws from `X ~ Normal(mu, sigma)` distribution into a `Vec`
1519///
1520/// # Parameters
1521/// - `-infinity < mu < infinity`
1522/// - `sigma > 0`
1523/// # Support
1524/// - `-infinity < x < infinity`
1525/// # Example
1526/// Suppose `X ~ Normal(mu=100.0, sigma=16.0)`. Use
1527/// ```
1528/// use ruststat::normal_ranvec;
1529/// println!("Random Vec of normals: {:?}", normal_ranvec(10, 100.0, 16.0));
1530/// ```
1531pub fn normal_ranvec(n: i32, mu: f64, sigma: f64) -> Vec<f64> {
1532 let mut rng = rand::rng();
1533 let mut u1: f64;
1534 let mut u2: f64;
1535 let mut z1: f64;
1536 let mut z2: f64;
1537
1538 let mut zvecthr: Vec<f64> = Vec::new();
1539
1540 let niter: i32;
1541 if n <= 0 || sigma <= 0.0 {
1542 println!("Bad argument to normal_rand");
1543 return vec![f64::NAN];
1544 }
1545
1546 if 0==n%2 {
1547 niter = n / 2;
1548 }
1549 else {
1550 niter = (n + 1) / 2;
1551 }
1552
1553 // let now = Instant::now();
1554
1555 for _ in 0..niter {
1556 u1 = rng.random();
1557 u2 = rng.random();
1558 z1 = mu + sigma * (-2.0 * u1.ln()).sqrt() * (2.0 * PI * u2).cos();
1559 z2 = mu + sigma * (-2.0 * u1.ln()).sqrt() * (2.0 * PI * u2).sin();
1560 zvecthr.push(z1);
1561 zvecthr.push(z2);
1562 }
1563
1564 // let elapsed = now.elapsed();
1565 // println!("Elapsed: {:.2?}", elapsed);
1566
1567 if 0!=n%2 { // n is odd --- throw one out
1568 zvecthr.pop();
1569 }
1570
1571 return zvecthr;
1572}
1573
1574// pub fn normal_rand2(mu: f64, sig: f64, rng: &mut impl Rng) -> f64 {
1575// // let mut rng = rand::thread_rng();
1576// let u1: f64;
1577// let u2: f64;
1578// let z1: f64;
1579// // let mut z2: f64;
1580//
1581// if sig <= 0.0 {
1582// println!("Bad argument to normal_rand");
1583// return f64::NAN;
1584// }
1585//
1586// u1 = rng.gen();
1587// u2 = rng.gen();
1588// z1 = mu + sig * (-2.0 * u1.ln()).sqrt() * (2.0 * PI * u2).cos();
1589// // z2 = mu + sig * (-2.0 * u1.ln()).sqrt() * (2.0 * PI * u2).sin();
1590//
1591// return z1;
1592// }
1593
1594
1595// ==========================================
1596// ==========================================
1597// Pareto (Type I) Distribution
1598// ==========================================
1599// ==========================================
1600
1601/// Struct for the Pareto (type I) distribution `X ~ Pareto1(sigma, alpha)`.
1602///
1603/// # Parameters
1604/// - `sigma > 0`
1605/// - `alpha > 0`
1606/// # Support
1607/// - `x >= sigma`
1608/// # Example
1609/// Suppose `X ~ Pareto1(sigma=2.0, alpha=0.5)`. Use
1610/// ```
1611/// use ruststat::Pareto1Dist;
1612/// let mut mydist = Pareto1Dist{sigma:2.0, alpha:0.5};
1613/// println!("Probability density function f(2.5): {}", mydist.pdf(2.5));
1614/// println!("Cumulative distribution function P(X<=110.0): {}", mydist.cdf(2.5));
1615/// println!("99th percentile: {}", mydist.per(0.99));
1616/// println!("Random draw: {}", mydist.ran());
1617/// println!("Random vector: {:?}", mydist.ranvec(5));
1618/// println!("Mean: {}", mydist.mean());
1619/// println!("Variance: {}", mydist.var());
1620/// println!("Standard deviation: {}", mydist.sd());
1621/// ```
1622pub struct Pareto1Dist {
1623 pub sigma: f64,
1624 pub alpha: f64,
1625}
1626impl Pareto1Dist {
1627 pub fn pdf(&mut self, x: f64) -> f64 {
1628 return pareto4_pdf(x, self.sigma, self.sigma, 1.0, self.alpha);
1629 }
1630 pub fn cdf(&mut self, x: f64) -> f64 {
1631 return pareto4_cdf(x, self.sigma, self.sigma, 1.0, self.alpha);
1632 }
1633 pub fn per(&mut self, x: f64) -> f64 {
1634 return pareto4_per(x,self.sigma, self.sigma, 1.0, self.alpha);
1635 }
1636 pub fn ran(&mut self) -> f64 {
1637 return pareto4_ran(self.sigma, self.sigma, 1.0, self.alpha);
1638 }
1639 pub fn ranvec(&mut self, n: i32) -> Vec<f64> {
1640 return pareto4_ranvec(n, self.sigma, self.sigma, 1.0, self.alpha);
1641 }
1642 pub fn mean(&mut self) -> f64 {
1643 return self.sigma + self.sigma * gamma(self.alpha-1.0) *
1644 gamma(1.0 + 1.0) / gamma(self.alpha);
1645 }
1646 pub fn var(&mut self) -> f64 {
1647 return self.sigma.powi(2) * gamma(self.alpha - 1.0 * 2.0) *
1648 gamma(1.0 + 1.0 * 2.0) / gamma(self.alpha) - self.mean().powi(2);
1649 }
1650 pub fn sd(&mut self) -> f64 {
1651 return self.var().sqrt();
1652 }
1653}
1654
1655
1656// ==========================================
1657// ==========================================
1658// Pareto (Type II) Distribution
1659// ==========================================
1660// ==========================================
1661
1662/// Struct for the Pareto (type II) distribution `X ~ Pareto2(mu, sigma, alpha)`.
1663///
1664/// # Parameters
1665/// - `-infinity < mu < infinity`
1666/// - `sigma > 0`
1667/// - `alpha > 0`
1668/// # Support
1669/// - `x >= mu`
1670/// # Example
1671/// Suppose `X ~ Pareto2(mu=1.0, sigma=2.0, alpha=0.5)`. Use
1672/// ```
1673/// use ruststat::Pareto2Dist;
1674/// let mut mydist = Pareto2Dist{mu: 1.0, sigma:2.0, alpha:0.5};
1675/// println!("Probability density function f(2.5): {}", mydist.pdf(2.5));
1676/// println!("Cumulative distribution function P(X<=110.0): {}", mydist.cdf(2.5));
1677/// println!("99th percentile: {}", mydist.per(0.99));
1678/// println!("Random draw: {}", mydist.ran());
1679/// println!("Random vector: {:?}", mydist.ranvec(5));
1680/// println!("Mean: {}", mydist.mean());
1681/// println!("Variance: {}", mydist.var());
1682/// println!("Standard deviation: {}", mydist.sd());
1683/// ```
1684pub struct Pareto2Dist {
1685 pub mu: f64,
1686 pub sigma: f64,
1687 pub alpha: f64,
1688}
1689impl Pareto2Dist {
1690 pub fn pdf(&mut self, x: f64) -> f64 {
1691 return pareto4_pdf(x, self.mu, self.sigma, 1.0, self.alpha);
1692 }
1693 pub fn cdf(&mut self, x: f64) -> f64 {
1694 return pareto4_cdf(x, self.mu, self.sigma, 1.0, self.alpha);
1695 }
1696 pub fn per(&mut self, x: f64) -> f64 {
1697 return pareto4_per(x,self.mu, self.sigma, 1.0, self.alpha);
1698 }
1699 pub fn ran(&mut self) -> f64 {
1700 return pareto4_ran(self.mu, self.sigma, 1.0, self.alpha);
1701 }
1702 pub fn ranvec(&mut self, n: i32) -> Vec<f64> {
1703 return pareto4_ranvec(n,self.mu, self.sigma, 1.0, self.alpha);
1704 }
1705 pub fn mean(&mut self) -> f64 {
1706 return self.mu + self.sigma * gamma(self.alpha-1.0) *
1707 gamma(1.0 + 1.0) / gamma(self.alpha);
1708 }
1709 pub fn var(&mut self) -> f64 {
1710 return self.sigma.powi(2) * gamma(self.alpha - 1.0 * 2.0) *
1711 gamma(1.0 + 1.0 * 2.0) / gamma(self.alpha) - self.mean().powi(2);
1712 }
1713 pub fn sd(&mut self) -> f64 {
1714 return self.var().sqrt();
1715 }
1716}
1717
1718
1719// ==========================================
1720// ==========================================
1721// Pareto (Type III) Distribution
1722// ==========================================
1723// ==========================================
1724
1725/// Struct for the Pareto (type III) distribution `X ~ Pareto3(mu, sigma, gamma)`.
1726///
1727/// # Parameters
1728/// - `-infinity < mu < infinity`
1729/// - `sigma > 0`
1730/// - `gamma > 0`
1731/// # Support
1732/// - `x >= mu`
1733/// # Example
1734/// Suppose `X ~ Pareto3(mu=0.0, sigma=1.0, gamma=2.0)`. Use
1735/// ```
1736/// use ruststat::Pareto3Dist;
1737/// let mut mydist = Pareto3Dist{mu:0.0, sigma:1.0, gamma:2.0};
1738/// println!("Probability density function f(1.5): {}", mydist.pdf(1.5));
1739/// println!("Cumulative distribution function P(X<=110.0): {}", mydist.cdf(1.5));
1740/// println!("99th percentile: {}", mydist.per(0.99));
1741/// println!("Random draw: {}", mydist.ran());
1742/// println!("Random vector: {:?}", mydist.ranvec(5));
1743/// println!("Mean: {}", mydist.mean());
1744/// println!("Variance: {}", mydist.var());
1745/// println!("Standard deviation: {}", mydist.sd());
1746/// ```
1747pub struct Pareto3Dist {
1748 pub mu: f64,
1749 pub sigma: f64,
1750 pub gamma: f64,
1751}
1752impl Pareto3Dist {
1753 pub fn pdf(&mut self, x: f64) -> f64 {
1754 return pareto4_pdf(x, self.mu, self.sigma, self.gamma, 1.0);
1755 }
1756 pub fn cdf(&mut self, x: f64) -> f64 {
1757 return pareto4_cdf(x, self.mu, self.sigma, self.gamma, 1.0);
1758 }
1759 pub fn per(&mut self, x: f64) -> f64 {
1760 return pareto4_per(x,self.mu, self.sigma, self.gamma, 1.0);
1761 }
1762 pub fn ran(&mut self) -> f64 {
1763 return pareto4_ran(self.mu, self.sigma, self.gamma, 1.0);
1764 }
1765 pub fn ranvec(&mut self, n: i32) -> Vec<f64> {
1766 return pareto4_ranvec(n,self.mu, self.sigma, self.gamma, 1.0);
1767 }
1768 pub fn mean(&mut self) -> f64 {
1769 return self.mu + self.sigma * gamma(1.0-self.gamma) *
1770 gamma(1.0 + self.gamma) / gamma(1.0);
1771 }
1772 pub fn var(&mut self) -> f64 {
1773 return self.sigma.powi(2) * gamma(1.0 - self.gamma * 2.0) *
1774 gamma(1.0 + self.gamma * 2.0) / gamma(1.0) - self.mean().powi(2);
1775 }
1776 pub fn sd(&mut self) -> f64 {
1777 return self.var().sqrt();
1778 }
1779}
1780
1781
1782// ==========================================
1783// ==========================================
1784// Pareto (Type IV) Distribution
1785// ==========================================
1786// ==========================================
1787
1788/// Struct for the Pareto (type IV) distribution `X ~ Pareto4(mu, sigma, gamma, alpha)`.
1789///
1790/// # Parameters
1791/// - `-infinity < mu < infinity`
1792/// - `sigma > 0`
1793/// - `gamma > 0`
1794/// - `alpha > 0`
1795/// # Support
1796/// - `x >= mu`
1797/// # Example
1798/// Suppose `X ~ Pareto4(mu=0.0, sigma=1.0, gamma=2.0, alpha=0.5)`. Use
1799/// ```
1800/// use ruststat::Pareto4Dist;
1801/// let mut mydist = Pareto4Dist{mu:0.0, sigma:1.0, gamma:2.0, alpha:0.5};
1802/// println!("Probability density function f(1.5): {}", mydist.pdf(1.5));
1803/// println!("Cumulative distribution function P(X<=110.0): {}", mydist.cdf(1.5));
1804/// println!("99th percentile: {}", mydist.per(0.99));
1805/// println!("Random draw: {}", mydist.ran());
1806/// println!("Random vector: {:?}", mydist.ranvec(5));
1807/// println!("Mean: {}", mydist.mean());
1808/// println!("Variance: {}", mydist.var());
1809/// println!("Standard deviation: {}", mydist.sd());
1810/// ```
1811pub struct Pareto4Dist {
1812 pub mu: f64,
1813 pub sigma: f64,
1814 pub gamma: f64,
1815 pub alpha: f64,
1816}
1817impl Pareto4Dist {
1818 pub fn pdf(&mut self, x: f64) -> f64 {
1819 return pareto4_pdf(x, self.mu, self.sigma, self.gamma, self.alpha);
1820 }
1821 pub fn cdf(&mut self, x: f64) -> f64 {
1822 return pareto4_cdf(x, self.mu, self.sigma, self.gamma, self.alpha);
1823 }
1824 pub fn per(&mut self, x: f64) -> f64 {
1825 return pareto4_per(x,self.mu, self.sigma, self.gamma, self.alpha);
1826 }
1827 pub fn ran(&mut self) -> f64 {
1828 return pareto4_ran(self.mu, self.sigma, self.gamma, self.alpha);
1829 }
1830 pub fn ranvec(&mut self, n: i32) -> Vec<f64> {
1831 return pareto4_ranvec(n,self.mu, self.sigma, self.gamma, self.alpha);
1832 }
1833 pub fn mean(&mut self) -> f64 {
1834 return self.mu + self.sigma * gamma(self.alpha-self.gamma) *
1835 gamma(1.0 + self.gamma) / gamma(self.alpha);
1836 }
1837 pub fn var(&mut self) -> f64 {
1838 return self.sigma.powi(2) * gamma(self.alpha - self.gamma * 2.0) *
1839 gamma(1.0 + self.gamma * 2.0) / gamma(self.alpha) - self.mean().powi(2);
1840 }
1841 pub fn sd(&mut self) -> f64 {
1842 return self.var().sqrt();
1843 }
1844}
1845
1846
1847/// Computes probability density function (pdf) for `X ~ Pareto(mu, sigma, gamma, alpha)`.
1848///
1849/// # Parameters
1850/// - `-infinity < mu < infinity`
1851/// - `sigma > 0`
1852/// - `gamma > 0`
1853/// - `alpha > 0`
1854/// # Support
1855/// - `x >= mu`
1856/// # Example
1857/// Suppose `X ~ Pareto4(mu=0.0, sigma=1.0, gamma=2.0, alpha=0.5)`. Use.
1858/// ```
1859/// use ruststat::pareto4_pdf;
1860/// println!("Probability density function f(1.5): {}", pareto4_pdf(1.5, 0.0, 1.0, 2.0, 0.5));
1861pub fn pareto4_pdf(x: f64, mu: f64, sigma: f64, gamma: f64, alpha: f64) -> f64 {
1862 if sigma <= 0.0 || gamma <= 0.0 || alpha <= 0.0 {
1863 println!("NAN produced. Error in function pareto_pdf");
1864 return f64::NAN;
1865 }
1866 if x < mu {
1867 return 0.0;
1868 }
1869 return (alpha/(gamma*sigma))*((x-mu)/sigma).powf(1.0/gamma - 1.0)*
1870 (1.0 + ((x-mu)/sigma).powf(1.0/gamma)).powf(-alpha-1.0);
1871}
1872
1873
1874/// Computes cumulative distribution function (cdf) for `X ~ Pareto(mu, sigma, gamma, alpha)`.
1875///
1876/// # Parameters
1877/// - `-infinity < mu < infinity`
1878/// - `sigma > 0`
1879/// - `gamma > 0`
1880/// - `alpha > 0`
1881/// # Support
1882/// - `x >= mu`
1883/// # Example
1884/// Suppose `X ~ Pareto4(mu=0.0, sigma=1.0, gamma=2.0, alpha=0.5)`. Use.
1885/// ```
1886/// use ruststat::pareto4_cdf;
1887/// println!("P(X<=1.5): {}", pareto4_cdf(1.5, 0.0, 1.0, 2.0, 0.5));
1888/// ```
1889pub fn pareto4_cdf(x: f64, mu: f64, sigma: f64, gamma: f64, alpha: f64) -> f64 {
1890 if sigma <= 0.0 || gamma <= 0.0 || alpha <= 0.0 {
1891 println!("NAN produced. Error in function pareto_cdf");
1892 return f64::NAN;
1893 }
1894 if x < mu {
1895 return 0.0;
1896 }
1897
1898 return 1.0 - (1.0 + ((x-mu)/sigma).powf(1.0/gamma)).powf(-alpha);
1899}
1900
1901
1902/// Computes a percentile for `X ~ Pareto(mu, sigma, gamma, alpha)`.
1903///
1904/// # Note
1905/// Determines the value of `x` such that `P(X <= x) = q`.
1906/// # Parameters
1907/// - `-infinity < mu < infinity`
1908/// - `sigma > 0`
1909/// - `gamma > 0`
1910/// - `alpha > 0`
1911/// # Support
1912/// - `x >= mu`
1913/// # Example
1914/// Suppose `X ~ Pareto4(mu=0.0, sigma=1.0, gamma=2.0, alpha=0.5)`. To find the 80th percentile, use `q=0.80` and
1915/// ```
1916/// use ruststat::pareto4_per;
1917/// println!("Percentile: {}", pareto4_per(0.8, 0.0, 1.0, 2.0, 0.5));
1918/// ```
1919pub fn pareto4_per(p: f64, mu: f64, sigma: f64, gamma: f64, alpha: f64) -> f64 {
1920 return mu + sigma * ((1.0-p).powf(-1.0/alpha) - 1.0).powf(gamma);
1921}
1922
1923
1924/// Random draw from `X ~ Pareto(mu, sigma, gamma, alpha)` distribution.
1925///
1926/// # Parameters
1927/// - `-infinity < mu < infinity`
1928/// - `sigma > 0`
1929/// - `gamma > 0`
1930/// - `alpha > 0`
1931/// # Support
1932/// - `x >= mu`
1933/// # Example
1934/// Suppose `X ~ Pareto4(mu=0.0, sigma=1.0, gamma=2.0, alpha=0.5)`. Use
1935/// ```
1936/// use ruststat::pareto4_ran;
1937/// println!("Random draw: {}", pareto4_ran(0.0, 1.0, 2.0, 0.5));
1938/// ```
1939pub fn pareto4_ran(mu: f64, sigma: f64, gamma: f64, alpha: f64) -> f64 {
1940 return mu + sigma * ((1.0-unif_ran(0.0, 1.0)).powf(-1.0/alpha) - 1.0).powf(gamma);
1941}
1942
1943
1944/// Save random draws from `X ~ Pareto(mu, sigma, gamma, alpha)` distribution into a `Vec`
1945///
1946/// # Parameters
1947/// - `-infinity < mu < infinity`
1948/// - `sigma > 0`
1949/// - `gamma > 0`
1950/// - `alpha > 0`
1951/// # Support
1952/// - `x >= mu`
1953/// # Example
1954/// Suppose `X ~ Pareto4(mu=0.0, sigma=1.0, gamma=2.0, alpha=0.5)`. Use
1955/// ```
1956/// use ruststat::pareto4_ranvec;
1957/// println!("Random Vec: {:?}", pareto4_ranvec(10, 0.0, 1.0, 2.0, 0.5));
1958/// ```
1959pub fn pareto4_ranvec(n: i32, mu: f64, sigma: f64, gamma: f64, alpha: f64) -> Vec<f64> {
1960 let mut xvec: Vec<f64> = Vec::new();
1961 for _ in 0..n {
1962 xvec.push(pareto4_ran(mu, sigma, gamma, alpha));
1963 }
1964 return xvec;
1965}
1966
1967
1968// ==========================================
1969// ==========================================
1970// t Distribution
1971// ==========================================
1972// ==========================================
1973
1974/// Struct for Student's t distribution `X ~ t(nu)`.
1975///
1976/// # Parameters
1977/// - `nu > 0`
1978/// # Support
1979/// - `-infinity < x < infinity`
1980/// # Example
1981/// Suppose `X ~ t(nu=25)`. Use
1982/// ```
1983/// use ruststat::TDist;
1984/// let mut myt = TDist{nu:25.0};
1985/// println!("Probability density function f(2.2): {}", myt.pdf(2.2));
1986/// println!("Cumulative distribution function P(X<=2.2): {}", myt.cdf(2.2));
1987/// println!("99th percentile: {}", myt.per(0.99));
1988/// println!("Random draw: {}", myt.ran());
1989/// println!("Random vector: {:?}", myt.ranvec(5));
1990/// println!("Mean: {}", myt.mean());
1991/// println!("Variance: {}", myt.var());
1992/// println!("Standard deviation: {}", myt.sd());
1993/// ```
1994pub struct TDist {
1995 pub nu: f64,
1996}
1997impl TDist {
1998 pub fn pdf(&mut self, x: f64) -> f64 {
1999 return t_pdf(x, self.nu);
2000 }
2001 pub fn cdf(&mut self, x: f64) -> f64 {
2002 return t_cdf(x, self.nu);
2003 }
2004 pub fn per(&mut self, p: f64) -> f64 {
2005 return t_per(p,self.nu);
2006 }
2007 pub fn ran(&mut self) -> f64 {
2008 return t_ran(self.nu);
2009 }
2010 pub fn ranvec(&mut self, n: i32) -> Vec<f64> {
2011 return t_ranvec(n, self.nu);
2012 }
2013 pub fn mean(&mut self) -> f64 {
2014 return 0.0;
2015 }
2016 pub fn var(&mut self) -> f64 {
2017 return if self.nu > 2.0 {
2018 self.nu / (self.nu - 2.0)
2019 } else {
2020 f64::NAN
2021 }
2022 }
2023 pub fn sd(&mut self) -> f64 {
2024 return if self.nu > 2.0 {
2025 self.var().sqrt()
2026 } else {
2027 f64::NAN
2028 }
2029 }
2030}
2031
2032
2033/// Computes probability density function (pdf) for `X ~ t(nu)`.
2034///
2035/// # Parameters
2036/// - `nu > 0`
2037/// # Support
2038/// - `-infinity < x < infinity`
2039/// # Example
2040/// Suppose `X ~ t(nu=25.0)`. Use.
2041/// ```
2042/// use ruststat::t_pdf;
2043/// println!("Probability density function f(2.2): {}", t_pdf(2.2, 25.0));
2044pub fn t_pdf(x: f64, nu: f64) -> f64 {
2045 if nu <= 0.0 {
2046 println!("NAN produced. Error in function t_pdf");
2047 return f64::NAN;
2048 }
2049 return gamma((nu+1.0)/2.0) * (1.0 + x.powi(2)/nu).powf(-(nu+1.0)/2.0) /
2050 ((nu * PI).sqrt() * gamma(nu/2.0));
2051}
2052
2053
2054/// Computes cumulative distribution function (cdf) for `X ~ t(nu)`.
2055///
2056/// # Parameters
2057/// - `nu > 0`
2058/// # Support
2059/// - `-infinity < x < infinity`
2060/// # Example
2061/// Suppose `X ~ nu(nu=25.0)`. Use.
2062/// ```
2063/// use ruststat::t_cdf;
2064/// println!("P(X<=2.2): {}", t_cdf(2.2, 25.0));
2065/// ```
2066pub fn t_cdf(x: f64, nu: f64) -> f64 {
2067 if nu <= 0.0 {
2068 println!("NAN produced. Error in function t_cdf");
2069 return f64::NAN;
2070 }
2071
2072 return if x <= 0.0 {
2073 0.5 * betai(nu / (nu + x * x), nu / 2.0, 0.5)
2074 } else {
2075 1.0 - 0.5 * betai(nu / (nu + x * x), nu / 2.0, 0.5)
2076 }
2077}
2078
2079
2080/// Computes a percentile for `X ~ t(nu)`.
2081///
2082/// # Note
2083/// Determines the value of `x` such that `P(X <= x) = q`.
2084/// # Parameters
2085/// - `nu > 0`
2086/// # Support
2087/// - `-infinity < x < infinity`
2088/// # Example
2089/// Suppose `X ~ t(nu=25.0)`. To find the 80th percentile, use `q=0.80` and
2090/// ```
2091/// use ruststat::t_per;
2092/// println!("Percentile: {}", t_per(0.8, 25.0));
2093/// ```
2094pub fn t_per(p: f64, nu: f64) -> f64 {
2095 let (a, x): (f64, f64);
2096 return if p <= 0.5 {
2097 a = betai_inv(2.0 * p, nu / 2.0, 1.0 / 2.0);
2098 x = (nu / a - nu).sqrt();
2099 -x
2100 } else {
2101 a = betai_inv(2.0 * (1.0 - p), nu / 2.0, 1.0 / 2.0);
2102 x = (nu / a - nu).sqrt();
2103 x
2104 }
2105}
2106
2107
2108/// Random draw from `X ~ t(nu)` distribution.
2109///
2110/// # Parameters
2111/// - `nu > 0`
2112/// # Support
2113/// - `-infinity < x < infinity`
2114/// # Example
2115/// Suppose `X ~ t(nu=25.0)`. Use
2116/// ```
2117/// use ruststat::t_ran;
2118/// println!("Random draw: {}", t_ran(25.0));
2119/// ```
2120pub fn t_ran(nu: f64) -> f64 {
2121 return normal_ran(0.0, 1.0) *
2122 (nu / gamma_ran(nu/2.0, 1.0/2.0)).sqrt();
2123}
2124
2125
2126/// Save random draws from `X ~ t(nu)` distribution into a `Vec`
2127///
2128/// # Parameters
2129/// - `nu > 0`
2130/// # Support
2131/// - `-infinity < x < infinity`
2132/// # Example
2133/// Suppose `X ~ t(nu=25.0)`. Use
2134/// ```
2135/// use ruststat::t_ranvec;
2136/// println!("Random Vec: {:?}", t_ranvec(10, 25.0));
2137/// ```
2138pub fn t_ranvec(n: i32, nu: f64) -> Vec<f64> {
2139 let mut xvec: Vec<f64> = Vec::new();
2140 for _ in 0..n {
2141 xvec.push(t_ran(nu));
2142 }
2143 return xvec;
2144}
2145
2146
2147// ==========================================
2148// ==========================================
2149// Continuous Uniform Distribution
2150// ==========================================
2151// ==========================================
2152
2153/// Struct for continuous uniform distribution `X ~ Unif(a,b)`.
2154///
2155/// # Parameters
2156/// - `-infinity < a < infinity`
2157/// - `-infinity < b < infinity`
2158/// - `a < b`
2159/// # Support
2160/// - `a < x < b`
2161/// # Example
2162/// Suppose `X ~ Unif(a=0.0, b=1.0)`. Use
2163/// ```
2164/// use ruststat::UnifDist;
2165/// let mut myunif = UnifDist{a:0.0, b:1.0};
2166/// println!("Probability density function f(0.4): {}", myunif.pdf(0.4));
2167/// println!("Cumulative distribution function P(X<=0.4): {}", myunif.cdf(0.4));
2168/// println!("99th percentile: {}", myunif.per(0.99));
2169/// println!("Random draw: {}", myunif.ran());
2170/// println!("Random vector: {:?}", myunif.ranvec(5));
2171/// println!("Mean: {}", myunif.mean());
2172/// println!("Variance: {}", myunif.var());
2173/// println!("Standard deviation: {}", myunif.sd());
2174/// ```
2175pub struct UnifDist {
2176 pub a: f64,
2177 pub b: f64,
2178}
2179impl UnifDist {
2180 pub fn pdf(&mut self, x: f64) -> f64 {
2181 return unif_pdf(x, self.a, self.b);
2182 }
2183 pub fn cdf(&mut self, x: f64) -> f64 {
2184 return unif_cdf(x, self.a, self.b);
2185 }
2186 pub fn per(&mut self, x: f64) -> f64 {
2187 return unif_per(x,self.a, self.b);
2188 }
2189 pub fn ran(&mut self) -> f64 {
2190 return unif_ran(self.a, self.b);
2191 }
2192 pub fn ranvec(&mut self, n: i32) -> Vec<f64> {
2193 return unif_ranvec(n, self.a, self.b);
2194 }
2195 pub fn mean(&mut self) -> f64 {
2196 return (self.a + self.b) / 2.0;
2197 }
2198 pub fn var(&mut self) -> f64 {
2199 return (self.b - self.a).powi(2) / 12.0;
2200 }
2201 pub fn sd(&mut self) -> f64 {
2202 return self.var().sqrt();
2203 }
2204}
2205
2206
2207/// Computes probability density function (pdf) for `X ~ Unif(a,b)`.
2208///
2209/// # Parameters
2210/// - `-infinity < a < infinity`
2211/// - `-infinity < b < infinity`
2212/// - `a < b`
2213/// # Support
2214/// - `a < x < b`
2215/// # Example
2216/// Suppose `X ~ Unif(a=0.0, b=1.0)`. Use.
2217/// ```
2218/// use ruststat::unif_pdf;
2219/// println!("Probability density function f(0.4): {}", unif_pdf(0.4, 0.0, 1.0));
2220pub fn unif_pdf(x: f64, a: f64, b: f64) -> f64 {
2221 if a >= b {
2222 println!("NAN produced. Error in function unif_pdf");
2223 return f64::NAN;
2224 }
2225 if x < a || x > b {
2226 return 0.0;
2227 }
2228 return 1.0 / (b - a);
2229}
2230
2231
2232/// Computes cumulative distribution function (cdf) for `X ~ Unif(a,b)`.
2233///
2234/// # Parameters
2235/// - `-infinity < a < infinity`
2236/// - `-infinity < b < infinity`
2237/// - `a < b`
2238/// # Support
2239/// - `a < x < b`
2240/// # Example
2241/// Suppose `X ~ Unif(a=0.0, b=1.0)`. Use.
2242/// ```
2243/// use ruststat::unif_cdf;
2244/// println!("P(X<=0.4): {}", unif_cdf(0.4, 0.0, 1.0));
2245/// ```
2246pub fn unif_cdf(x: f64, a: f64, b: f64) -> f64 {
2247 if a >= b {
2248 println!("NAN produced. Error in function unif_cdf");
2249 return f64::NAN;
2250 }
2251 if x < a {
2252 return 0.0;
2253 }
2254 if x > b {
2255 return 1.0;
2256 }
2257
2258 return (x - a) / (b - a);
2259}
2260
2261
2262/// Computes a percentile for `X ~ Unif(a,b)`.
2263///
2264/// # Note
2265/// Determines the value of `x` such that `P(X <= x) = q`.
2266/// # Parameters
2267/// - `-infinity < a < infinity`
2268/// - `-infinity < b < infinity`
2269/// - `a < b`
2270/// # Support
2271/// - `a < x < b`
2272/// # Example
2273/// Suppose `X ~ Unif(a=0.0, b=1.0)`. To find the 80th percentile, use `q=0.80` and
2274/// ```
2275/// use ruststat::unif_per;
2276/// println!("Percentile: {}", unif_per(0.8, 0.0, 1.0));
2277/// ```
2278pub fn unif_per(p: f64, a: f64, b: f64) -> f64 {
2279 return a + p*(b-a);
2280}
2281
2282
2283/// Random draw from `X ~ Unif(a,b)` distribution.
2284///
2285/// # Parameters
2286/// - `-infinity < a < infinity`
2287/// - `-infinity < b < infinity`
2288/// - `a < b`
2289/// # Support
2290/// - `a < x < b`
2291/// # Example
2292/// Suppose `X ~ Unif(a=0.0, b=1.0)`. Use
2293/// ```
2294/// use ruststat::unif_ran;
2295/// println!("Random draw: {}", unif_ran(0.0, 1.0));
2296/// ```
2297pub fn unif_ran(a: f64, b: f64) -> f64 {
2298 let u: f64;
2299 u = random();
2300 // u = rand::thread_rng().gen();
2301 return a + u * (b-a);
2302}
2303
2304
2305/// Save random draws from `X ~ Unif(a,b)` distribution into a `Vec`
2306///
2307/// # Parameters
2308/// - `-infinity < a < infinity`
2309/// - `-infinity < b < infinity`
2310/// - `a < b`
2311/// # Support
2312/// - `a < x < b`
2313/// # Example
2314/// Suppose `X ~ Unif(a=0.0, b=1.0)`. Use
2315/// ```
2316/// use ruststat::unif_ranvec;
2317/// println!("Random Vec: {:?}", unif_ranvec(10, 0.0, 1.0));
2318/// ```
2319pub fn unif_ranvec(n: i32, a: f64, b: f64) -> Vec<f64> {
2320 let mut xvec: Vec<f64> = Vec::new();
2321 for _ in 0..n {
2322 xvec.push(unif_ran(a,b));
2323 }
2324 return xvec;
2325}
2326
2327
2328
2329// ==========================================
2330// ==========================================
2331// ==========================================
2332// Discrete RVs
2333// ==========================================
2334// ==========================================
2335// ==========================================
2336
2337
2338// ==========================================
2339// ==========================================
2340// Binomial Distribution
2341// ==========================================
2342// ==========================================
2343
2344/// Struct for the binomial distirubion `X ~ Bin(n,p)`.
2345///
2346/// # Parameters
2347/// - `n` = number of trials (`n = 1,2,...`)
2348/// - `p` = probability of success (`0 <= p <= 1`)
2349/// # Support
2350/// - `x = 0,1,2,...,n`
2351/// # Example
2352/// Suppose `X ~ Bin(n=100,p=0.9)`. Use
2353/// ```
2354/// use ruststat::BinDist;
2355/// let mut mybin = BinDist{n:100, p:0.9};
2356/// println!("P(X=80): {}", mybin.pmf(80));
2357/// println!("P(X<=80): {}", mybin.cdf(80));
2358/// println!("99th percentile: {}", mybin.per(0.99));
2359/// println!("Random draw: {}", mybin.ran());
2360/// println!("Random vector: {:?}", mybin.ranvec(5));
2361/// println!("Mean: {}", mybin.mean());
2362/// println!("Variance: {}", mybin.var());
2363/// println!("Standard deviation: {}", mybin.sd());
2364/// ```
2365pub struct BinDist {
2366 pub n: i32,
2367 pub p: f64,
2368}
2369impl BinDist {
2370 pub fn pmf(&mut self, x: i32) -> f64 {
2371 return bin_pmf(x, self.n, self.p);
2372 }
2373 pub fn cdf(&mut self, x: i32) -> f64 {
2374 return bin_cdf(x, self.n, self.p);
2375 }
2376 pub fn per(&mut self, q: f64) -> i32 {
2377 return bin_per(q, self.n, self.p);
2378 }
2379 pub fn ran(&mut self) -> i32 {
2380 return bin_ran(self.n, self.p);
2381 }
2382 pub fn ranvec(&mut self, n: i32) -> Vec<i32> {
2383 return bin_ranvec(n, self.n, self.p);
2384 }
2385 pub fn mean(&mut self) -> f64 {
2386 return (self.n as f64) * self.p;
2387 }
2388 pub fn var(&mut self) -> f64 {
2389 return (self.n as f64) * self.p * (1.0-self.p);
2390 }
2391 pub fn sd(&mut self) -> f64 {
2392 return self.var().sqrt();
2393 }
2394}
2395
2396
2397/// Computes probability mass function (pmf) for `X ~ Bin(n,p)`
2398///
2399/// # Parameters
2400/// - `n` = number of trials (`n = 1,2,...`)
2401/// - `p` = probability of success (`0 <= p <= 1`)
2402/// # Support
2403/// - `x = 0,1,2,...,n`
2404/// # Example
2405/// Suppose `X ~ Bin(n=10,p=0.6)`. To compute `P(X = 7)`, use
2406/// ```
2407/// use ruststat::bin_pmf;
2408/// println!("P(X=x): {}", bin_pmf(7, 10, 0.6));
2409/// ```
2410pub fn bin_pmf(x: i32, n: i32, p: f64) -> f64 {
2411 if n <= 0 || p < 0.0 || p > 1.0 {
2412 println!("NAN produced. Error in function bin_pmf");
2413 return f64::NAN;
2414 }
2415 if x < 0 || x > n {
2416 return 0.0;
2417 }
2418 return comb(n, x) * p.powi(x) * (1.0-p).powi(n-x);
2419}
2420
2421
2422/// Computes cumulative distribution function (cdf) for `X ~ Bin(n,p)`
2423///
2424/// # Parameters
2425/// - `n` = number of trials (`n = 1,2,...`)
2426/// - `p` = probability of success (`0 <= p <= 1`)
2427/// # Support
2428/// - `x = 0,1,2,...,n`
2429/// # Example
2430/// Suppose `X ~ Bin(n=10,p=0.6)`. To compute `P(X <= 7)`, use
2431/// ```
2432/// use ruststat::bin_cdf;
2433/// println!("P(X<=x): {}", bin_cdf(7, 10, 0.6));
2434/// ```
2435pub fn bin_cdf(x: i32, n: i32, p: f64) -> f64 {
2436 if n <= 0 || p < 0.0 || p > 1.0 {
2437 println!("NAN produced. Error in function bin_cdf");
2438 return f64::NAN;
2439 }
2440 if x < 0 {
2441 return 0.0;
2442 }
2443 if x > n {
2444 return 1.0;
2445 }
2446
2447 let mut sum = 0.0;
2448 for i in 0..=x {
2449 sum += bin_pmf(i, n, p);
2450 }
2451 return if sum < 1.0 {
2452 sum
2453 } else {
2454 1.0
2455 }
2456}
2457
2458
2459/// Computes a percentile for `X ~ Bin(n,p)`
2460/// # Note
2461/// Determines the smallest (integer) value of `x` such that `P(X <= x) >= q`.
2462/// # Parameters
2463/// - `n` = number of trials (`n = 1,2,...`)
2464/// - `p` = probability of success (`0 <= p <= 1`)
2465/// # Support
2466/// - `x = 0,1,2,...,n`
2467/// # Example
2468/// Suppose `X ~ Bin(n=10,p=0.6)`. To find the 80th percentile, use `q=0.80` and
2469/// ```
2470/// use ruststat::bin_per;
2471/// println!("Percentile: {}", bin_per(0.8, 10, 0.6));
2472/// ```
2473pub fn bin_per(q: f64, n: i32, p: f64) -> i32 {
2474 let mut x = 0;
2475
2476 if n <= 0 || p < 0.0 || p > 1.0 || q < 0.0 || q > 1.0 {
2477 println!("NAN produced. Error in function bin_per");
2478 return f64::NAN as i32;
2479 }
2480 if q == 0.0 {
2481 return 0;
2482 }
2483 if q == 1.0 {
2484 return n;
2485 }
2486
2487 while bin_cdf(x, n, p) < q {
2488 x += 1;
2489 }
2490 return x;
2491}
2492
2493
2494/// Random draw from `X ~ Bin(n,p)` distribution
2495/// Sheldon Ross, Simulation, (2003)
2496/// # Parameters
2497/// - `n` = number of trials (`n = 1,2,...`)
2498/// - `p` = probability of success (`0 <= p <= 1`)
2499/// # Support
2500/// - `x = 0,1,2,...,n`
2501/// # Example
2502/// Suppose `X ~ Bin(n=10,p=0.6)`. Use
2503/// ```
2504/// use ruststat::bin_ran;
2505/// println!("Random draw: {}", bin_ran(10, 0.6));
2506/// ```
2507pub fn bin_ran(n: i32, p: f64) -> i32 {
2508
2509 if n <= 0 || p < 0.0 || p > 1.0 {
2510 println!("NAN produced. Error in function bin_ran");
2511 return f64::NAN as i32;
2512 }
2513 if p == 0.0 {
2514 return 0;
2515 }
2516 if p == 1.0 {
2517 return n;
2518 }
2519
2520 let u : f64;
2521 u = unif_ran(0.0, 1.0);
2522 let c = p / (1.0 - p);
2523 let mut i = 0;
2524 let mut pr = (1.0 - p).powi(n);
2525 let mut f = pr;
2526 loop {
2527 if u < f {
2528 return i;
2529 }
2530 pr = c * ((n - i) as f64 / (i + 1) as f64) * pr;
2531 f = f + pr;
2532 i = i + 1;
2533 }
2534
2535 // let cdf = rand::thread_rng().gen();
2536 // let mut x = 0;
2537 //
2538 // while bin_cdf(x, n, p) < cdf {
2539 // x += 1;
2540 // }
2541 //
2542 // return x;
2543}
2544
2545/// Save random draws from `X ~ Bin(n,p)` distribution into a `Vec`
2546/// # Parameters
2547/// - `n` = number of trials (`n = 1,2,...`)
2548/// - `p` = probability of success (`0 <= p <= 1`)
2549/// # Example
2550/// Suppose `X ~ Bin(n=10,p=0.6)`. Use
2551/// ```
2552/// use ruststat::bin_ranvec;
2553/// println!("Random Vec: {:?}", bin_ranvec(10, 10, 0.6));
2554/// ```
2555pub fn bin_ranvec(nn: i32, n: i32, p: f64) -> Vec<i32> {
2556 let mut xvec: Vec<i32> = Vec::new();
2557 for _ in 0..nn {
2558 xvec.push(bin_ran(n,p));
2559 }
2560 return xvec;
2561}
2562
2563
2564// ==========================================
2565// ==========================================
2566// Geometric Distribution
2567// ==========================================
2568// ==========================================
2569
2570/// Struct for the geometric distribution `X ~ Geo(p)` where
2571/// `X =` the number of failures prior to observing the first success.
2572///
2573/// # Parameters
2574/// - `p` = probability of success (`0 < p <= 1`)
2575/// # Support
2576/// - `x = 0,1,2,...`
2577/// # Example
2578/// Suppose `X ~ Geo(p=0.2)`. Use
2579/// ```
2580/// use ruststat::GeoDist;
2581/// let mut mygeo = GeoDist{p:0.2};
2582/// println!("probability mass function: {}", mygeo.pmf(8));
2583/// println!("cumulative distribution function: {}", mygeo.cdf(8));
2584/// println!("percentile: {}", mygeo.per(0.99));
2585/// println!("random: {}", mygeo.ran());
2586/// println!("Random vector: {:?}", mygeo.ranvec(5));
2587/// println!("mean: {}", mygeo.mean());
2588/// println!("variance: {}", mygeo.var());
2589/// println!("standard deviation: {}", mygeo.sd());
2590/// ```
2591pub struct GeoDist {
2592 pub p: f64,
2593}
2594impl GeoDist {
2595 pub fn pmf(&mut self, x: i32) -> f64 {
2596 return geo_pmf(x, self.p);
2597 }
2598 pub fn cdf(&mut self, x: i32) -> f64 {
2599 return geo_cdf(x, self.p);
2600 }
2601 pub fn per(&mut self, q: f64) -> i32 {
2602 return geo_per(q, self.p);
2603 }
2604 pub fn ran(&mut self) -> i32 {
2605 return geo_ran(self.p);
2606 }
2607 pub fn ranvec(&mut self, n: i32) -> Vec<i32> {
2608 return geo_ranvec(n, self.p);
2609 }
2610 pub fn mean(&mut self) -> f64 {
2611 return (1.0 - self.p) / self.p;
2612 }
2613 pub fn var(&mut self) -> f64 {
2614 return (1.0 - self.p) / self.p.powi(2);
2615 }
2616 pub fn sd(&mut self) -> f64 {
2617 return self.var().sqrt();
2618 }
2619}
2620
2621
2622/// Computes probability mass function (pmf) for `X ~ Geo(p)`
2623/// where `X =` the number of failures prior to the first success.
2624///
2625/// # Parameters
2626/// - `p` = probability of success (`0 < p <= 1`)
2627/// # Support
2628/// - `x = 0,1,2,...`
2629/// # Example
2630/// Suppose `X ~ Geo(p=0.6)`. To compute `P(X = 3)`, use
2631/// ```
2632/// use ruststat::geo_pmf;
2633/// println!("P(X=x): {}", geo_pmf(3, 0.6));
2634/// ```
2635pub fn geo_pmf(x: i32, p: f64) -> f64 {
2636 if p <= 0.0 || p > 1.0 {
2637 println!("NAN produced. Error in function geo_pmf");
2638 return f64::NAN;
2639 }
2640 if x < 0 {
2641 return 0.0;
2642 }
2643 return (1.0-p).powi(x) * p;
2644}
2645
2646
2647/// Computes cumulative distribution function (cdf) for `X ~ Geo(p)`
2648/// where `X =` the number of failures prior to the first success.
2649///
2650/// # Parameters
2651/// - `p` = probability of success (`0 <= p <= 1`)
2652/// # Support
2653/// - `x = 0,1,2,...`
2654/// # Example
2655/// Suppose `X ~ Geo(p=0.6)`. To compute `P(X <= 3)`, use
2656/// ```
2657/// use ruststat::geo_cdf;
2658/// println!("P(X<=x): {}", geo_cdf(3, 0.6));
2659/// ```
2660pub fn geo_cdf(x: i32, p: f64) -> f64 {
2661 if p <= 0.0 || p > 1.0 {
2662 println!("NAN produced. Error in function geo_pmf");
2663 return f64::NAN;
2664 }
2665 if x < 0 {
2666 return 0.0;
2667 }
2668
2669 let mut sum = 0.0;
2670 for i in 0..=x {
2671 sum += geo_pmf(i, p);
2672 }
2673 return sum;
2674}
2675
2676
2677/// Computes a percentile for `X ~ Geo(p)`
2678/// where `X =` the number of failures prior to the first success.
2679///
2680/// # Note
2681/// Determines the smallest (integer) value of `x` such that `P(X <= x) >= q`.
2682/// # Parameters
2683/// - `p` = probability of success (`0 < p <= 1`)
2684/// # Support
2685/// - `x = 0,1,2,...`
2686/// # Example
2687/// Suppose `X ~ Geo(p=0.6)`. To find the 80th percentile, use `q=0.80` and
2688/// ```
2689/// use ruststat::geo_per;
2690/// println!("Percentile: {}", geo_per(0.8, 0.6));
2691/// ```
2692pub fn geo_per(q: f64, p: f64) -> i32 {
2693 let mut x = 0;
2694
2695 if p <= 0.0 || p > 1.0 || q < 0.0 || q > 1.0 {
2696 println!("NAN produced. Error in function geo1_per");
2697 return f64::NAN as i32;
2698 }
2699 if q == 0.0 {
2700 return 0;
2701 }
2702 if q == 1.0 {
2703 return i32::MAX;
2704 }
2705
2706 while geo_cdf(x, p) < q {
2707 x += 1;
2708 }
2709 return x;
2710}
2711
2712
2713/// Random draw from `X ~ Geo(p)` distribution
2714/// where `X =` the number of failures prior to the first success.
2715///
2716/// # Parameters
2717/// - `p` = probability of success (`0 < p <= 1`)
2718/// # Example
2719/// Suppose `X ~ Geo(p=0.6)`. Use
2720/// ```
2721/// use ruststat::geo_ran;
2722/// println!("Random draw: {}", geo_ran(0.6));
2723/// ```
2724pub fn geo_ran(p: f64) -> i32 {
2725
2726 if p <= 0.0 || p > 1.0 {
2727 println!("NAN produced. Error in function geo1_ran");
2728 return f64::NAN as i32;
2729 }
2730
2731 let u = unif_ran(0.0, 1.0);
2732 return (u.ln() / (1.0-p).ln()).floor() as i32;
2733
2734 // let cdf = unif_ran(0.0, 1.0);
2735 // let mut x = 0;
2736 //
2737 // while geo_cdf(x, p) < cdf {
2738 // x += 1;
2739 // }
2740 // return x;
2741}
2742
2743
2744/// Save random draws from `X ~ Geo(p)` distribution into a `Vec`
2745/// # Parameters
2746/// - `p` = probability of success (`0 <= p <= 1`)
2747/// # Example
2748/// Suppose `X ~ Geo(p=0.6)`. Use
2749/// ```
2750/// use ruststat::geo_ranvec;
2751/// println!("Random Vec: {:?}", geo_ranvec(10, 0.6));
2752/// ```
2753pub fn geo_ranvec(nn: i32, p: f64) -> Vec<i32> {
2754 let mut xvec: Vec<i32> = Vec::new();
2755 for _ in 0..nn {
2756 xvec.push(geo_ran(p));
2757 }
2758 return xvec;
2759}
2760
2761
2762// ==========================================
2763// ==========================================
2764// Geometric Distribution 2
2765// ==========================================
2766// ==========================================
2767
2768/// Struct for the geometric distribution `X ~ Geo(p)` where
2769/// `X =` the trial on which the first success is observed.
2770///
2771/// # Parameters
2772/// - `p` = probability of success (`0 < p <= 1`)
2773/// # Support
2774/// - `x = 1,2,3,...`
2775/// # Example
2776/// Suppose `X ~ Geo(p=0.2)`. Use
2777/// ```
2778/// use ruststat::Geo2Dist;
2779/// let mut mygeo = Geo2Dist{p:0.2};
2780/// println!("probability mass function: {}", mygeo.pmf(8));
2781/// println!("cumulative distribution function: {}", mygeo.cdf(8));
2782/// println!("percentile: {}", mygeo.per(0.99));
2783/// println!("random: {}", mygeo.ran());
2784/// println!("Random vector: {:?}", mygeo.ranvec(5));
2785/// println!("mean: {}", mygeo.mean());
2786/// println!("variance: {}", mygeo.var());
2787/// println!("standard deviation: {}", mygeo.sd());
2788/// ```
2789pub struct Geo2Dist {
2790 pub p: f64,
2791}
2792impl Geo2Dist {
2793 pub fn pmf(&mut self, x: i32) -> f64 {
2794 return geo2_pmf(x, self.p);
2795 }
2796 pub fn cdf(&mut self, x: i32) -> f64 {
2797 return geo2_cdf(x, self.p);
2798 }
2799 pub fn per(&mut self, q: f64) -> i32 {
2800 return geo2_per(q, self.p);
2801 }
2802 pub fn ran(&mut self) -> i32 {
2803 return geo2_ran(self.p);
2804 }
2805 pub fn ranvec(&mut self, n: i32) -> Vec<i32> {
2806 return geo2_ranvec(n, self.p);
2807 }
2808 pub fn mean(&mut self) -> f64 {
2809 return 1.0 / self.p;
2810 }
2811 pub fn var(&mut self) -> f64 {
2812 return (1.0 - self.p) / self.p.powi(2);
2813 }
2814 pub fn sd(&mut self) -> f64 {
2815 return self.var().sqrt();
2816 }
2817}
2818
2819
2820/// Computes probability mass function (pmf) for `X ~ Geo(p)`
2821/// where `X =` the trial on which the first success is observed.
2822///
2823/// # Parameters
2824/// - `p` = probability of success (`0 < p <= 1`)
2825/// # Support
2826/// - `x = 1,2,3,...`
2827/// # Example
2828/// Suppose `X ~ Geo(p=0.6)`. To compute `P(X = 3)`, use
2829/// ```
2830/// use ruststat::geo2_pmf;
2831/// println!("P(X=x): {}", geo2_pmf(3, 0.6));
2832/// ```
2833pub fn geo2_pmf(x: i32, p: f64) -> f64 {
2834 if p <= 0.0 || p > 1.0 {
2835 println!("NAN produced. Error in function geo2_pmf");
2836 return f64::NAN;
2837 }
2838 if x < 1 {
2839 return 0.0;
2840 }
2841 return (1.0-p).powi(x-1) * p;
2842}
2843
2844
2845/// Computes cumulative distribution function (cdf) for `X ~ Geo(p)`
2846/// where `X =` the trial on which the first success is observed.
2847///
2848/// # Parameters
2849/// - `p` = probability of success (`0 <= p <= 1`)
2850/// # Support
2851/// - `x = 1,2,3,...`
2852/// # Example
2853/// Suppose `X ~ Geo(p=0.6)`. To compute `P(X <= 3)`, use
2854/// ```
2855/// use ruststat::geo2_cdf;
2856/// println!("P(X<=x): {}", geo2_cdf(3, 0.6));
2857/// ```
2858pub fn geo2_cdf(x: i32, p: f64) -> f64 {
2859 if p <= 0.0 || p > 1.0 {
2860 println!("NAN produced. Error in function geo2_cdf");
2861 return f64::NAN;
2862 }
2863 if x < 1 {
2864 return 0.0;
2865 }
2866
2867 let mut sum = 0.0;
2868 for i in 1..=x {
2869 sum += geo2_pmf(i, p);
2870 }
2871 return sum;
2872}
2873
2874
2875/// Computes a percentile for `X ~ Geo(p)`
2876/// where `X =` the trial on which the first success is observed.
2877///
2878/// # Note
2879/// Determines the smallest (integer) value of `x` such that `P(X <= x) >= q`.
2880/// # Parameters
2881/// - `p` = probability of success (`0 < p <= 1`)
2882/// # Support
2883/// - `x = 1,2,3,...`
2884/// # Example
2885/// Suppose `X ~ Geo(p=0.6)`. To find the 80th percentile, use `q=0.80` and
2886/// ```
2887/// use ruststat::geo2_per;
2888/// println!("Percentile: {}", geo2_per(0.8, 0.6));
2889/// ```
2890pub fn geo2_per(q: f64, p: f64) -> i32 {
2891 let mut x = 1;
2892
2893 if p <= 0.0 || p > 1.0 || q < 0.0 || q > 1.0 {
2894 println!("NAN produced. Error in function geo2_per");
2895 return f64::NAN as i32;
2896 }
2897 if q == 0.0 {
2898 return 1;
2899 }
2900 if q == 1.0 {
2901 return i32::MAX;
2902 }
2903
2904 while geo2_cdf(x, p) < q {
2905 x += 1;
2906 }
2907 return x;
2908}
2909
2910
2911/// Random draw from `X ~ Geo(p)` distribution
2912/// where `X =` the trial on which the first success is observed.
2913///
2914/// # Parameters
2915/// - `p` = probability of success (`0 < p <= 1`)
2916/// # Example
2917/// Suppose `X ~ Geo(p=0.6)`. Use
2918/// ```
2919/// use ruststat::geo2_ran;
2920/// println!("Random draw: {}", geo2_ran(0.6));
2921/// ```
2922pub fn geo2_ran(p: f64) -> i32 {
2923
2924 if p <= 0.0 || p > 1.0 {
2925 println!("NAN produced. Error in function geo2_ran");
2926 return f64::NAN as i32;
2927 }
2928
2929 let u = unif_ran(0.0, 1.0);
2930 return (u.ln() / (1.0-p).ln()).floor() as i32 + 1;
2931
2932 // let cdf = rand::thread_rng().gen();
2933 // let mut x = 1;
2934 //
2935 // while geo2_cdf(x, p) < cdf {
2936 // x += 1;
2937 // }
2938 // return x;
2939}
2940
2941/// Save random draws from `X ~ Geo(p)` distribution into a `Vec`
2942/// where `X =` the trial on which the first success is observed.
2943///
2944/// # Parameters
2945/// - `p` = probability of success (`0 < p <= 1`)
2946/// # Example
2947/// Suppose `X ~ Geo(p=0.6)`. Use
2948/// ```
2949/// use ruststat::geo2_ranvec;
2950/// println!("Random Vec: {:?}", geo2_ranvec(10, 0.6));
2951/// ```
2952pub fn geo2_ranvec(nn: i32, p: f64) -> Vec<i32> {
2953 let mut xvec: Vec<i32> = Vec::new();
2954 for _ in 0..nn {
2955 xvec.push(geo2_ran(p));
2956 }
2957 return xvec;
2958}
2959
2960
2961// ==========================================
2962// ==========================================
2963// HyperGeometric Distribution
2964// ==========================================
2965// ==========================================
2966
2967/// Struct for the hypergeometric distribution `X ~ HG(n,N,M)`.
2968///
2969/// # Parameters
2970/// - Sample size: `n = 1,2,3,...,N`
2971/// - Population size: `N = 1,2,3,...`
2972/// - Number of successes in population: `M = 1,2,3,...,N`
2973/// # Support
2974/// - `x = 0,1,2,...,n`
2975/// - `x <= M`
2976/// - `n-x <= N-M`
2977/// # Example
2978/// Suppose `X ~ HG(n=20, N=100, M=50)`. Use
2979/// ```
2980/// use ruststat::HGDist;
2981/// let mut myhg = HGDist{n:20, N:100, M:50};
2982/// println!("P(X=6): {}", myhg.pmf(6));
2983/// println!("P(X<=6): {}", myhg.cdf(6));
2984/// println!("99th percentile: {}", myhg.per(0.99));
2985/// println!("Random draw: {}", myhg.ran());
2986/// println!("Random vector: {:?}", myhg.ranvec(5));
2987/// println!("Mean: {}", myhg.mean());
2988/// println!("Variance: {}", myhg.var());
2989/// println!("Standard deviation: {}", myhg.sd());
2990/// ```
2991#[allow(non_snake_case)]
2992pub struct HGDist {
2993 pub n: i32,
2994 pub N: i32,
2995 pub M: i32,
2996}
2997impl HGDist {
2998 pub fn pmf(&mut self, x: i32) -> f64 {
2999 return hg_pmf(x, self.n, self.N, self.M);
3000 }
3001 pub fn cdf(&mut self, x: i32) -> f64 {
3002 return hg_cdf(x, self.n, self.N, self.M);
3003 }
3004 pub fn per(&mut self, q: f64) -> i32 {
3005 return hg_per(q, self.n, self.N, self.M);
3006 }
3007 pub fn ran(&mut self) -> i32 {
3008 return hg_ran(self.n, self.N, self.M);
3009 }
3010 pub fn ranvec(&mut self, n: i32) -> Vec<i32> {
3011 return hg_ranvec(n, self.n, self.N, self.M);
3012 }
3013 pub fn mean(&mut self) -> f64 {
3014 return (self.n as f64) * (self.M as f64) / (self.N as f64);
3015 }
3016 pub fn var(&mut self) -> f64 {
3017 return (self.n as f64) *
3018 (self.M as f64) / (self.N as f64) *
3019 (1.0 - (self.M as f64) / (self.N as f64)) *
3020 (self.N as f64 - self.n as f64) / (self.N as f64 - 1.0);
3021 }
3022 pub fn sd(&mut self) -> f64 {
3023 return self.var().sqrt();
3024 }
3025}
3026
3027
3028/// Computes probability mass function (pmf) for `X ~ HG(n,N,M)`
3029/// where `X =` the number of successes.
3030///
3031/// # Parameters
3032/// - Sample size: `n = 1,2,3,...,N`
3033/// - Population size: `N = 1,2,3,...`
3034/// - Number of successes in population: `M = 1,2,3,...,N`
3035/// # Support
3036/// - `x = 0,1,2,...,n`
3037/// - `x <= M`
3038/// - `n-x <= N-M`
3039/// # Example
3040/// Suppose `X ~ HG(n=20,N=100,M=50)`. To compute `P(X = 7)`, use
3041/// ```
3042/// use ruststat::hg_pmf;
3043/// println!("P(X=x): {}", hg_pmf(7, 20, 100, 50));
3044/// ```
3045#[allow(non_snake_case)]
3046pub fn hg_pmf(x: i32, n: i32, N: i32, M: i32) -> f64 {
3047 if n < 1 || N < 1 || M < 1 || M > N || n > N {
3048 println!("NAN produced. Error in function hg_pmf");
3049 return f64::NAN;
3050 }
3051 if x < 0 || x > n || x > M || (n-x) > (N-M) {
3052 return 0.0;
3053 }
3054
3055 return comb(M, x) * comb(N-M, n-x) / comb(N, n);
3056}
3057
3058
3059/// Computes cumulative distribution function (cdf) for `X ~ HG(n,N,M)`
3060/// where `X =` the number of successes.
3061///
3062/// # Parameters
3063/// - Sample size: `n = 1,2,3,...,N`
3064/// - Population size: `N = 1,2,3,...`
3065/// - Number of successes in population: `M = 1,2,3,...,N`
3066/// # Support
3067/// - `x = 0,1,2,...,n`
3068/// - `x <= M`
3069/// - `n-x <= N-M`
3070/// # Example
3071/// Suppose `X ~ HG(n=20,N=100,M=50)`. To compute `P(X <= 7)`, use
3072/// ```
3073/// use ruststat::hg_cdf;
3074/// println!("P(X<=x): {}", hg_cdf(7, 20, 100, 50));
3075/// ```
3076#[allow(non_snake_case)]
3077pub fn hg_cdf(x: i32, n: i32, N: i32, M: i32) -> f64 {
3078 if n < 1 || N < 1 || M < 1 || M > N || n > N {
3079 println!("NAN produced. Error in function hg_cdf");
3080 return f64::NAN;
3081 }
3082 if x < 0 || x > M || (n-x) > (N-M) {
3083 return 0.0;
3084 }
3085 if x > n {
3086 return 1.0;
3087 }
3088
3089 let mut sum = 0.0;
3090 for i in 0..=x {
3091 sum += hg_pmf(i, n, N, M);
3092 }
3093 return sum;
3094}
3095
3096
3097/// Computes a percentile for `X ~ HG(n,N,M)`
3098/// where `X =` the number of successes.
3099///
3100/// # Note
3101/// Determines the smallest (integer) value of `x` such that `P(X <= x) >= q`.
3102/// # Parameters
3103/// - Sample size: `n = 1,2,3,...,N`
3104/// - Population size: `N = 1,2,3,...`
3105/// - Number of successes in population: `M = 1,2,3,...,N`
3106/// # Support
3107/// - `x = 0,1,2,...,n`
3108/// - `x <= M`
3109/// - `n-x <= N-M`
3110/// # Example
3111/// Suppose `X ~ HG(n=20, N=100, M=50)`. To find the 80th percentile, use `q=0.80` and
3112/// ```
3113/// use ruststat::hg_per;
3114/// println!("Percentile: {}", hg_per(0.8, 20, 100, 50));
3115/// ```
3116#[allow(non_snake_case)]
3117pub fn hg_per(q: f64, n: i32, N: i32, M: i32) -> i32 {
3118 let mut x = 0;
3119
3120 if n < 1 || N < 1 || M < 1 ||
3121 M > N || n > N ||
3122 q < 0.0 || q > 1.0 {
3123 println!("NAN produced. Error in function hg_per");
3124 return f64::NAN as i32;
3125 }
3126 // if q == 0.0 {
3127 // return 0;
3128 // }
3129 // if q == 1.0 {
3130 // return n;
3131 // }
3132
3133 while hg_cdf(x, n, N, M) < q {
3134 x += 1;
3135 }
3136 return x;
3137}
3138
3139
3140/// Random draw from `X ~ HG(n, N, M)` distribution
3141/// where `X =` the number of successes.
3142///
3143/// # Parameters
3144/// - Sample size: `n = 1,2,3,...,N`
3145/// - Population size: `N = 1,2,3,...`
3146/// - Number of successes in population: `M = 1,2,3,...,N`
3147/// # Example
3148/// Suppose `X ~ HG(n=20, N=100, M=50)`. Use
3149/// ```
3150/// use ruststat::hg_ran;
3151/// println!("Random draw: {}", hg_ran(20, 100, 50));
3152/// ```
3153#[allow(non_snake_case)]
3154pub fn hg_ran(n: i32, N: i32, M: i32) -> i32 {
3155
3156 if n < 1 || N < 1 || M < 1 ||
3157 M > N || n > N {
3158 println!("NAN produced. Error in function hg_ran");
3159 return f64::NAN as i32;
3160 }
3161
3162
3163 // use rand::seq::index::sample;
3164 // use rand::seq::SliceRandom;
3165 use rand::rng;
3166
3167 let mut rng = rng();
3168
3169 let popn = Vec::from_iter(1..=N);
3170 let sample = popn.choose_multiple(&mut rng, n as usize);
3171 // let sample = popn.choose_multiple(&mut rng, n as usize);
3172 let x = sample.filter(|&x| *x <= M).count();
3173 return x as i32;
3174 // println!("count <= M: {}", sample.filter(|&x| *x <= M).count());
3175
3176
3177 // let cdf = rand::thread_rng().gen();
3178 // let mut x = 0;
3179 //
3180 // while hg_cdf(x, n, N, M) < cdf {
3181 // x += 1;
3182 // }
3183 // return x;
3184}
3185
3186
3187/// Save random draws from `X ~ HG(n,N,M)` distribution into a `Vec`
3188/// where `X =` the number of successes.
3189///
3190/// # Parameters
3191/// - Sample size: `n = 1,2,3,...,N`
3192/// - Population size: `N = 1,2,3,...`
3193/// - Number of successes in population: `M = 1,2,3,...,N`
3194/// # Example
3195/// Suppose `X ~ HG(n=20, N=100, M=50)`. Use
3196/// ```
3197/// use ruststat::hg_ranvec;
3198/// println!("Random Vec: {:?}", hg_ranvec(10, 20, 100, 50));
3199/// ```
3200#[allow(non_snake_case)]
3201pub fn hg_ranvec(nn: i32, n: i32, N: i32, M: i32) -> Vec<i32> {
3202 let mut xvec: Vec<i32> = Vec::new();
3203 for _ in 0..nn {
3204 xvec.push(hg_ran(n,N,M));
3205 }
3206 return xvec;
3207}
3208
3209
3210// ==========================================
3211// ==========================================
3212// Negative Binomial Distribution
3213// ==========================================
3214// ==========================================
3215
3216/// Struct for the negative binomial distribution `X ~ NB(r,p)` where
3217/// `X =` the number of failures prior to observing the `r`th success.
3218///
3219/// # Parameters
3220/// - `r = 1,2,3,...`
3221/// - `p` = probability of success (`0 < p <= 1`)
3222/// # Support
3223/// - `x = 0,1,2,...`
3224/// # Example
3225/// Suppose `X ~ NB(r=4,p=0.2)`. Use
3226/// ```
3227/// use ruststat::NBDist;
3228/// let mut mynb = NBDist{r:4, p:0.2};
3229/// println!("P(X=6): {}", mynb.pmf(6));
3230/// println!("P(X<=6): {}", mynb.cdf(6));
3231/// println!("99th percentile: {}", mynb.per(0.99));
3232/// println!("Random draw: {}", mynb.ran());
3233/// println!("Random vector: {:?}", mynb.ranvec(5));
3234/// println!("Mean: {}", mynb.mean());
3235/// println!("Variance: {}", mynb.var());
3236/// println!("Standard deviation: {}", mynb.sd());
3237/// ```
3238pub struct NBDist {
3239 pub r: i32,
3240 pub p: f64,
3241}
3242impl NBDist {
3243 pub fn pmf(&mut self, x: i32) -> f64 {
3244 return nb_pmf(x, self.r, self.p);
3245 }
3246 pub fn cdf(&mut self, x: i32) -> f64 {
3247 return nb_cdf(x, self.r, self.p);
3248 }
3249 pub fn per(&mut self, q: f64) -> i32 {
3250 return nb_per(q, self.r, self.p);
3251 }
3252 pub fn ran(&mut self) -> i32 {
3253 return nb_ran(self.r, self.p);
3254 }
3255 pub fn ranvec(&mut self, n: i32) -> Vec<i32> {
3256 return nb_ranvec(n, self.r, self.p);
3257 }
3258 pub fn mean(&mut self) -> f64 {
3259 return (self.r as f64) * (1.0 - self.p) / self.p;
3260 }
3261 pub fn var(&mut self) -> f64 {
3262 return (self.r as f64) * (1.0 - self.p) / self.p.powi(2);
3263 }
3264 pub fn sd(&mut self) -> f64 {
3265 return self.var().sqrt();
3266 }
3267}
3268
3269
3270/// Computes probability mass function (pmf) for `X ~ NB(r,p)`
3271/// where `X =` the number of failures prior to the `r`th success.
3272///
3273/// # Parameters
3274/// - `r = 1,2,...`
3275/// - `p` = probability of success (`0 < p <= 1`)
3276/// # Support
3277/// - `x = 0,1,2,...`
3278/// # Example
3279/// Suppose `X ~ NB(r=2,p=0.6)`. To compute `P(X = 3)`, use
3280/// ```
3281/// use ruststat::nb_pmf;
3282/// println!("P(X=x): {}", nb_pmf(3, 2, 0.6));
3283/// ```
3284pub fn nb_pmf(x: i32, r: i32, p: f64) -> f64 {
3285 if r < 1 || p <= 0.0 || p > 1.0 {
3286 println!("NAN produced. Error in function nb_pmf");
3287 return f64::NAN;
3288 }
3289 if x < 0 {
3290 return 0.0;
3291 }
3292 return comb(x+r-1, r-1) * p.powi(r) * (1.0-p).powi(x);
3293}
3294
3295
3296/// Computes cumulative distribution function (cdf) for `X ~ NB(r,p)`
3297/// where `X =` the number of failures prior to the `r`th success.
3298///
3299/// # Parameters
3300/// - `r = 1,2,...`
3301/// - `p` = probability of success (`0 <= p <= 1`)
3302/// # Support
3303/// - `x = 0,1,2,...`
3304/// # Example
3305/// Suppose `X ~ NB(r=2, p=0.6)`. To compute `P(X <= 3)`, use
3306/// ```
3307/// use ruststat::nb_cdf;
3308/// println!("P(X<=x): {}", nb_cdf(3, 2, 0.6));
3309/// ```
3310pub fn nb_cdf(x: i32, r: i32, p: f64) -> f64 {
3311 if r < 1 || p <= 0.0 || p > 1.0 {
3312 println!("NAN produced. Error in function nb_cdf");
3313 return f64::NAN;
3314 }
3315 if x < 0 {
3316 return 0.0;
3317 }
3318
3319 let mut sum = 0.0;
3320 for i in 0..=x {
3321 sum += nb_pmf(i, r, p);
3322 }
3323 return sum;
3324}
3325
3326
3327/// Computes a percentile for `X ~ NB(r,p)`
3328/// where `X =` the number of failures prior to the `r`th success.
3329///
3330/// # Note
3331/// Determines the smallest (integer) value of `x` such that `P(X <= x) >= q`.
3332/// # Parameters
3333/// - `r = 1,2,...`
3334/// - `p` = probability of success (`0 < p <= 1`)
3335/// # Support
3336/// - `x = 0,1,2,...`
3337/// # Example
3338/// Suppose `X ~ NB(r=2, p=0.6)`. To find the 80th percentile, use `q=0.80` and
3339/// ```
3340/// use ruststat::nb_per;
3341/// println!("Percentile: {}", nb_per(0.8, 2, 0.6));
3342/// ```
3343pub fn nb_per(q: f64, r: i32, p: f64) -> i32 {
3344 let mut x = 0;
3345
3346 if r < 0 || p <= 0.0 || p > 1.0 || q < 0.0 || q > 1.0 {
3347 println!("NAN produced. Error in function nb_per");
3348 return f64::NAN as i32;
3349 }
3350 if q == 0.0 {
3351 return 0;
3352 }
3353 if q == 1.0 {
3354 return i32::MAX;
3355 }
3356
3357 while nb_cdf(x, r, p) < q {
3358 x += 1;
3359 }
3360 return x;
3361}
3362
3363
3364/// Random draw from `X ~ NB(r, p)` distribution
3365/// where `X =` the number of failures prior to the `r`th success.
3366///
3367/// # Parameters
3368/// - `r = 1,2,...`
3369/// - `p` = probability of success (`0 < p <= 1`)
3370/// # Example
3371/// Suppose `X ~ NB(r=2, p=0.6)`. Use
3372/// ```
3373/// use ruststat::nb_ran;
3374/// println!("Random draw: {}", nb_ran(2, 0.6));
3375/// ```
3376pub fn nb_ran(r: i32, p: f64) -> i32 {
3377
3378 if r < 0 || p <= 0.0 || p > 1.0 {
3379 println!("NAN produced. Error in function nb_ran");
3380 return f64::NAN as i32;
3381 }
3382
3383 let mut geo_vec = Vec::new();
3384 for _ in 0..r {
3385 geo_vec.push(geo_ran(p));
3386 }
3387 return geo_vec.iter().sum();
3388 // let cdf = rand::thread_rng().gen();
3389 // let mut x = 0;
3390 //
3391 // while nb_cdf(x, r, p) < cdf {
3392 // x += 1;
3393 // }
3394 // return x;
3395}
3396
3397
3398/// Save random draws from `X ~ NB(r,p)` distribution into a `Vec`
3399/// where `X =` the number of failures prior to the `r`th success.
3400///
3401/// # Parameters
3402/// - `r = 1,2,...`
3403/// - `p` = probability of success (`0 < p <= 1`)
3404/// # Example
3405/// Suppose `X ~ NB(r=2, p=0.6)`. Use
3406/// ```
3407/// use ruststat::nb_ranvec;
3408/// println!("Random Vec: {:?}", nb_ranvec(10, 2, 0.6));
3409/// ```
3410pub fn nb_ranvec(nn: i32, r: i32, p: f64) -> Vec<i32> {
3411 let mut xvec: Vec<i32> = Vec::new();
3412 for _ in 0..nn {
3413 xvec.push(nb_ran(r,p));
3414 }
3415 return xvec;
3416}
3417
3418
3419// ==========================================
3420// ==========================================
3421// Negative Binomial Distribution 2
3422// ==========================================
3423// ==========================================
3424
3425/// Struct for the negative binomial distribution `X ~ NB(r,p)` where
3426/// `X =` the trial on which the `r`th success is observed.
3427///
3428/// # Parameters
3429/// - `r = r,r+1,r+2,...`
3430/// - `p` = probability of success (`0 < p <= 1`)
3431/// # Support
3432/// - `x = r,r+1,r+2,...`
3433/// # Example
3434/// Suppose `X ~ NB(r=4,p=0.2)`. Use
3435/// ```
3436/// use ruststat::NB2Dist;
3437/// let mut mynb = NB2Dist{r:4, p:0.2};
3438/// println!("P(X=6): {}", mynb.pmf(6));
3439/// println!("P(X<=6): {}", mynb.cdf(6));
3440/// println!("99th percentile: {}", mynb.per(0.99));
3441/// println!("Random draw: {}", mynb.ran());
3442/// println!("Random vector: {:?}", mynb.ranvec(5));
3443/// println!("Mean: {}", mynb.mean());
3444/// println!("Variance: {}", mynb.var());
3445/// println!("Standard deviation: {}", mynb.sd());
3446/// ```
3447pub struct NB2Dist {
3448 pub r: i32,
3449 pub p: f64,
3450}
3451impl NB2Dist {
3452 pub fn pmf(&mut self, x: i32) -> f64 {
3453 return nb2_pmf(x, self.r, self.p);
3454 }
3455 pub fn cdf(&mut self, x: i32) -> f64 {
3456 return nb2_cdf(x, self.r, self.p);
3457 }
3458 pub fn per(&mut self, q: f64) -> i32 {
3459 return nb2_per(q, self.r, self.p);
3460 }
3461 pub fn ran(&mut self) -> i32 {
3462 return nb2_ran(self.r, self.p);
3463 }
3464 pub fn ranvec(&mut self, n: i32) -> Vec<i32> {
3465 return nb2_ranvec(n, self.r, self.p);
3466 }
3467 pub fn mean(&mut self) -> f64 {
3468 return (self.r as f64) / self.p;
3469 }
3470 pub fn var(&mut self) -> f64 {
3471 return (self.r as f64) * (1.0 - self.p) / self.p.powi(2);
3472 }
3473 pub fn sd(&mut self) -> f64 {
3474 return self.var().sqrt();
3475 }
3476}
3477
3478
3479/// Computes probability mass function (pmf) for `X ~ NB(r,p)`
3480/// where `X =` the trial on which the `r`th success is observed.
3481///
3482/// # Parameters
3483/// - `r = r,r+1,r+2,...`
3484/// - `p` = probability of success (`0 < p <= 1`)
3485/// # Support
3486/// - `x = r,r+1,r+2,...`
3487/// # Example
3488/// Suppose `X ~ NB(r=2,p=0.6)`. To compute `P(X = 3)`, use
3489/// ```
3490/// use ruststat::nb2_pmf;
3491/// println!("P(X=x): {}", nb2_pmf(3, 2, 0.6));
3492/// ```
3493pub fn nb2_pmf(x: i32, r: i32, p: f64) -> f64 {
3494 if r < 1 || p <= 0.0 || p > 1.0 {
3495 println!("NAN produced. Error in function nb2_pmf");
3496 return f64::NAN;
3497 }
3498 if x < r {
3499 return 0.0;
3500 }
3501 return comb(x-1, r-1) * p.powi(r) * (1.0-p).powi(x-r);
3502}
3503
3504
3505/// Computes cumulative distribution function (cdf) for `X ~ NB(r,p)`
3506/// where `X =` the trial on which the `r`th success is observed.
3507///
3508/// # Parameters
3509/// - `r = r,r+1,r+2,...`
3510/// - `p` = probability of success (`0 <= p <= 1`)
3511/// # Support
3512/// - `x = r,r+1,r+2,...`
3513/// # Example
3514/// Suppose `X ~ NB(r=2, p=0.6)`. To compute `P(X <= 3)`, use
3515/// ```
3516/// use ruststat::nb2_cdf;
3517/// println!("P(X<=x): {}", nb2_cdf(3, 2, 0.6));
3518/// ```
3519pub fn nb2_cdf(x: i32, r: i32, p: f64) -> f64 {
3520 if r < 1 || p <= 0.0 || p > 1.0 {
3521 println!("NAN produced. Error in function nb2_cdf");
3522 return f64::NAN;
3523 }
3524 if x < r {
3525 return 0.0;
3526 }
3527
3528 let mut sum = 0.0;
3529 for i in r..=x {
3530 sum += nb2_pmf(i, r, p);
3531 }
3532 return sum;
3533}
3534
3535
3536/// Computes a percentile for `X ~ NB(r,p)`
3537/// where `X =` the trial on which the `r`th success is observed.
3538///
3539/// # Note
3540/// Determines the smallest (integer) value of `x` such that `P(X <= x) >= q`.
3541/// # Parameters
3542/// - `r = r,r+1,r+2,...`
3543/// - `p` = probability of success (`0 < p <= 1`)
3544/// # Support
3545/// - `x = r,r+1,r+2,...`
3546/// # Example
3547/// Suppose `X ~ NB(r=2, p=0.6)`. To find the 80th percentile, use `q=0.80` and
3548/// ```
3549/// use ruststat::nb2_per;
3550/// println!("Percentile: {}", nb2_per(0.8, 2, 0.6));
3551/// ```
3552pub fn nb2_per(q: f64, r: i32, p: f64) -> i32 {
3553
3554 if r < 1 || p <= 0.0 || p > 1.0 || q < 0.0 || q > 1.0 {
3555 println!("NAN produced. Error in function nb2_per");
3556 return f64::NAN as i32;
3557 }
3558 if q == 0.0 {
3559 return r;
3560 }
3561 if q == 1.0 {
3562 return f64::INFINITY as i32;
3563 }
3564
3565 let mut x = r;
3566 while nb2_cdf(x, r, p) < q {
3567 x += 1;
3568 }
3569 return x;
3570}
3571
3572
3573/// Random draw from `X ~ NB(r, p)` distribution
3574/// where `X =` the trial on which the `r`th success is observed.
3575///
3576/// # Parameters
3577/// - `r = r,r+1,r+2,...`
3578/// - `p` = probability of success (`0 < p <= 1`)
3579/// # Example
3580/// Suppose `X ~ NB(r=2, p=0.6)`. Use
3581/// ```
3582/// use ruststat::nb2_ran;
3583/// println!("Random draw: {}", nb2_ran(2, 0.6));
3584/// ```
3585pub fn nb2_ran(r: i32, p: f64) -> i32 {
3586
3587 if r < 1 || p <= 0.0 || p > 1.0 {
3588 println!("NAN produced. Error in function nb2_ran");
3589 return f64::NAN as i32;
3590 }
3591
3592 let mut geo2_vec = Vec::new();
3593 for _ in 0..r {
3594 geo2_vec.push(geo2_ran(p));
3595 }
3596 return geo2_vec.iter().sum();
3597
3598 // let cdf = unif_ran(0.0, 1.0);
3599 // let mut x = r;
3600 //
3601 // while nb2_cdf(x, r, p) < cdf {
3602 // x += 1;
3603 // }
3604 // return x;
3605}
3606
3607
3608/// Save random draws from `X ~ NB(r,p)` distribution into a `Vec`
3609/// where `X =` the trial on which the `r`th success is observed.
3610///
3611/// # Parameters
3612/// - `r = r,r+1,r+2,...`
3613/// - `p` = probability of success (`0 < p <= 1`)
3614/// # Example
3615/// Suppose `X ~ NB(r=2, p=0.6)`. Use
3616/// ```
3617/// use ruststat::nb2_ranvec;
3618/// println!("Random Vec: {:?}", nb2_ranvec(10, 2, 0.6));
3619/// ```
3620pub fn nb2_ranvec(nn: i32, r: i32, p: f64) -> Vec<i32> {
3621 let mut xvec: Vec<i32> = Vec::new();
3622 for _ in 0..nn {
3623 xvec.push(nb2_ran(r,p));
3624 }
3625 return xvec;
3626}
3627
3628
3629// ==========================================
3630// ==========================================
3631// Poisson Distribution
3632// ==========================================
3633// ==========================================
3634
3635/// Struct for the Poisson distribution `X ~ Pois(lambda)`.
3636///
3637/// # Parameters
3638/// - `lambda > 0`
3639/// # Support
3640/// - `x = 0,1,2,...`
3641/// # Example
3642/// Suppose `X ~ Pois(lambda=2.5)`. Use
3643/// ```
3644/// use ruststat::PoisDist;
3645/// let mut mypois = PoisDist{lambda:2.5};
3646/// println!("P(X=6): {}", mypois.pmf(6));
3647/// println!("P(X<=6): {}", mypois.cdf(6));
3648/// println!("99th percentile: {}", mypois.per(0.99));
3649/// println!("Random draw: {}", mypois.ran());
3650/// println!("Random vector: {:?}", mypois.ranvec(5));
3651/// println!("Mean: {}", mypois.mean());
3652/// println!("Variance: {}", mypois.var());
3653/// println!("Standard deviation: {}", mypois.sd());
3654/// ```
3655pub struct PoisDist {
3656 pub lambda: f64,
3657}
3658impl PoisDist {
3659 pub fn pmf(&mut self, x: i32) -> f64 {
3660 return pois_pmf(x, self.lambda);
3661 }
3662 pub fn cdf(&mut self, x: i32) -> f64 {
3663 return pois_cdf(x, self.lambda);
3664 }
3665 pub fn per(&mut self, q: f64) -> i32 {
3666 return pois_per(q, self.lambda);
3667 }
3668 pub fn ran(&mut self) -> i32 {
3669 return pois_ran(self.lambda);
3670 }
3671 pub fn ranvec(&mut self, n: i32) -> Vec<i32> {
3672 return pois_ranvec(n, self.lambda);
3673 }
3674 pub fn mean(&mut self) -> f64 {
3675 return self.lambda;
3676 }
3677 pub fn var(&mut self) -> f64 {
3678 return self.lambda;
3679 }
3680 pub fn sd(&mut self) -> f64 {
3681 return self.var().sqrt();
3682 }
3683}
3684
3685
3686/// Computes probability mass function (pmf) for `X ~ Pois(lambda).`
3687///
3688/// # Parameters
3689/// - `lambda > 0`
3690/// # Support
3691/// - `x = 0,1,2,...`
3692/// # Example
3693/// Suppose `X ~ Pois(lambda=2.5)`. To compute `P(X = 4)`, use
3694/// ```
3695/// use ruststat::pois_pmf;
3696/// println!("P(X=x): {}", pois_pmf(4, 2.5));
3697/// ```
3698pub fn pois_pmf(x: i32, lambda: f64) -> f64 {
3699 if lambda <= 0.0 {
3700 println!("NAN produced. Error in function pois_pmf");
3701 return f64::NAN;
3702 }
3703 if x < 0 {
3704 return 0.0;
3705 }
3706 return (-lambda).exp() * lambda.powi(x) / (fact_i(x) as f64);
3707}
3708
3709
3710/// Computes cumulative distriubtion function (cdf) for `X ~ Pois(lambda).`
3711///
3712/// # Parameters
3713/// - `lambda > 0`
3714/// # Support
3715/// - `x = 0,1,2,...`
3716/// # Example
3717/// Suppose `X ~ Pois(lambda=2.5)`. To compute `P(X <= 4)`, use
3718/// ```
3719/// use ruststat::pois_cdf;
3720/// println!("P(X<=x): {}", pois_cdf(4, 2.5));
3721/// ```
3722// pub fn pois_cdf(x: i32, lambda: f64) -> f64 {
3723// if lambda <= 0.0 || x < 0 {
3724// println!("NAN produced. Error in function pois_cdf");
3725// return f64::NAN;
3726// }
3727// let mut sum = 0.0;
3728// for i in 0..=x {
3729// sum += pois_pmf(i, lambda);
3730// }
3731// return sum;
3732// }
3733pub fn pois_cdf(x: i32, lambda: f64) -> f64 {
3734 if lambda <= 0.0 {
3735 println!("NAN produced. Error in function pois_cdf");
3736 return f64::NAN;
3737 }
3738 if x < 0 {
3739 return 0.0;
3740 }
3741 return gammq(lambda, (x+1) as f64);
3742}
3743
3744
3745/// Computes a percentile for `X ~ Pois(lambda)`.
3746///
3747/// # Note
3748/// Determines the smallest (integer) value of `x` such that `P(X <= x) >= q`.
3749/// # Parameters
3750/// - `lambda > 0`
3751/// # Support
3752/// - `x = 0,1,2,...`
3753/// # Example
3754/// Suppose `X ~ Pois(lambda=2.5)`. To find the 80th percentile, use `q=0.80` and
3755/// ```
3756/// use ruststat::pois_per;
3757/// println!("Percentile: {}", pois_per(2.5, 0.8));
3758/// ```
3759pub fn pois_per(q: f64, lambda: f64) -> i32 {
3760 let mut x = 0;
3761
3762 if lambda <= 0.0 || q < 0.0 || q > 1.0 {
3763 println!("NAN produced. Error in function pois_per");
3764 return f64::NAN as i32;
3765 }
3766 if q == 0.0 {
3767 return 0;
3768 }
3769 if q == 1.0 {
3770 return i32::MAX;
3771 }
3772
3773 while pois_cdf(x, lambda) < q {
3774 x += 1;
3775 }
3776 return x;
3777}
3778
3779
3780/// Random draw from `X ~ Pois(r, p)` distribution.
3781/// Sheldon Ross, Simulation, 2003
3782///
3783/// # Parameters
3784/// - `lambda > 0`
3785/// # Example
3786/// Suppose `X ~ Pois(lambda=2.5)`. Use
3787/// ```
3788/// use ruststat::pois_ran;
3789/// println!("Random draw: {}", pois_ran(2.5));
3790/// ```
3791pub fn pois_ran(lambda: f64) -> i32 {
3792
3793 if lambda <= 0.0 {
3794 println!("NAN produced. Error in function pois_ran");
3795 return f64::NAN as i32;
3796 }
3797
3798 let u = unif_ran(0.0, 1.0);
3799 let mut i = 0;
3800 let mut p = (-lambda).exp();
3801 let mut f = p;
3802 loop {
3803 if u < f {
3804 return i;
3805 }
3806 p = lambda*p / (i+1) as f64;
3807 f = f + p;
3808 i = i + 1;
3809 }
3810 // return 0;
3811 // let exp_lambda = (-lambda).exp(); //constant for terminating loop
3812 // let (mut u,mut prod,mut r): (f64, f64, i32);
3813 //
3814 // r = -1;
3815 // prod = 1.0;
3816 //
3817 // while (prod > exp_lambda) {
3818 // u = unif_ran(0.0, 1.0); //generate uniform variable
3819 // prod = prod * u; //update product
3820 // r += 1; //increase Poisson variable
3821 // }
3822 //
3823 // return r;
3824
3825 // let cdf = unif_ran(0.0, 1.0);
3826 // let mut x = 0;
3827 //
3828 // while pois_cdf(x, lambda) < cdf {
3829 // x += 1;
3830 // }
3831 // return x;
3832}
3833
3834
3835/// Save random draws from `X ~ Pois(lambda)` distribution into a `Vec`
3836///
3837/// # Parameters
3838/// - `lambda > 0`
3839/// # Example
3840/// Suppose `X ~ Pois(lambda=2.5)`. Use
3841/// ```
3842/// use ruststat::pois_ranvec;
3843/// println!("Random Vec: {:?}", pois_ranvec(10, 2.5));
3844/// ```
3845pub fn pois_ranvec(nn: i32, lambda: f64) -> Vec<i32> {
3846 let mut xvec: Vec<i32> = Vec::new();
3847 for _ in 0..nn {
3848 xvec.push(pois_ran(lambda));
3849 }
3850 return xvec;
3851}
3852
3853
3854
3855// ===========================================================================
3856// ===========================================================================
3857// Special Functions
3858// ===========================================================================
3859// ===========================================================================
3860
3861/// Incomplete beta function.
3862///
3863/// # Parameters
3864/// - `a > 0`
3865/// - `b > 0`
3866/// - `0 < x < 1`
3867/// # Example
3868/// Suppose `X ~ Beta(alpha=0.5, beta=2.0)`.
3869/// ```
3870/// use ruststat::betai;
3871/// println!("Incomplete beta function: {}", betai(0.7, 0.5, 2.0));
3872/// ```
3873pub fn betai(x: f64, a: f64, b: f64) -> f64 {
3874
3875 let bt: f64;
3876
3877 if x < 0.0 || x > 1.0 {
3878 println!("Bad x in function betai");
3879 return f64::NAN;
3880 }
3881 if x == 0.0 || x == 1.0 {
3882 bt=0.0;
3883 }
3884 else {
3885 bt=(gammaln(a+b)-gammaln(a)-gammaln(b) +
3886 a*x.ln() +
3887 b*(1.0-x).ln()).exp();
3888 }
3889 return if x < ((a + 1.0) / (a + b + 2.0)) {
3890 bt * betacf(x, a, b) / a
3891 } else {
3892 1.0 - bt * betacf(1.0 - x, b, a) / b
3893 }
3894}
3895
3896
3897fn betacf(x: f64, a: f64, b: f64) -> f64 {
3898 let imax = 100;
3899 let eps = 3.0e-7;
3900 let fpmin = 1.0e-30;
3901
3902 let mut m2: i32;
3903 let mut aa: f64;
3904 let mut c: f64;
3905 let mut d: f64;
3906 let mut del: f64;
3907 let mut h: f64;
3908 let qab: f64;
3909 let qam: f64;
3910 let qap: f64;
3911
3912 qab=a+b;
3913 qap=a+1.0;
3914 qam=a-1.0;
3915 c=1.0;
3916 d=1.0-qab*x/qap;
3917 if d.abs() < fpmin {
3918 d=fpmin;
3919 }
3920 d=1.0/d;
3921 h=d;
3922 for m in 1..=imax {
3923 m2=2*m;
3924 aa=(m as f64)*(b-m as f64)*x/((qam+m2 as f64)*(a+m2 as f64));
3925 d=1.0+aa*d;
3926 if d.abs() < fpmin {
3927 d=fpmin;
3928 }
3929 c=1.0+aa/c;
3930 if c.abs() < fpmin {
3931 c=fpmin;
3932 }
3933 d=1.0/d;
3934 h *= d*c;
3935 aa = -(a+m as f64)*(qab+m as f64)*x/((a+m2 as f64)*(qap+m2 as f64));
3936 d=1.0+aa*d;
3937 if d.abs() < fpmin {
3938 d=fpmin;
3939 }
3940 c=1.0+aa/c;
3941 if c.abs() < fpmin {
3942 c=fpmin;
3943 }
3944 d=1.0/d;
3945 del=d*c;
3946 h *= del;
3947 if (del-1.0).abs() < eps {
3948 break;
3949 }
3950 }
3951 // if (m > MAXIT) nrerror("a or b too big, or MAXIT too small in betacf");
3952 return h;
3953}
3954
3955
3956/// Log gamma function
3957/// - `x > 0`
3958pub fn gammaln(x: f64) -> f64 {
3959 let cof = vec![57.1562356658629235,-59.5979603554754912,
3960 14.1360979747417471,-0.491913816097620199,0.339946499848118887e-4,
3961 0.465236289270485756e-4,-0.983744753048795646e-4,0.158088703224912494e-3,
3962 -0.210264441724104883e-3,0.217439618115212643e-3,-0.164318106536763890e-3,
3963 0.844182239838527433e-4,-0.261908384015814087e-4,0.368991826595316234e-5];
3964
3965 if x <= 0.0 {
3966 println!("Bad argument in gammaln; returning f64::NAN");
3967 return f64::NAN;
3968 // panic!("bad ard in gammaln");
3969 }
3970
3971 let mut y= x;
3972 let z = x;
3973
3974 let mut tmp = z + 5.24218750000000000;
3975 tmp = (z + 0.5) * tmp.ln() - tmp;
3976 let mut ser = 0.999999999999997092;
3977 for j in 0..14 {
3978 ser += cof[j] / { y += 1.0; y};
3979 }
3980 return tmp + (2.5066282746310005 * ser / z).ln();
3981}
3982
3983
3984/// Gamma function
3985/// - `x > 0`
3986pub fn gamma(x: f64) -> f64 {
3987 return gammaln(x).exp();
3988}
3989
3990
3991/// Factorial (`i32`).
3992/// - `x = 1,2,3,...`
3993pub fn fact_i(x: i32) -> i32 {
3994 return if x > 1 {
3995 x * fact_i(x - 1)
3996 } else {
3997 1
3998 }
3999}
4000
4001
4002/// Log factorial (`i32`).
4003/// - `x = 1,2,3,...`
4004pub fn factln_i(x: i32) -> f64 {
4005 return if x > 1 {
4006 (x as f64).ln() + factln_i(x - 1)
4007 } else {
4008 0.0
4009 }
4010}
4011
4012
4013/// Generalized factorial (`f64`).
4014/// - `x > 0`
4015pub fn fact_f(x: f64) -> f64 {
4016 return if x > 1.0 {
4017 x * fact_f(x - 1.0)
4018 } else {
4019 x * gamma(x)
4020 }
4021}
4022
4023
4024/// Log Generalized factorial (`f64`).
4025/// - `x > 0`
4026pub fn factln_f(x: f64) -> f64 {
4027 return if x > 1.0 {
4028 x.ln() + fact_f(x - 1.0).ln()
4029 } else {
4030 x + gammaln(x)
4031 }
4032}
4033
4034
4035/// Combination
4036/// - `n = 0,1,2,...`
4037/// - `x = 0,1,2,...`
4038/// - `n >= x`
4039pub fn comb(n: i32, x: i32) -> f64 {
4040 return (0.5 + (factln_i(n) - factln_i(x) - factln_i(n-x)).exp()).floor();
4041}
4042
4043
4044/// Computes beta function.
4045/// - `a > 0`
4046/// - `b > 0`
4047pub fn beta_fn(a: f64, b:f64) -> f64 {
4048 return (gammaln(a) + gammaln(b) - gammaln(a+b)).exp();
4049}
4050
4051
4052/// Incomplete gamma function, series representation
4053pub fn gser(x: f64, a: f64) -> f64 {
4054 let imax = 100;
4055 let eps = 3.0e-7;
4056 // let fpmin = 1.0e-30;
4057 let gln = gammaln(a);
4058
4059 if x <= 0.0 {
4060 if x < 0.0 {
4061 println!("x less than 0 in routine gser");
4062 }
4063 return 0.0;
4064 }
4065 else {
4066 let mut ap = a;
4067 let mut del = 1.0 / a;
4068 let mut sum = 1.0 / a;
4069
4070 for _ in 1..imax {
4071 ap = ap + 1.0;
4072 del = del * x / ap;
4073 sum = sum + del;
4074 if del.abs() < sum.abs() * eps {
4075 return sum * (-x + a * x.ln() - gln).exp();
4076 }
4077 }
4078 println!("a too large, ITMAX too small in routine gser");
4079 }
4080 return 0.0;
4081}
4082
4083
4084/// Incomplete gamma function, continued fraction representation
4085pub fn gcf(x: f64, a: f64) -> f64 {
4086 let imax = 100;
4087 let eps = 3.0e-7;
4088 let fpmin = 1.0e-30;
4089
4090 let gln = gammaln(a);
4091 let mut b= x + 1.0 - a;
4092 let mut c = 1.0 / fpmin;
4093 let mut d= 1.0 / b;
4094 let mut h= d;
4095
4096 let mut an: f64;
4097 let mut del: f64;
4098
4099 for i in 1..=imax {
4100 an = -(i as f64) * (i as f64 - a);
4101 b += 2.0;
4102 d = an * d + b;
4103 if d.abs() < fpmin {
4104 d = fpmin;
4105 }
4106 c = b + an / c;
4107 if c.abs() < fpmin {
4108 c=fpmin;
4109 }
4110 d = 1.0 / d;
4111 del = d * c;
4112 h *= del;
4113 if (del-1.0).abs() < eps {
4114 break;
4115 }
4116 }
4117 // if (i > imax) {
4118 // println!("a too large, ITMAX too small in gcf");
4119 // }
4120
4121 return (-x + a * x.ln() - gln).exp() * h;
4122}
4123
4124
4125/// Incomplete gamma function `P(x,a)`
4126pub fn gammp(x: f64, a: f64) -> f64 {
4127 if x < 0.0 || a <= 0.0 {
4128 println ! ("Invalid arguments in routine gammp");
4129 }
4130 return if x < (a + 1.0) {
4131 gser(x, a)
4132 } else {
4133 1.0 - gcf(x, a)
4134 }
4135}
4136
4137
4138/// Complmentary incomplete gamma function `Q(x,a)`
4139pub fn gammq(x: f64, a: f64) -> f64 {
4140 if x < 0.0 || a <= 0.0 {
4141 println!("Invalid arguments in routine gammq");
4142 }
4143 return if x == 0.0 {
4144 1.0
4145 } else if a >= 100.0 {
4146 gammapprox(x, a)
4147 } else if x < (a + 1.0) {
4148 1.0 - gser(x, a)
4149 } else {
4150 gcf(x, a)
4151 }
4152}
4153
4154
4155/// Incomplete gamma function, quadrature `P(x,a)`
4156pub fn gammapprox(x: f64, a: f64) -> f64 {
4157
4158 const Y_VEC: [f64; 18] = [
4159 0.0021695375159141994, 0.011413521097787704,0.027972308950302116,
4160 0.051727015600492421, 0.082502225484340941, 0.12007019910960293,
4161 0.16415283300752470, 0.21442376986779355, 0.27051082840644336,
4162 0.33199876341447887, 0.39843234186401943, 0.46931971407375483,
4163 0.54413605556657973, 0.62232745288031077, 0.70331500465597174,
4164 0.78649910768313447, 0.87126389619061517, 0.95698180152629142];
4165 const W_VEC: [f64; 18] = [
4166 0.0055657196642445571, 0.012915947284065419, 0.020181515297735382,
4167 0.027298621498568734, 0.034213810770299537,0.040875750923643261,
4168 0.047235083490265582, 0.053244713977759692,0.058860144245324798,
4169 0.064039797355015485, 0.068745323835736408,0.072941885005653087,
4170 0.076598410645870640, 0.079687828912071670,0.082187266704339706,
4171 0.084078218979661945, 0.085346685739338721,0.085983275670394821];
4172
4173 let (xu,mut t,mut sum,ans,a1,lna1,sqrta1): (f64,f64,f64,f64,f64,f64,f64);
4174 a1 = a-1.0;
4175 lna1 = a1.ln();
4176 sqrta1 = a1.sqrt();
4177 if x > a1 {
4178 xu = f64::max(a1 + 11.5*sqrta1, x + 6.0*sqrta1);
4179 }
4180 else {
4181 xu = f64::max(0.0,f64::min(a1 - 7.5*sqrta1, x - 5.0*sqrta1));
4182 }
4183 sum = 0.0;
4184 for j in 0..18 { //Gauss-Legendre.
4185 t = x + (xu-x)*Y_VEC[j];
4186 sum += W_VEC[j]*(-(t-a1)+a1*(t.ln()-lna1)).exp();
4187 }
4188 ans = sum*(xu-x)*(a1*(a1.ln()-1.0)-gammaln(a)).exp();
4189
4190 return if ans >= 0.0 {
4191 ans
4192 } else {
4193 1.0 + ans
4194 }
4195}
4196
4197
4198
4199/// Error function (gammp implementation) `Erf(x)`
4200pub fn erf2(x: f64) -> f64 {
4201 return if x < 0.0 {
4202 -gammp(x * x, 0.5)
4203 } else {
4204 gammp(x * x, 0.5)
4205 }
4206}
4207
4208
4209
4210/// Inverse of incomplete beta function
4211/// - `0 < p < 1`
4212/// - `alpha > 0`
4213/// - `beta > 0`
4214pub fn betai_inv(p: f64, a:f64, b: f64) -> f64 {
4215 let eps = 1.0e-8;
4216 let (pp,mut t,mut u,mut err,mut x,al,h,w,afac,a1,b1,lna,lnb):
4217 (f64,f64,f64,f64,f64,f64,f64,f64,f64,f64,f64,f64,f64);
4218 a1=a-1.0;
4219 b1=b-1.0;
4220
4221 if p <= 0.0 {
4222 return 0.;
4223 }
4224 else if p >= 1.0 {
4225 return 1.0;
4226 }
4227 else if a >= 1.0 && b >= 1.0 {
4228 if p < 0.5 {
4229 pp = p
4230 }
4231 else {
4232 pp = 1.0 - p;
4233 }
4234 t = (-2.0*pp.ln()).sqrt();
4235 x = (2.30753 + t*0.27061) / (1.0 + t*(0.99229 + t*0.04481)) - t;
4236 if p < 0.5 {
4237 x = -x;
4238 }
4239 al = (x.powi(2)-3.0)/6.0;
4240 h = 2.0 / (1.0/(2.0*a-1.0)+1.0/(2.0*b-1.0));
4241 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));
4242 x = a/(a+b*(2.0*w).exp());
4243 }
4244 else {
4245 lna = (a/(a+b)).ln();
4246 lnb = (b/(a+b)).ln();
4247 t = (a*lna).exp()/a;
4248 u = (b*lnb).exp()/b;
4249 w = t + u;
4250 if p < t/w {
4251 x = (a*w*p).powf(1.0/a);
4252 }
4253 else {
4254 x = 1.0 - (b*w*(1.-p)).powf(1.0/b);
4255 }
4256 }
4257
4258 afac = -gammaln(a)-gammaln(b)+gammaln(a+b);
4259 for j in 0..10 {
4260 if x == 0.0 || x == 1.0 {
4261 return x;
4262 }
4263 err = betai(x, a, b) - p;
4264 t = (a1 * x.ln() + b1 * (1.0 - x).ln() + afac).exp();
4265 u = err / t;
4266 t = u / (1.0 - 0.5 * f64::min(1.0, u * (a1 / x - b1 / (1.0 - x))));
4267 x -= t;
4268 // x -= (t = u / (1. - 0.5 * MIN(1., u * (a1 / x - b1 / (1. - x)))));
4269 if x <= 0.0 {
4270 x = 0.5 * (x + t);
4271 }
4272 if x >= 1.0 {
4273 x = 0.5 * (x + t + 1.0);
4274 }
4275 if t.abs() < eps*x && j>0 {
4276 break;
4277 }
4278 }
4279
4280 return x;
4281}
4282
4283
4284
4285
4286/// Inverse of incomplete gamma function
4287/// - `0 < p < 1`
4288/// - `alpha > 0`
4289pub fn gammai_inv(p: f64, alpha:f64) -> f64 {
4290 let (mut x,mut err,mut t,mut u,pp,lna1,afac,a1): (f64,f64,f64,f64,f64,f64,f64,f64);
4291 a1 = alpha-1.0;
4292
4293 let eps = 1.0e-8; // Accuracy is the square of eps.
4294 let gln = gammaln(alpha);
4295
4296 if alpha <= 0.0 {
4297 println!("a must be pos in invgammap");
4298 }
4299 if p >= 1.0 {
4300 return f64::max(100.0,alpha + 100.0*alpha.sqrt());
4301 }
4302 if p <= 0.0 {
4303 return 0.0;
4304 }
4305 lna1 = a1.ln();
4306 afac = (a1*(lna1-1.0)-gln).exp();
4307 if alpha > 1.0 {
4308 if p < 0.5 {
4309 pp = p;
4310 }
4311 else {
4312 pp = 1.0 - p;
4313 }
4314 t = (-2.0*pp.ln()).sqrt();
4315 x = (2.30753+t*0.27061) /
4316 (1.0+t*(0.99229+t*0.04481)) - t;
4317 if p < 0.5 {
4318 x = -x;
4319 }
4320 x = f64::max(1.0e-3,alpha*(1.-1./(9.*alpha)-x/(3.*alpha.sqrt()).powi(3)));
4321 }
4322 else {
4323 t = 1.0 - alpha*(0.253+alpha*0.12);
4324 if p < t {
4325 x = (p/t).powf(1.0/alpha);
4326 }
4327 else {
4328 x = 1.0-(1.0-(p-t)/(1.0-t)).ln();
4329 }
4330 }
4331
4332 for _ in 0..12 {
4333 if x <= 0.0 {
4334 return 0.0;
4335 }
4336 err = gammp(x,alpha) - p;
4337 if alpha > 1.0 {
4338 t = afac*(-(x-a1)+a1*(x.ln()-lna1)).exp();
4339 }
4340 else {
4341 t = (-x+a1*x.ln()-gln).exp();
4342 }
4343 u = err/t;
4344 t = u/(1.0-0.5*f64::min(1.0,u*((alpha-1.0)/x - 1.0)));
4345 x -= t; //Halley’s method.
4346 if x <= 0.0 {
4347 x = 0.5*(x + t);
4348 } //Halve old value if x tries to go negative.
4349 if t.abs() < eps *x {
4350 break;
4351 }
4352 }
4353
4354 return x;
4355}
4356
4357
4358
4359
4360
4361/// Chebyshev coefficients
4362fn erfc_cheb(z: f64) -> f64 {
4363
4364 const NCOEF: usize = 28;
4365 const COEF: [f64; 28] = [
4366 -1.3026537197817094, 6.4196979235649026e-1, 1.9476473204185836e-2, -9.561514786808631e-3,
4367 -9.46595344482036e-4, 3.66839497852761e-4, 4.2523324806907e-5, -2.0278578112534e-5,
4368 -1.624290004647e-6, 1.303655835580e-6, 1.5626441722e-8, -8.5238095915e-8,
4369 6.529054439e-9, 5.059343495e-9, -9.91364156e-10, -2.27365122e-10,
4370 9.6467911e-11, 2.394038e-12, -6.886027e-12, 8.94487e-13,
4371 3.13092e-13, -1.12708e-13, 3.81e-16, 7.106e-15,
4372 -1.523e-15, -9.4e-17, 1.21e-16,-2.8e-17 ];
4373
4374 let (mut d, mut dd, t, ty, mut tmp) : (f64, f64, f64, f64, f64);
4375 d = 0.0;
4376 dd = 0.0;
4377
4378 assert!(z >= 0f64, "erfccheb requires nonnegative argument");
4379 t = 2.0 / (2.0 + z);
4380 ty = 4.0 * t - 2.0;
4381 for j in (1..NCOEF-1).rev() {
4382 tmp = d;
4383 d = ty * d - dd + COEF[j];
4384 dd = tmp;
4385 }
4386 return t * (-z.powi(2) + 0.5 * (COEF[0] + ty * d) - dd).exp();
4387}
4388
4389
4390/// Error function (Chebyshev implementation)
4391pub fn erf(x: f64) -> f64 {
4392 return if x >= 0.0 {
4393 1.0 - erfc_cheb(x)
4394 } else {
4395 erfc_cheb(-x) - 1.0
4396 }
4397}
4398
4399/// Complementary error function
4400pub fn erfc(x: f64) -> f64 {
4401 return if x >= 0.0 {
4402 erfc_cheb(x)
4403 } else {
4404 2.0 - erfc_cheb(-x)
4405 }
4406}
4407
4408/// Inverse of complementary error function
4409pub fn erfc_inv(p: f64) -> f64 {
4410
4411 let (pp, t, mut x): (f64, f64, f64);
4412
4413 // Return arbitrary large pos or neg value
4414 if p >= 2.0 {
4415 return -100.0;
4416 }
4417 else if p <= 0.0 {
4418 return 100.0;
4419 }
4420
4421 if p < 1.0 {
4422 pp = p
4423 }
4424 else {
4425 pp = 2.0 - p;
4426 }
4427
4428 t = (-2.0 * (pp / 2.0).ln()).sqrt();
4429 x = -std::f64::consts::FRAC_1_SQRT_2 * ((2.30753 + t * 0.27061) /
4430 (1f64 + t * (0.99229 + t * 0.04481)) - t);
4431 for _ in 0..2 {
4432 let err = erfc(x) - pp;
4433 x += err / (std::f64::consts::FRAC_2_SQRT_PI * (-x.powi(2)).exp() - x * err);
4434 }
4435 return if p < 1.0 {
4436 x
4437 } else {
4438 -x
4439 }
4440}
4441
4442/// Inverse of error function
4443pub fn erf_inv(p: f64) -> f64 {
4444 return erfc_inv(1.0 - p);
4445}
4446
4447
4448
4449
4450
4451// const NN: usize = 10; // number of terms in the Chebyshev series
4452
4453
4454
4455
4456
4457
4458///////////////////////////////
4459// Depreciated root finder code
4460///////////////////////////////
4461// let f = |x| { beta_cdf(x,alpha,beta) - q };
4462// let eps = 1.0e-15;
4463// let mut convergency = SimpleConvergency { eps, max_iter:30 };
4464//
4465// let percentile = find_root_secant(0.8, 0.999, &f, &mut convergency);
4466//
4467// if q < 0.0 || q > 1.0 || alpha <= 0.0 || beta <= 0.0 || percentile.is_err() {
4468// println!("Error in function gamma_percentile");
4469// return f64::NAN;
4470// }
4471//
4472// return percentile.unwrap();
4473
4474
4475
4476#[cfg(test)]
4477mod tests {
4478 use super::*;
4479
4480
4481#[test]
4482 pub fn it_works() {
4483 // let result = add(2, 2);
4484 // assert_eq!(result, 4);
4485 println!("It works!!");
4486
4487 println!("\nBeta");
4488 println!("pdf: {}", beta_pdf(0.7,0.5,1.5));
4489 println!("cdf: {}", beta_cdf(0.7,0.5,1.5));
4490 println!("per: {}", beta_per(0.1,0.5,1.5));
4491 println!("ran: {}", beta_ran(0.5,1.5));
4492 println!("ran_vec: {:?}", beta_ranvec(3,0.5, 1.5));
4493 let mut mybeta = BetaDist{alpha:0.5, beta:1.5};
4494 println!("pdf: {}", mybeta.pdf(0.7));
4495 println!("cdf: {}", mybeta.cdf(0.7));
4496 println!("per: {}", mybeta.per(0.1));
4497 println!("ran: {}", mybeta.ran());
4498 println!("ranvec: {:?}", mybeta.ranvec(5));
4499 println!("mean: {}", mybeta.mean());
4500 println!("var: {}", mybeta.var());
4501 println!("sd: {}", mybeta.sd());
4502 println!("---------------------");
4503
4504 println!("\nChi-Square");
4505 println!("pdf: {}", chisq_pdf(0.7,1.5));
4506 println!("cdf: {}", chisq_cdf(0.7,1.5));
4507 println!("per: {}", chisq_per(0.1,1.5));
4508 println!("ran: {}", chisq_ran(1.5));
4509 println!("ran_vec: {:?}", chisq_ranvec(3,1.5));
4510 let mut mychisq = ChiSqDist{nu:1.5};
4511 println!("pdf: {}", mychisq.pdf(0.7));
4512 println!("cdf: {}", mychisq.cdf(0.7));
4513 println!("per: {}", mychisq.per(0.1));
4514 println!("ran: {}", mychisq.ran());
4515 println!("ranvec: {:?}", mychisq.ranvec(5));
4516 println!("mean: {}", mychisq.mean());
4517 println!("var: {}", mychisq.var());
4518 println!("sd: {}", mychisq.sd());
4519 println!("---------------------");
4520
4521 println!("\nExp");
4522 println!("pdf: {}", exp_pdf(0.7,1.5));
4523 println!("cdf: {}", exp_cdf(0.7,1.5));
4524 println!("per: {}", exp_per(0.1,1.5));
4525 println!("ran: {}", exp_ran(1.5));
4526 println!("ran_vec: {:?}", exp_ranvec(3,1.5));
4527 let mut myexp = ExpDist{lambda:1.5};
4528 println!("pdf: {}", myexp.pdf(0.7));
4529 println!("cdf: {}", myexp.cdf(0.7));
4530 println!("per: {}", myexp.per(0.1));
4531 println!("ran: {}", myexp.ran());
4532 println!("ranvec: {:?}", myexp.ranvec(5));
4533 println!("mean: {}", myexp.mean());
4534 println!("var: {}", myexp.var());
4535 println!("sd: {}", myexp.sd());
4536 println!("---------------------");
4537
4538 println!("\nF Dist");
4539 println!("pdf: {}", f_pdf(0.7,1.5, 4.5));
4540 println!("cdf: {}", f_cdf(0.7,1.5, 4.5));
4541 println!("per: {}", f_per(0.1,1.5, 4.5));
4542 println!("ran: {}", f_ran(1.5, 4.5));
4543 println!("ran_vec: {:?}", f_ranvec(3,1.5, 4.5));
4544 let mut mydist = FDist{nu1:1.5, nu2:4.5};
4545 println!("pdf: {}", mydist.pdf(0.7));
4546 println!("cdf: {}", mydist.cdf(0.7));
4547 println!("per: {}", mydist.per(0.1));
4548 println!("ran: {}", mydist.ran());
4549 println!("ranvec: {:?}", mydist.ranvec(5));
4550 println!("mean: {}", mydist.mean());
4551 println!("var: {}", mydist.var());
4552 println!("sd: {}", mydist.sd());
4553 println!("---------------------");
4554
4555 println!("\nGamma Dist");
4556 println!("pdf: {}", gamma_pdf(0.7,1.5, 4.5));
4557 println!("cdf: {}", gamma_cdf(0.7,1.5, 4.5));
4558 println!("per: {}", gamma_per(0.1,1.5, 4.5));
4559 println!("ran: {}", gamma_ran(1.5, 4.5));
4560 println!("ran_vec: {:?}", gamma_ranvec(3,1.5, 4.5));
4561 let mut mydist = GammaDist{alpha:1.5, beta:4.5};
4562 println!("pdf: {}", mydist.pdf(0.7));
4563 println!("cdf: {}", mydist.cdf(0.7));
4564 println!("per: {}", mydist.per(0.99));
4565 println!("ran: {}", mydist.ran());
4566 println!("ranvec: {:?}", mydist.ranvec(5));
4567 println!("mean: {}", mydist.mean());
4568 println!("var: {}", mydist.var());
4569 println!("sd: {}", mydist.sd());
4570 println!("---------------------");
4571
4572 println!("\nLog-Normal");
4573 println!("pdf: {}", lognormal_pdf(0.7,1.5, 4.5));
4574 println!("cdf: {}", lognormal_cdf(0.7,1.5, 4.5));
4575 println!("per: {}", lognormal_per(0.1,1.5, 4.5));
4576 println!("ran: {}", lognormal_ran(1.5, 4.5));
4577 println!("ran_vec: {:?}", lognormal_ranvec(3,1.5, 5.5));
4578 let mut mydist = LogNormalDist{mu:1.5, sigma:4.5};
4579 println!("pdf: {}", mydist.pdf(0.7));
4580 println!("cdf: {}", mydist.cdf(0.7));
4581 println!("per: {}", mydist.per(0.99));
4582 println!("ran: {}", mydist.ran());
4583 println!("ranvec: {:?}", mydist.ranvec(5));
4584 println!("mean: {}", mydist.mean());
4585 println!("var: {}", mydist.var());
4586 println!("sd: {}", mydist.sd());
4587 println!("---------------------");
4588
4589 println!("\nNormal");
4590 println!("pdf: {}", normal_pdf(0.7,1.5, 4.5));
4591 println!("cdf: {}", normal_cdf(0.7,1.5, 4.5));
4592 println!("per: {}", normal_per(0.1,1.5, 4.5));
4593 println!("ran: {}", normal_ran(1.5, 4.5));
4594 println!("ran_vec: {:?}", normal_ranvec(3,1.5, 4.5));
4595 let mut mydist = NormalDist{mu:1.5, sigma:4.5};
4596 println!("pdf: {}", mydist.pdf(0.7));
4597 println!("cdf: {}", mydist.cdf(0.7));
4598 println!("per: {}", mydist.per(0.99));
4599 println!("ran: {}", mydist.ran());
4600 println!("ranvec: {:?}", mydist.ranvec(5));
4601 println!("mean: {}", mydist.mean());
4602 println!("var: {}", mydist.var());
4603 println!("sd: {}", mydist.sd());
4604 println!("---------------------");
4605
4606 println!("\nt Dist");
4607 println!("pdf: {}", t_pdf(0.7,4.5));
4608 println!("cdf: {}", t_cdf(0.7,4.5));
4609 println!("per: {}", t_per(0.1,4.5));
4610 println!("ran: {}", t_ran(4.5));
4611 println!("ran_vec: {:?}", t_ranvec(3,4.5));
4612 let mut mydist = TDist{nu:4.5};
4613 println!("pdf: {}", mydist.pdf(0.7));
4614 println!("cdf: {}", mydist.cdf(0.7));
4615 println!("per: {}", mydist.per(0.99));
4616 println!("ran: {}", mydist.ran());
4617 println!("ranvec: {:?}", mydist.ranvec(5));
4618 println!("mean: {}", mydist.mean());
4619 println!("var: {}", mydist.var());
4620 println!("sd: {}", mydist.sd());
4621 println!("---------------------");
4622
4623 println!("\nUhif");
4624 println!("pdf: {}", unif_pdf(1.7,1.5, 4.5));
4625 println!("cdf: {}", unif_cdf(1.7,1.5, 4.5));
4626 println!("per: {}", unif_per(0.1,1.5, 4.5));
4627 println!("ran: {}", unif_ran(1.5, 4.5));
4628 println!("ran_vec: {:?}", unif_ranvec(3,1.5, 4.5));
4629 let mut mydist = UnifDist{a:1.5, b:4.5};
4630 println!("pdf: {}", mydist.pdf(0.7));
4631 println!("cdf: {}", mydist.cdf(0.7));
4632 println!("per: {}", mydist.per(0.99));
4633 println!("ran: {}", mydist.ran());
4634 println!("ranvec: {:?}", mydist.ranvec(5));
4635 println!("mean: {}", mydist.mean());
4636 println!("var: {}", mydist.var());
4637 println!("sd: {}", mydist.sd());
4638 println!("---------------------");
4639
4640 println!("\nBinomial");
4641 println!("bin_pmf: {}", bin_pmf(99,100,0.9));
4642 println!("bin_cdf: {}", bin_cdf(99,100,0.9));
4643 println!("bin_per: {}", bin_per(1.0,100,0.9));
4644 println!("bin_ran: {}", bin_ran(100,0.9));
4645 println!("ran_vec: {:?}", bin_ranvec(3,100, 0.9));
4646 let mut mybin = BinDist{n:100, p:0.9};
4647 println!("bin pmf: {}", mybin.pmf(80));
4648 println!("bin cdf: {}", mybin.cdf(80));
4649 println!("bin per: {}", mybin.per(0.99));
4650 println!("bin ran: {}", mybin.ran());
4651 println!("ranvec: {:?}", mybin.ranvec(5));
4652 println!("bin mean: {}", mybin.mean());
4653 println!("bin var: {}", mybin.var());
4654 println!("bin sd: {}", mybin.sd());
4655
4656 println!("\nGeo");
4657 println!("geo_pmf: {}", geo_pmf(0,0.05));
4658 println!("geo_cdf: {}", geo_cdf(0,0.05));
4659 println!("geo_per: {}", geo_per(1.0,0.05));
4660 println!("geo_ran: {}", geo_ran(0.05));
4661 println!("ran_vec: {:?}", geo_ranvec(3,0.05));
4662 let mut mygeo = GeoDist{p:0.05};
4663 println!("geo pmf: {}", mygeo.pmf(2));
4664 println!("geo cdf: {}", mygeo.cdf(2));
4665 println!("geo per: {}", mygeo.per(0.99));
4666 println!("geo ran: {}", mygeo.ran());
4667 println!("ranvec: {:?}", mygeo.ranvec(5));
4668 println!("geo mean: {}", mygeo.mean());
4669 println!("geo var: {}", mygeo.var());
4670 println!("geo sd: {}", mygeo.sd());
4671
4672
4673 println!("\nGeo2");
4674 println!("geo2_pmf: {}", geo2_pmf(1,0.05));
4675 println!("geo2_cdf: {}", geo2_cdf(1,0.05));
4676 println!("geo2_per: {}", geo2_per(0.99,0.05));
4677 println!("geo2_ran: {}", geo2_ran(0.05));
4678 println!("ran_vec: {:?}", geo2_ranvec(3,0.05));
4679 let mut mygeo2 = Geo2Dist{p:0.05};
4680 println!("geo2 pmf: {}", mygeo2.pmf(2));
4681 println!("geo2 cdf: {}", mygeo2.cdf(2));
4682 println!("geo2 per: {}", mygeo2.per(0.99));
4683 println!("geo2 ran: {}", mygeo2.ran());
4684 println!("ranvec: {:?}", mygeo2.ranvec(5));
4685 println!("geo2 mean: {}", mygeo2.mean());
4686 println!("geo2 var: {}", mygeo2.var());
4687 println!("geo2 sd: {}", mygeo2.sd());
4688
4689
4690 println!("\nHG");
4691 println!("hg_pmf: {}", hg_pmf(80,100,1000, 900));
4692 println!("hg_cdf: {}", hg_cdf(80,100,1000, 900));
4693 println!("hg_per: {}", hg_per(0.26,100,1000, 900));
4694 println!("hg_ran: {}", hg_ran(100,1000, 900));
4695 println!("ran_vec: {:?}", hg_ranvec(3,100, 1000, 900));
4696 let mut myhg = HGDist{n:100, N:1000, M:900};
4697 println!("hg pmf: {}", myhg.pmf(80));
4698 println!("hg cdf: {}", myhg.cdf(80));
4699 println!("hg per: {}", myhg.per(0.26));
4700 println!("hg ran: {}", myhg.ran());
4701 println!("ranvec: {:?}", myhg.ranvec(5));
4702 println!("hg mean: {}", myhg.mean());
4703 println!("hg var: {}", myhg.var());
4704 println!("hg sd: {}", myhg.sd());
4705
4706
4707 println!("\nNB");
4708 println!("NB_pmf: {}", nb_pmf(10,5, 0.1));
4709 println!("NB_cdf: {}", nb_cdf(10,5, 0.1));
4710 println!("NB_per: {}", nb_per(0.0,5, 0.1));
4711 println!("NB_ran: {}", nb_ran(5, 0.1));
4712 println!("ran_vec: {:?}", nb_ranvec(3,5, 0.1));
4713 let mut mynb = NBDist{r: 5, p:0.1};
4714 println!("NB pmf: {}", mynb.pmf(2));
4715 println!("NB cdf: {}", mynb.cdf(2));
4716 println!("NB per: {}", mynb.per(0.99));
4717 println!("NB ran: {}", mynb.ran());
4718 println!("ranvec: {:?}", mynb.ranvec(5));
4719 println!("NB mean: {}", mynb.mean());
4720 println!("NB var: {}", mynb.var());
4721 println!("NB sd: {}", mynb.sd());
4722
4723
4724 println!("\nNB2");
4725 println!("NB2_pmf: {}", nb2_pmf(10,5, 0.1));
4726 println!("NB2_cdf: {}", nb2_cdf(10,5, 0.1));
4727 println!("NB2_per: {}", nb2_per(1.0,5, 0.1));
4728 println!("NB2_ran: {}", nb2_ran(5, 0.1));
4729 println!("ran_vec: {:?}", nb2_ranvec(3,5, 0.1));
4730 let mut mynb2 = NB2Dist{r: 5, p:0.1};
4731 println!("NB2 pmf: {}", mynb2.pmf(2));
4732 println!("NB2 cdf: {}", mynb2.cdf(2));
4733 println!("NB2 per: {}", mynb2.per(0.99));
4734 println!("NB2 ran: {}", mynb2.ran());
4735 println!("ranvec: {:?}", mynb2.ranvec(5));
4736 println!("NB2 mean: {}", mynb2.mean());
4737 println!("NB2 var: {}", mynb2.var());
4738 println!("NB2 sd: {}", mynb2.sd());
4739
4740
4741 println!("\nPois");
4742 println!("pois_pmf: {}", pois_pmf(3,2.0));
4743 println!("pois_cdf: {}", pois_cdf(3,2.0));
4744 println!("pois_per: {}", pois_per(1.0,2.0));
4745 println!("pois_ran: {}", pois_ran(2.0));
4746 println!("ran_vec: {:?}", pois_ranvec(3,2.0));
4747 let mut mypois = PoisDist{lambda: 2.0};
4748 println!("pois pmf: {}", mypois.pmf(3));
4749 println!("pois cdf: {}", mypois.cdf(3));
4750 println!("pois per: {}", mypois.per(0.26));
4751 println!("pois ran: {}", mypois.ran());
4752 println!("ranvec: {:?}", mypois.ranvec(5));
4753 println!("pois mean: {}", mypois.mean());
4754 println!("pois var: {}", mypois.var());
4755 println!("pois sd: {}", mypois.sd());
4756
4757
4758 // use t_ran;
4759 // let mut vec = Vec::new();
4760 //
4761 // let iter: usize = 1000000;
4762 // for _ in 0..iter {
4763 // vec.push(t_ran(3.0));
4764 // }
4765 //
4766 // let mut mean: f64 = vec.iter().sum();
4767 // mean = mean / (iter as f64);
4768 //
4769 // let mut var: f64 = vec.iter().map(|x| (x-mean).powi(2) ).sum();
4770 // var = var / ((iter - 1) as f64);
4771 //
4772 // println!("Mean: {}", mean);
4773 // println!("Var: {}", var);
4774
4775
4776 use crate::erf;
4777 println!("\nerf: {}", erf(1.0));
4778 use crate::erf2;
4779 println!("erf2: {}", erf2(1.0));
4780 }
4781}