1use pyo3::exceptions::PyRuntimeError;
6use pyo3::prelude::*;
7use scirs2_stats::distributions::bernoulli::Bernoulli as RustBernoulli;
8use scirs2_stats::distributions::beta::Beta as RustBeta;
9use scirs2_stats::distributions::binomial::Binomial as RustBinomial;
10use scirs2_stats::distributions::cauchy::Cauchy as RustCauchy;
11use scirs2_stats::distributions::chi_square::ChiSquare as RustChiSquare;
12use scirs2_stats::distributions::exponential::Exponential as RustExponential;
13use scirs2_stats::distributions::f::F as RustF;
14use scirs2_stats::distributions::gamma::Gamma as RustGamma;
15use scirs2_stats::distributions::geometric::Geometric as RustGeometric;
16use scirs2_stats::distributions::hypergeometric::Hypergeometric as RustHypergeometric;
17use scirs2_stats::distributions::laplace::Laplace as RustLaplace;
18use scirs2_stats::distributions::logistic::Logistic as RustLogistic;
19use scirs2_stats::distributions::lognormal::Lognormal as RustLognormal;
20use scirs2_stats::distributions::negative_binomial::NegativeBinomial as RustNegativeBinomial;
21use scirs2_stats::distributions::normal::Normal as RustNormal;
22use scirs2_stats::distributions::pareto::Pareto as RustPareto;
23use scirs2_stats::distributions::poisson::Poisson as RustPoisson;
24use scirs2_stats::distributions::student_t::StudentT as RustStudentT;
25use scirs2_stats::distributions::uniform::Uniform as RustUniform;
26use scirs2_stats::distributions::weibull::Weibull as RustWeibull;
27use scirs2_stats::{ContinuousDistribution, DiscreteDistribution};
28
29#[pyclass(name = "chi2")]
31pub struct PyChiSquare {
32 dist: RustChiSquare<f64>,
33}
34#[pymethods]
35impl PyChiSquare {
36 #[new]
43 #[pyo3(signature = (df, loc = 0.0, scale = 1.0))]
44 fn new(df: f64, loc: f64, scale: f64) -> PyResult<Self> {
45 let dist = RustChiSquare::new(df, loc, scale).map_err(|e| {
46 PyRuntimeError::new_err(format!("Chi-square distribution creation failed: {}", e))
47 })?;
48 Ok(PyChiSquare { dist })
49 }
50 fn pdf(&self, x: f64) -> f64 {
52 self.dist.pdf(x)
53 }
54 fn cdf(&self, x: f64) -> f64 {
56 self.dist.cdf(x)
57 }
58 fn ppf(&self, q: f64) -> PyResult<f64> {
60 self.dist
61 .ppf(q)
62 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
63 }
64 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
66 let arr = self
67 .dist
68 .rvs(size)
69 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
70 Ok(arr.to_vec())
71 }
72}
73#[pyclass(name = "binom")]
75pub struct PyBinomial {
76 dist: RustBinomial<f64>,
77}
78#[pymethods]
79impl PyBinomial {
80 #[new]
86 fn new(n: usize, p: f64) -> PyResult<Self> {
87 let dist = RustBinomial::new(n, p).map_err(|e| {
88 PyRuntimeError::new_err(format!("Binomial distribution creation failed: {}", e))
89 })?;
90 Ok(PyBinomial { dist })
91 }
92 fn pmf(&self, k: f64) -> f64 {
94 self.dist.pmf(k)
95 }
96 fn cdf(&self, k: f64) -> f64 {
98 self.dist.cdf(k)
99 }
100 fn ppf(&self, q: f64) -> PyResult<f64> {
102 self.dist
103 .ppf(q)
104 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
105 }
106 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
108 let arr = self
109 .dist
110 .rvs(size)
111 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
112 Ok(arr.to_vec())
113 }
114}
115#[pyclass(name = "geom")]
117pub struct PyGeometric {
118 dist: RustGeometric<f64>,
119}
120#[pymethods]
121impl PyGeometric {
122 #[new]
127 fn new(p: f64) -> PyResult<Self> {
128 let dist = RustGeometric::new(p).map_err(|e| {
129 PyRuntimeError::new_err(format!("Geometric distribution creation failed: {}", e))
130 })?;
131 Ok(PyGeometric { dist })
132 }
133 fn pmf(&self, k: f64) -> f64 {
135 self.dist.pmf(k)
136 }
137 fn cdf(&self, k: f64) -> f64 {
139 self.dist.cdf(k)
140 }
141 fn ppf(&self, q: f64) -> PyResult<f64> {
143 self.dist
144 .ppf(q)
145 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
146 }
147 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
149 let arr = self
150 .dist
151 .rvs(size)
152 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
153 Ok(arr.to_vec())
154 }
155}
156#[pyclass(name = "lognorm")]
158pub struct PyLognormal {
159 dist: RustLognormal<f64>,
160}
161#[pymethods]
162impl PyLognormal {
163 #[new]
170 #[pyo3(signature = (mu = 0.0, sigma = 1.0, loc = 0.0))]
171 fn new(mu: f64, sigma: f64, loc: f64) -> PyResult<Self> {
172 let dist = RustLognormal::new(mu, sigma, loc).map_err(|e| {
173 PyRuntimeError::new_err(format!("Lognormal distribution creation failed: {}", e))
174 })?;
175 Ok(PyLognormal { dist })
176 }
177 fn pdf(&self, x: f64) -> f64 {
179 self.dist.pdf(x)
180 }
181 fn cdf(&self, x: f64) -> f64 {
183 self.dist.cdf(x)
184 }
185 fn ppf(&self, q: f64) -> PyResult<f64> {
187 self.dist
188 .ppf(q)
189 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
190 }
191 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
193 let arr = self
194 .dist
195 .rvs(size)
196 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
197 Ok(arr.to_vec())
198 }
199}
200#[pyclass(name = "weibull_min")]
202pub struct PyWeibull {
203 dist: RustWeibull<f64>,
204}
205#[pymethods]
206impl PyWeibull {
207 #[new]
214 #[pyo3(signature = (shape, scale = 1.0, loc = 0.0))]
215 fn new(shape: f64, scale: f64, loc: f64) -> PyResult<Self> {
216 let dist = RustWeibull::new(shape, scale, loc).map_err(|e| {
217 PyRuntimeError::new_err(format!("Weibull distribution creation failed: {}", e))
218 })?;
219 Ok(PyWeibull { dist })
220 }
221 fn pdf(&self, x: f64) -> f64 {
223 self.dist.pdf(x)
224 }
225 fn cdf(&self, x: f64) -> f64 {
227 self.dist.cdf(x)
228 }
229 fn ppf(&self, q: f64) -> PyResult<f64> {
231 self.dist
232 .ppf(q)
233 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
234 }
235 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
237 let arr = self
238 .dist
239 .rvs(size)
240 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
241 Ok(arr.to_vec())
242 }
243}
244#[pyclass(name = "gamma")]
246pub struct PyGamma {
247 dist: RustGamma<f64>,
248}
249#[pymethods]
250impl PyGamma {
251 #[new]
258 #[pyo3(signature = (shape, scale = 1.0, loc = 0.0))]
259 fn new(shape: f64, scale: f64, loc: f64) -> PyResult<Self> {
260 let dist = RustGamma::new(shape, scale, loc).map_err(|e| {
261 PyRuntimeError::new_err(format!("Gamma distribution creation failed: {}", e))
262 })?;
263 Ok(PyGamma { dist })
264 }
265 fn pdf(&self, x: f64) -> f64 {
267 self.dist.pdf(x)
268 }
269 fn cdf(&self, x: f64) -> f64 {
271 self.dist.cdf(x)
272 }
273 fn ppf(&self, q: f64) -> PyResult<f64> {
275 self.dist
276 .ppf(q)
277 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
278 }
279 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
281 let arr = self
282 .dist
283 .rvs(size)
284 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
285 Ok(arr.to_vec())
286 }
287}
288#[pyclass(name = "logistic")]
290pub struct PyLogistic {
291 dist: RustLogistic<f64>,
292}
293#[pymethods]
294impl PyLogistic {
295 #[new]
301 #[pyo3(signature = (loc = 0.0, scale = 1.0))]
302 fn new(loc: f64, scale: f64) -> PyResult<Self> {
303 let dist = RustLogistic::new(loc, scale).map_err(|e| {
304 PyRuntimeError::new_err(format!("Logistic distribution creation failed: {}", e))
305 })?;
306 Ok(PyLogistic { dist })
307 }
308 fn pdf(&self, x: f64) -> f64 {
310 self.dist.pdf(x)
311 }
312 fn cdf(&self, x: f64) -> f64 {
314 self.dist.cdf(x)
315 }
316 fn ppf(&self, q: f64) -> PyResult<f64> {
318 self.dist
319 .ppf(q)
320 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
321 }
322 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
324 let arr = self
325 .dist
326 .rvs(size)
327 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
328 Ok(arr.to_vec())
329 }
330}
331#[pyclass(name = "poisson")]
333pub struct PyPoisson {
334 dist: RustPoisson<f64>,
335}
336#[pymethods]
337impl PyPoisson {
338 #[new]
343 fn new(mu: f64) -> PyResult<Self> {
344 let dist = RustPoisson::new(mu, 0.0).map_err(|e| {
345 PyRuntimeError::new_err(format!("Poisson distribution creation failed: {}", e))
346 })?;
347 Ok(PyPoisson { dist })
348 }
349 fn pmf(&self, k: f64) -> f64 {
351 self.dist.pmf(k)
352 }
353 fn cdf(&self, k: f64) -> f64 {
355 self.dist.cdf(k)
356 }
357 fn ppf(&self, q: f64) -> PyResult<f64> {
359 self.dist
360 .ppf(q)
361 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
362 }
363 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
365 let arr = self
366 .dist
367 .rvs(size)
368 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
369 Ok(arr.to_vec())
370 }
371}
372#[pyclass(name = "t")]
374pub struct PyStudentT {
375 dist: RustStudentT<f64>,
376}
377#[pymethods]
378impl PyStudentT {
379 #[new]
386 #[pyo3(signature = (df, loc = 0.0, scale = 1.0))]
387 fn new(df: f64, loc: f64, scale: f64) -> PyResult<Self> {
388 let dist = RustStudentT::new(df, loc, scale).map_err(|e| {
389 PyRuntimeError::new_err(format!("Student's t distribution creation failed: {}", e))
390 })?;
391 Ok(PyStudentT { dist })
392 }
393 fn pdf(&self, x: f64) -> f64 {
395 self.dist.pdf(x)
396 }
397 fn cdf(&self, x: f64) -> f64 {
399 self.dist.cdf(x)
400 }
401 fn ppf(&self, q: f64) -> PyResult<f64> {
403 self.dist
404 .ppf(q)
405 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
406 }
407 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
409 let arr = self
410 .dist
411 .rvs(size)
412 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
413 Ok(arr.to_vec())
414 }
415}
416#[pyclass(name = "pareto")]
418pub struct PyPareto {
419 dist: RustPareto<f64>,
420}
421#[pymethods]
422impl PyPareto {
423 #[new]
430 #[pyo3(signature = (shape, scale = 1.0, loc = 0.0))]
431 fn new(shape: f64, scale: f64, loc: f64) -> PyResult<Self> {
432 let dist = RustPareto::new(shape, scale, loc).map_err(|e| {
433 PyRuntimeError::new_err(format!("Pareto distribution creation failed: {}", e))
434 })?;
435 Ok(PyPareto { dist })
436 }
437 fn pdf(&self, x: f64) -> f64 {
439 self.dist.pdf(x)
440 }
441 fn cdf(&self, x: f64) -> f64 {
443 self.dist.cdf(x)
444 }
445 fn ppf(&self, q: f64) -> PyResult<f64> {
447 self.dist
448 .ppf(q)
449 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
450 }
451 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
453 let arr = self
454 .dist
455 .rvs(size)
456 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
457 Ok(arr.to_vec())
458 }
459}
460#[pyclass(name = "expon")]
462pub struct PyExponential {
463 dist: RustExponential<f64>,
464}
465#[pymethods]
466impl PyExponential {
467 #[new]
472 #[pyo3(signature = (scale = 1.0))]
473 fn new(scale: f64) -> PyResult<Self> {
474 let rate = 1.0 / scale;
475 let dist = RustExponential::new(rate, 0.0).map_err(|e| {
476 PyRuntimeError::new_err(format!("Exponential distribution creation failed: {}", e))
477 })?;
478 Ok(PyExponential { dist })
479 }
480 fn pdf(&self, x: f64) -> f64 {
482 self.dist.pdf(x)
483 }
484 fn cdf(&self, x: f64) -> f64 {
486 self.dist.cdf(x)
487 }
488 fn ppf(&self, q: f64) -> PyResult<f64> {
490 self.dist
491 .ppf(q)
492 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
493 }
494 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
496 let arr = self
497 .dist
498 .rvs(size)
499 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
500 Ok(arr.to_vec())
501 }
502}
503#[pyclass(name = "beta")]
505pub struct PyBeta {
506 dist: RustBeta<f64>,
507}
508#[pymethods]
509impl PyBeta {
510 #[new]
518 #[pyo3(signature = (alpha, beta, loc = 0.0, scale = 1.0))]
519 fn new(alpha: f64, beta: f64, loc: f64, scale: f64) -> PyResult<Self> {
520 let dist = RustBeta::new(alpha, beta, loc, scale).map_err(|e| {
521 PyRuntimeError::new_err(format!("Beta distribution creation failed: {}", e))
522 })?;
523 Ok(PyBeta { dist })
524 }
525 fn pdf(&self, x: f64) -> f64 {
527 self.dist.pdf(x)
528 }
529 fn cdf(&self, x: f64) -> f64 {
531 self.dist.cdf(x)
532 }
533 fn ppf(&self, q: f64) -> PyResult<f64> {
535 self.dist
536 .ppf(q)
537 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
538 }
539 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
541 let arr = self
542 .dist
543 .rvs(size)
544 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
545 Ok(arr.to_vec())
546 }
547}
548#[pyclass(name = "norm")]
550pub struct PyNormal {
551 dist: RustNormal<f64>,
552}
553#[pymethods]
554impl PyNormal {
555 #[new]
561 #[pyo3(signature = (loc = 0.0, scale = 1.0))]
562 fn new(loc: f64, scale: f64) -> PyResult<Self> {
563 let dist = RustNormal::new(loc, scale).map_err(|e| {
564 PyRuntimeError::new_err(format!("Normal distribution creation failed: {}", e))
565 })?;
566 Ok(PyNormal { dist })
567 }
568 fn pdf(&self, x: f64) -> f64 {
570 self.dist.pdf(x)
571 }
572 fn cdf(&self, x: f64) -> f64 {
574 self.dist.cdf(x)
575 }
576 fn ppf(&self, q: f64) -> PyResult<f64> {
578 self.dist
579 .ppf(q)
580 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
581 }
582 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
584 let arr = self
585 .dist
586 .rvs(size)
587 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
588 Ok(arr.to_vec())
589 }
590}
591#[pyclass(name = "laplace")]
593pub struct PyLaplace {
594 dist: RustLaplace<f64>,
595}
596#[pymethods]
597impl PyLaplace {
598 #[new]
604 #[pyo3(signature = (loc = 0.0, scale = 1.0))]
605 fn new(loc: f64, scale: f64) -> PyResult<Self> {
606 let dist = RustLaplace::new(loc, scale).map_err(|e| {
607 PyRuntimeError::new_err(format!("Laplace distribution creation failed: {}", e))
608 })?;
609 Ok(PyLaplace { dist })
610 }
611 fn pdf(&self, x: f64) -> f64 {
613 self.dist.pdf(x)
614 }
615 fn cdf(&self, x: f64) -> f64 {
617 self.dist.cdf(x)
618 }
619 fn ppf(&self, q: f64) -> PyResult<f64> {
621 self.dist
622 .ppf(q)
623 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
624 }
625 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
627 let arr = self
628 .dist
629 .rvs(size)
630 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
631 Ok(arr.to_vec())
632 }
633}
634#[pyclass(name = "cauchy")]
636pub struct PyCauchy {
637 dist: RustCauchy<f64>,
638}
639#[pymethods]
640impl PyCauchy {
641 #[new]
647 #[pyo3(signature = (loc = 0.0, scale = 1.0))]
648 fn new(loc: f64, scale: f64) -> PyResult<Self> {
649 let dist = RustCauchy::new(loc, scale).map_err(|e| {
650 PyRuntimeError::new_err(format!("Cauchy distribution creation failed: {}", e))
651 })?;
652 Ok(PyCauchy { dist })
653 }
654 fn pdf(&self, x: f64) -> f64 {
656 self.dist.pdf(x)
657 }
658 fn cdf(&self, x: f64) -> f64 {
660 self.dist.cdf(x)
661 }
662 fn ppf(&self, q: f64) -> PyResult<f64> {
664 self.dist
665 .ppf(q)
666 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
667 }
668 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
670 let arr = self
671 .dist
672 .rvs(size)
673 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
674 Ok(arr.to_vec())
675 }
676}
677#[pyclass(name = "f")]
679pub struct PyF {
680 dist: RustF<f64>,
681}
682#[pymethods]
683impl PyF {
684 #[new]
692 #[pyo3(signature = (dfn, dfd, loc = 0.0, scale = 1.0))]
693 fn new(dfn: f64, dfd: f64, loc: f64, scale: f64) -> PyResult<Self> {
694 let dist = RustF::new(dfn, dfd, loc, scale).map_err(|e| {
695 PyRuntimeError::new_err(format!("F distribution creation failed: {}", e))
696 })?;
697 Ok(PyF { dist })
698 }
699 fn pdf(&self, x: f64) -> f64 {
701 self.dist.pdf(x)
702 }
703 fn cdf(&self, x: f64) -> f64 {
705 self.dist.cdf(x)
706 }
707 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
709 let arr = self
710 .dist
711 .rvs(size)
712 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
713 Ok(arr.to_vec())
714 }
715}
716#[pyclass(name = "uniform")]
718pub struct PyUniform {
719 dist: RustUniform<f64>,
720}
721#[pymethods]
722impl PyUniform {
723 #[new]
729 #[pyo3(signature = (loc = 0.0, scale = 1.0))]
730 fn new(loc: f64, scale: f64) -> PyResult<Self> {
731 let dist = RustUniform::new(loc, loc + scale).map_err(|e| {
732 PyRuntimeError::new_err(format!("Uniform distribution creation failed: {}", e))
733 })?;
734 Ok(PyUniform { dist })
735 }
736 fn pdf(&self, x: f64) -> f64 {
738 self.dist.pdf(x)
739 }
740 fn cdf(&self, x: f64) -> f64 {
742 self.dist.cdf(x)
743 }
744 fn ppf(&self, q: f64) -> PyResult<f64> {
746 self.dist
747 .ppf(q)
748 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
749 }
750 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
752 let arr = self
753 .dist
754 .rvs(size)
755 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
756 Ok(arr.to_vec())
757 }
758}
759
760#[pyclass(name = "bernoulli")]
762pub struct PyBernoulli {
763 dist: RustBernoulli<f64>,
764}
765#[pymethods]
766impl PyBernoulli {
767 #[new]
772 fn new(p: f64) -> PyResult<Self> {
773 let dist = RustBernoulli::new(p).map_err(|e| {
774 PyRuntimeError::new_err(format!("Bernoulli distribution creation failed: {}", e))
775 })?;
776 Ok(PyBernoulli { dist })
777 }
778 fn pmf(&self, k: f64) -> f64 {
780 self.dist.pmf(k)
781 }
782 fn cdf(&self, k: f64) -> f64 {
784 self.dist.cdf(k)
785 }
786 fn ppf(&self, p_val: f64) -> PyResult<f64> {
788 self.dist
789 .ppf(p_val)
790 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
791 }
792 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
794 self.dist
795 .rvs(size)
796 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))
797 }
798}
799
800#[pyclass(name = "nbinom")]
802pub struct PyNegativeBinomial {
803 dist: RustNegativeBinomial<f64>,
804}
805#[pymethods]
806impl PyNegativeBinomial {
807 #[new]
813 fn new(n: f64, p: f64) -> PyResult<Self> {
814 let dist = RustNegativeBinomial::new(n, p).map_err(|e| {
815 PyRuntimeError::new_err(format!(
816 "Negative Binomial distribution creation failed: {}",
817 e
818 ))
819 })?;
820 Ok(PyNegativeBinomial { dist })
821 }
822 fn pmf(&self, k: f64) -> f64 {
824 self.dist.pmf(k)
825 }
826 fn cdf(&self, k: f64) -> f64 {
828 self.dist.cdf(k)
829 }
830 fn ppf(&self, pval: f64) -> PyResult<f64> {
832 self.dist
833 .ppf(pval)
834 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
835 }
836 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
838 self.dist
839 .rvs(size)
840 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))
841 }
842}
843
844#[pyclass(name = "hypergeom")]
846pub struct PyHypergeometric {
847 dist: RustHypergeometric<f64>,
848}
849#[pymethods]
850impl PyHypergeometric {
851 #[new]
858 fn new(m: usize, n: usize, k: usize) -> PyResult<Self> {
859 let dist = RustHypergeometric::new(m, n, k, 0.0_f64).map_err(|e| {
860 PyRuntimeError::new_err(format!(
861 "Hypergeometric distribution creation failed: {}",
862 e
863 ))
864 })?;
865 Ok(PyHypergeometric { dist })
866 }
867 fn pmf(&self, x: f64) -> f64 {
869 self.dist.pmf(x)
870 }
871 fn cdf(&self, x: f64) -> f64 {
873 self.dist.cdf(x)
874 }
875 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
877 let arr = self
878 .dist
879 .rvs(size)
880 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
881 Ok(arr.to_vec())
882 }
883}