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 ppf(&self, q: f64) -> PyResult<f64> {
709 self.dist
710 .ppf(q)
711 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
712 }
713 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
715 let arr = self
716 .dist
717 .rvs(size)
718 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
719 Ok(arr.to_vec())
720 }
721}
722#[pyclass(name = "uniform")]
724pub struct PyUniform {
725 dist: RustUniform<f64>,
726}
727#[pymethods]
728impl PyUniform {
729 #[new]
735 #[pyo3(signature = (loc = 0.0, scale = 1.0))]
736 fn new(loc: f64, scale: f64) -> PyResult<Self> {
737 let dist = RustUniform::new(loc, loc + scale).map_err(|e| {
738 PyRuntimeError::new_err(format!("Uniform distribution creation failed: {}", e))
739 })?;
740 Ok(PyUniform { dist })
741 }
742 fn pdf(&self, x: f64) -> f64 {
744 self.dist.pdf(x)
745 }
746 fn cdf(&self, x: f64) -> f64 {
748 self.dist.cdf(x)
749 }
750 fn ppf(&self, q: f64) -> PyResult<f64> {
752 self.dist
753 .ppf(q)
754 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
755 }
756 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
758 let arr = self
759 .dist
760 .rvs(size)
761 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
762 Ok(arr.to_vec())
763 }
764}
765
766#[pyclass(name = "bernoulli")]
768pub struct PyBernoulli {
769 dist: RustBernoulli<f64>,
770}
771#[pymethods]
772impl PyBernoulli {
773 #[new]
778 fn new(p: f64) -> PyResult<Self> {
779 let dist = RustBernoulli::new(p).map_err(|e| {
780 PyRuntimeError::new_err(format!("Bernoulli distribution creation failed: {}", e))
781 })?;
782 Ok(PyBernoulli { dist })
783 }
784 fn pmf(&self, k: f64) -> f64 {
786 self.dist.pmf(k)
787 }
788 fn cdf(&self, k: f64) -> f64 {
790 self.dist.cdf(k)
791 }
792 fn ppf(&self, p_val: f64) -> PyResult<f64> {
794 self.dist
795 .ppf(p_val)
796 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
797 }
798 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
800 self.dist
801 .rvs(size)
802 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))
803 }
804}
805
806#[pyclass(name = "nbinom")]
808pub struct PyNegativeBinomial {
809 dist: RustNegativeBinomial<f64>,
810}
811#[pymethods]
812impl PyNegativeBinomial {
813 #[new]
819 fn new(n: f64, p: f64) -> PyResult<Self> {
820 let dist = RustNegativeBinomial::new(n, p).map_err(|e| {
821 PyRuntimeError::new_err(format!(
822 "Negative Binomial distribution creation failed: {}",
823 e
824 ))
825 })?;
826 Ok(PyNegativeBinomial { dist })
827 }
828 fn pmf(&self, k: f64) -> f64 {
830 self.dist.pmf(k)
831 }
832 fn cdf(&self, k: f64) -> f64 {
834 self.dist.cdf(k)
835 }
836 fn ppf(&self, pval: f64) -> PyResult<f64> {
838 self.dist
839 .ppf(pval)
840 .map_err(|e| PyRuntimeError::new_err(format!("PPF failed: {}", e)))
841 }
842 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
844 self.dist
845 .rvs(size)
846 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))
847 }
848}
849
850#[pyclass(name = "hypergeom")]
852pub struct PyHypergeometric {
853 dist: RustHypergeometric<f64>,
854}
855#[pymethods]
856impl PyHypergeometric {
857 #[new]
864 fn new(m: usize, n: usize, k: usize) -> PyResult<Self> {
865 let dist = RustHypergeometric::new(m, n, k, 0.0_f64).map_err(|e| {
866 PyRuntimeError::new_err(format!(
867 "Hypergeometric distribution creation failed: {}",
868 e
869 ))
870 })?;
871 Ok(PyHypergeometric { dist })
872 }
873 fn pmf(&self, x: f64) -> f64 {
875 self.dist.pmf(x)
876 }
877 fn cdf(&self, x: f64) -> f64 {
879 self.dist.cdf(x)
880 }
881 fn rvs(&self, size: usize) -> PyResult<Vec<f64>> {
883 let arr = self
884 .dist
885 .rvs(size)
886 .map_err(|e| PyRuntimeError::new_err(format!("RVS failed: {}", e)))?;
887 Ok(arr.to_vec())
888 }
889}