1use pyo3::exceptions::PyRuntimeError;
6use pyo3::prelude::*;
7use scirs2_stats::distributions::beta::Beta as RustBeta;
8use scirs2_stats::distributions::binomial::Binomial as RustBinomial;
9use scirs2_stats::distributions::cauchy::Cauchy as RustCauchy;
10use scirs2_stats::distributions::chi_square::ChiSquare as RustChiSquare;
11use scirs2_stats::distributions::exponential::Exponential as RustExponential;
12use scirs2_stats::distributions::f::F as RustF;
13use scirs2_stats::distributions::gamma::Gamma as RustGamma;
14use scirs2_stats::distributions::geometric::Geometric as RustGeometric;
15use scirs2_stats::distributions::laplace::Laplace as RustLaplace;
16use scirs2_stats::distributions::logistic::Logistic as RustLogistic;
17use scirs2_stats::distributions::lognormal::Lognormal as RustLognormal;
18use scirs2_stats::distributions::normal::Normal as RustNormal;
19use scirs2_stats::distributions::pareto::Pareto as RustPareto;
20use scirs2_stats::distributions::poisson::Poisson as RustPoisson;
21use scirs2_stats::distributions::student_t::StudentT as RustStudentT;
22use scirs2_stats::distributions::uniform::Uniform as RustUniform;
23use scirs2_stats::distributions::weibull::Weibull as RustWeibull;
24use scirs2_stats::{ContinuousDistribution, DiscreteDistribution};
25
26#[pyclass(name = "chi2")]
28pub struct PyChiSquare {
29 dist: RustChiSquare<f64>,
30}
31#[pymethods]
32impl PyChiSquare {
33 #[new]
40 #[pyo3(signature = (df, loc = 0.0, scale = 1.0))]
41 fn new(df: f64, loc: f64, scale: f64) -> PyResult<Self> {
42 let dist = RustChiSquare::new(df, loc, scale).map_err(|e| {
43 PyRuntimeError::new_err(format!("Chi-square distribution creation failed: {}", e))
44 })?;
45 Ok(PyChiSquare { dist })
46 }
47 fn pdf(&self, x: f64) -> f64 {
49 self.dist.pdf(x)
50 }
51 fn cdf(&self, x: f64) -> f64 {
53 self.dist.cdf(x)
54 }
55 fn ppf(&self, q: f64) -> PyResult<f64> {
57 self.dist
58 .ppf(q)
59 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
60 }
61 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
63 let arr = self
64 .dist
65 .rvs(size)
66 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
67 Ok(arr.to_vec())
68 }
69}
70#[pyclass(name = "binom")]
72pub struct PyBinomial {
73 dist: RustBinomial<f64>,
74}
75#[pymethods]
76impl PyBinomial {
77 #[new]
83 fn new(n: usize, p: f64) -> PyResult<Self> {
84 let dist = RustBinomial::new(n, p).map_err(|e| {
85 PyRuntimeError::new_err(format!("Binomial distribution creation failed: {}", e))
86 })?;
87 Ok(PyBinomial { dist })
88 }
89 fn pmf(&self, k: f64) -> f64 {
91 self.dist.pmf(k)
92 }
93 fn cdf(&self, k: f64) -> f64 {
95 self.dist.cdf(k)
96 }
97 fn ppf(&self, q: f64) -> PyResult<f64> {
99 self.dist
100 .ppf(q)
101 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
102 }
103 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
105 let arr = self
106 .dist
107 .rvs(size)
108 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
109 Ok(arr.to_vec())
110 }
111}
112#[pyclass(name = "geom")]
114pub struct PyGeometric {
115 dist: RustGeometric<f64>,
116}
117#[pymethods]
118impl PyGeometric {
119 #[new]
124 fn new(p: f64) -> PyResult<Self> {
125 let dist = RustGeometric::new(p).map_err(|e| {
126 PyRuntimeError::new_err(format!("Geometric distribution creation failed: {}", e))
127 })?;
128 Ok(PyGeometric { dist })
129 }
130 fn pmf(&self, k: f64) -> f64 {
132 self.dist.pmf(k)
133 }
134 fn cdf(&self, k: f64) -> f64 {
136 self.dist.cdf(k)
137 }
138 fn ppf(&self, q: f64) -> PyResult<f64> {
140 self.dist
141 .ppf(q)
142 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
143 }
144 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
146 let arr = self
147 .dist
148 .rvs(size)
149 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
150 Ok(arr.to_vec())
151 }
152}
153#[pyclass(name = "lognorm")]
155pub struct PyLognormal {
156 dist: RustLognormal<f64>,
157}
158#[pymethods]
159impl PyLognormal {
160 #[new]
167 #[pyo3(signature = (mu = 0.0, sigma = 1.0, loc = 0.0))]
168 fn new(mu: f64, sigma: f64, loc: f64) -> PyResult<Self> {
169 let dist = RustLognormal::new(mu, sigma, loc).map_err(|e| {
170 PyRuntimeError::new_err(format!("Lognormal distribution creation failed: {}", e))
171 })?;
172 Ok(PyLognormal { dist })
173 }
174 fn pdf(&self, x: f64) -> f64 {
176 self.dist.pdf(x)
177 }
178 fn cdf(&self, x: f64) -> f64 {
180 self.dist.cdf(x)
181 }
182 fn ppf(&self, q: f64) -> PyResult<f64> {
184 self.dist
185 .ppf(q)
186 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
187 }
188 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
190 let arr = self
191 .dist
192 .rvs(size)
193 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
194 Ok(arr.to_vec())
195 }
196}
197#[pyclass(name = "weibull_min")]
199pub struct PyWeibull {
200 dist: RustWeibull<f64>,
201}
202#[pymethods]
203impl PyWeibull {
204 #[new]
211 #[pyo3(signature = (shape, scale = 1.0, loc = 0.0))]
212 fn new(shape: f64, scale: f64, loc: f64) -> PyResult<Self> {
213 let dist = RustWeibull::new(shape, scale, loc).map_err(|e| {
214 PyRuntimeError::new_err(format!("Weibull distribution creation failed: {}", e))
215 })?;
216 Ok(PyWeibull { dist })
217 }
218 fn pdf(&self, x: f64) -> f64 {
220 self.dist.pdf(x)
221 }
222 fn cdf(&self, x: f64) -> f64 {
224 self.dist.cdf(x)
225 }
226 fn ppf(&self, q: f64) -> PyResult<f64> {
228 self.dist
229 .ppf(q)
230 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
231 }
232 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
234 let arr = self
235 .dist
236 .rvs(size)
237 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
238 Ok(arr.to_vec())
239 }
240}
241#[pyclass(name = "gamma")]
243pub struct PyGamma {
244 dist: RustGamma<f64>,
245}
246#[pymethods]
247impl PyGamma {
248 #[new]
255 #[pyo3(signature = (shape, scale = 1.0, loc = 0.0))]
256 fn new(shape: f64, scale: f64, loc: f64) -> PyResult<Self> {
257 let dist = RustGamma::new(shape, scale, loc).map_err(|e| {
258 PyRuntimeError::new_err(format!("Gamma distribution creation failed: {}", e))
259 })?;
260 Ok(PyGamma { dist })
261 }
262 fn pdf(&self, x: f64) -> f64 {
264 self.dist.pdf(x)
265 }
266 fn cdf(&self, x: f64) -> f64 {
268 self.dist.cdf(x)
269 }
270 fn ppf(&self, q: f64) -> PyResult<f64> {
272 self.dist
273 .ppf(q)
274 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
275 }
276 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
278 let arr = self
279 .dist
280 .rvs(size)
281 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
282 Ok(arr.to_vec())
283 }
284}
285#[pyclass(name = "logistic")]
287pub struct PyLogistic {
288 dist: RustLogistic<f64>,
289}
290#[pymethods]
291impl PyLogistic {
292 #[new]
298 #[pyo3(signature = (loc = 0.0, scale = 1.0))]
299 fn new(loc: f64, scale: f64) -> PyResult<Self> {
300 let dist = RustLogistic::new(loc, scale).map_err(|e| {
301 PyRuntimeError::new_err(format!("Logistic distribution creation failed: {}", e))
302 })?;
303 Ok(PyLogistic { dist })
304 }
305 fn pdf(&self, x: f64) -> f64 {
307 self.dist.pdf(x)
308 }
309 fn cdf(&self, x: f64) -> f64 {
311 self.dist.cdf(x)
312 }
313 fn ppf(&self, q: f64) -> PyResult<f64> {
315 self.dist
316 .ppf(q)
317 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
318 }
319 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
321 let arr = self
322 .dist
323 .rvs(size)
324 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
325 Ok(arr.to_vec())
326 }
327}
328#[pyclass(name = "poisson")]
330pub struct PyPoisson {
331 dist: RustPoisson<f64>,
332}
333#[pymethods]
334impl PyPoisson {
335 #[new]
340 fn new(mu: f64) -> PyResult<Self> {
341 let dist = RustPoisson::new(mu, 0.0).map_err(|e| {
342 PyRuntimeError::new_err(format!("Poisson distribution creation failed: {}", e))
343 })?;
344 Ok(PyPoisson { dist })
345 }
346 fn pmf(&self, k: f64) -> f64 {
348 self.dist.pmf(k)
349 }
350 fn cdf(&self, k: f64) -> f64 {
352 self.dist.cdf(k)
353 }
354 fn ppf(&self, q: f64) -> PyResult<f64> {
356 self.dist
357 .ppf(q)
358 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
359 }
360 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
362 let arr = self
363 .dist
364 .rvs(size)
365 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
366 Ok(arr.to_vec())
367 }
368}
369#[pyclass(name = "t")]
371pub struct PyStudentT {
372 dist: RustStudentT<f64>,
373}
374#[pymethods]
375impl PyStudentT {
376 #[new]
383 #[pyo3(signature = (df, loc = 0.0, scale = 1.0))]
384 fn new(df: f64, loc: f64, scale: f64) -> PyResult<Self> {
385 let dist = RustStudentT::new(df, loc, scale).map_err(|e| {
386 PyRuntimeError::new_err(format!("Student's t distribution creation failed: {}", e))
387 })?;
388 Ok(PyStudentT { dist })
389 }
390 fn pdf(&self, x: f64) -> f64 {
392 self.dist.pdf(x)
393 }
394 fn cdf(&self, x: f64) -> f64 {
396 self.dist.cdf(x)
397 }
398 fn ppf(&self, q: f64) -> PyResult<f64> {
400 self.dist
401 .ppf(q)
402 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
403 }
404 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
406 let arr = self
407 .dist
408 .rvs(size)
409 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
410 Ok(arr.to_vec())
411 }
412}
413#[pyclass(name = "pareto")]
415pub struct PyPareto {
416 dist: RustPareto<f64>,
417}
418#[pymethods]
419impl PyPareto {
420 #[new]
427 #[pyo3(signature = (shape, scale = 1.0, loc = 0.0))]
428 fn new(shape: f64, scale: f64, loc: f64) -> PyResult<Self> {
429 let dist = RustPareto::new(shape, scale, loc).map_err(|e| {
430 PyRuntimeError::new_err(format!("Pareto distribution creation failed: {}", e))
431 })?;
432 Ok(PyPareto { dist })
433 }
434 fn pdf(&self, x: f64) -> f64 {
436 self.dist.pdf(x)
437 }
438 fn cdf(&self, x: f64) -> f64 {
440 self.dist.cdf(x)
441 }
442 fn ppf(&self, q: f64) -> PyResult<f64> {
444 self.dist
445 .ppf(q)
446 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
447 }
448 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
450 let arr = self
451 .dist
452 .rvs(size)
453 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
454 Ok(arr.to_vec())
455 }
456}
457#[pyclass(name = "expon")]
459pub struct PyExponential {
460 dist: RustExponential<f64>,
461}
462#[pymethods]
463impl PyExponential {
464 #[new]
469 #[pyo3(signature = (scale = 1.0))]
470 fn new(scale: f64) -> PyResult<Self> {
471 let rate = 1.0 / scale;
472 let dist = RustExponential::new(rate, 0.0).map_err(|e| {
473 PyRuntimeError::new_err(format!("Exponential distribution creation failed: {}", e))
474 })?;
475 Ok(PyExponential { dist })
476 }
477 fn pdf(&self, x: f64) -> f64 {
479 self.dist.pdf(x)
480 }
481 fn cdf(&self, x: f64) -> f64 {
483 self.dist.cdf(x)
484 }
485 fn ppf(&self, q: f64) -> PyResult<f64> {
487 self.dist
488 .ppf(q)
489 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
490 }
491 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
493 let arr = self
494 .dist
495 .rvs(size)
496 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
497 Ok(arr.to_vec())
498 }
499}
500#[pyclass(name = "beta")]
502pub struct PyBeta {
503 dist: RustBeta<f64>,
504}
505#[pymethods]
506impl PyBeta {
507 #[new]
515 #[pyo3(signature = (alpha, beta, loc = 0.0, scale = 1.0))]
516 fn new(alpha: f64, beta: f64, loc: f64, scale: f64) -> PyResult<Self> {
517 let dist = RustBeta::new(alpha, beta, loc, scale).map_err(|e| {
518 PyRuntimeError::new_err(format!("Beta distribution creation failed: {}", e))
519 })?;
520 Ok(PyBeta { dist })
521 }
522 fn pdf(&self, x: f64) -> f64 {
524 self.dist.pdf(x)
525 }
526 fn cdf(&self, x: f64) -> f64 {
528 self.dist.cdf(x)
529 }
530 fn ppf(&self, q: f64) -> PyResult<f64> {
532 self.dist
533 .ppf(q)
534 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
535 }
536 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
538 let arr = self
539 .dist
540 .rvs(size)
541 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
542 Ok(arr.to_vec())
543 }
544}
545#[pyclass(name = "norm")]
547pub struct PyNormal {
548 dist: RustNormal<f64>,
549}
550#[pymethods]
551impl PyNormal {
552 #[new]
558 #[pyo3(signature = (loc = 0.0, scale = 1.0))]
559 fn new(loc: f64, scale: f64) -> PyResult<Self> {
560 let dist = RustNormal::new(loc, scale).map_err(|e| {
561 PyRuntimeError::new_err(format!("Normal distribution creation failed: {}", e))
562 })?;
563 Ok(PyNormal { dist })
564 }
565 fn pdf(&self, x: f64) -> f64 {
567 self.dist.pdf(x)
568 }
569 fn cdf(&self, x: f64) -> f64 {
571 self.dist.cdf(x)
572 }
573 fn ppf(&self, q: f64) -> PyResult<f64> {
575 self.dist
576 .ppf(q)
577 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
578 }
579 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
581 let arr = self
582 .dist
583 .rvs(size)
584 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
585 Ok(arr.to_vec())
586 }
587}
588#[pyclass(name = "laplace")]
590pub struct PyLaplace {
591 dist: RustLaplace<f64>,
592}
593#[pymethods]
594impl PyLaplace {
595 #[new]
601 #[pyo3(signature = (loc = 0.0, scale = 1.0))]
602 fn new(loc: f64, scale: f64) -> PyResult<Self> {
603 let dist = RustLaplace::new(loc, scale).map_err(|e| {
604 PyRuntimeError::new_err(format!("Laplace distribution creation failed: {}", e))
605 })?;
606 Ok(PyLaplace { dist })
607 }
608 fn pdf(&self, x: f64) -> f64 {
610 self.dist.pdf(x)
611 }
612 fn cdf(&self, x: f64) -> f64 {
614 self.dist.cdf(x)
615 }
616 fn ppf(&self, q: f64) -> PyResult<f64> {
618 self.dist
619 .ppf(q)
620 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
621 }
622 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
624 let arr = self
625 .dist
626 .rvs(size)
627 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
628 Ok(arr.to_vec())
629 }
630}
631#[pyclass(name = "cauchy")]
633pub struct PyCauchy {
634 dist: RustCauchy<f64>,
635}
636#[pymethods]
637impl PyCauchy {
638 #[new]
644 #[pyo3(signature = (loc = 0.0, scale = 1.0))]
645 fn new(loc: f64, scale: f64) -> PyResult<Self> {
646 let dist = RustCauchy::new(loc, scale).map_err(|e| {
647 PyRuntimeError::new_err(format!("Cauchy distribution creation failed: {}", e))
648 })?;
649 Ok(PyCauchy { dist })
650 }
651 fn pdf(&self, x: f64) -> f64 {
653 self.dist.pdf(x)
654 }
655 fn cdf(&self, x: f64) -> f64 {
657 self.dist.cdf(x)
658 }
659 fn ppf(&self, q: f64) -> PyResult<f64> {
661 self.dist
662 .ppf(q)
663 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
664 }
665 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
667 let arr = self
668 .dist
669 .rvs(size)
670 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
671 Ok(arr.to_vec())
672 }
673}
674#[pyclass(name = "f")]
676pub struct PyF {
677 dist: RustF<f64>,
678}
679#[pymethods]
680impl PyF {
681 #[new]
689 #[pyo3(signature = (dfn, dfd, loc = 0.0, scale = 1.0))]
690 fn new(dfn: f64, dfd: f64, loc: f64, scale: f64) -> PyResult<Self> {
691 let dist = RustF::new(dfn, dfd, loc, scale).map_err(|e| {
692 PyRuntimeError::new_err(format!("F distribution creation failed: {}", e))
693 })?;
694 Ok(PyF { dist })
695 }
696 fn pdf(&self, x: f64) -> f64 {
698 self.dist.pdf(x)
699 }
700 fn cdf(&self, x: f64) -> f64 {
702 self.dist.cdf(x)
703 }
704 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
706 let arr = self
707 .dist
708 .rvs(size)
709 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
710 Ok(arr.to_vec())
711 }
712}
713#[pyclass(name = "uniform")]
715pub struct PyUniform {
716 dist: RustUniform<f64>,
717}
718#[pymethods]
719impl PyUniform {
720 #[new]
726 #[pyo3(signature = (loc = 0.0, scale = 1.0))]
727 fn new(loc: f64, scale: f64) -> PyResult<Self> {
728 let dist = RustUniform::new(loc, loc + scale).map_err(|e| {
729 PyRuntimeError::new_err(format!("Uniform distribution creation failed: {}", e))
730 })?;
731 Ok(PyUniform { dist })
732 }
733 fn pdf(&self, x: f64) -> f64 {
735 self.dist.pdf(x)
736 }
737 fn cdf(&self, x: f64) -> f64 {
739 self.dist.cdf(x)
740 }
741 fn ppf(&self, q: f64) -> PyResult<f64> {
743 self.dist
744 .ppf(q)
745 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
746 }
747 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
749 let arr = self
750 .dist
751 .rvs(size)
752 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
753 Ok(arr.to_vec())
754 }
755}