1#![allow(clippy::not_unsafe_ptr_arg_deref)]
2use std::os::raw::c_int;
19
20const LN_SQRT_2PI: f64 = 0.918_938_533_204_672_8;
23const DBL_EPSILON: f64 = f64::EPSILON;
24
25fn r_finite(x: f64) -> bool {
26 x.is_finite()
27}
28
29fn unif_rand() -> f64 {
31 super::runtime::unif_rand()
32}
33
34pub fn pgamma_raw(a: f64, x: f64) -> f64 {
41 if x <= 0.0 {
42 return 0.0;
43 }
44 if x.is_infinite() {
45 return 1.0;
46 }
47 if a <= 0.0 {
48 return 1.0;
49 }
50
51 if x < a + 1.0 {
52 gamma_series(a, x)
54 } else {
55 1.0 - gamma_cf(a, x)
57 }
58}
59
60pub fn qgamma_raw(a: f64, x: f64) -> f64 {
62 1.0 - pgamma_raw(a, x)
63}
64
65fn gamma_series(a: f64, x: f64) -> f64 {
67 let ln_gamma_a = libm::lgamma(a);
68 let mut sum = 1.0 / a;
69 let mut term = 1.0 / a;
70 for n in 1..200 {
71 term *= x / (a + n as f64);
72 sum += term;
73 if term.abs() < sum.abs() * DBL_EPSILON {
74 break;
75 }
76 }
77 sum * (-x + a * x.ln() - ln_gamma_a).exp()
78}
79
80fn gamma_cf(a: f64, x: f64) -> f64 {
82 let ln_gamma_a = libm::lgamma(a);
83 let mut c = 1e-30_f64;
85 let mut d = 1.0 / (x + 1.0 - a);
86 let mut f = d;
87
88 for i in 1..200 {
89 let an = -(i as f64) * (i as f64 - a);
90 let bn = x + 2.0 * i as f64 + 1.0 - a;
91 d = bn + an * d;
92 if d.abs() < 1e-30 {
93 d = 1e-30;
94 }
95 c = bn + an / c;
96 if c.abs() < 1e-30 {
97 c = 1e-30;
98 }
99 d = 1.0 / d;
100 let delta = c * d;
101 f *= delta;
102 if (delta - 1.0).abs() < DBL_EPSILON {
103 break;
104 }
105 }
106 f * (-x + a * x.ln() - ln_gamma_a).exp()
107}
108
109pub fn pbeta_raw(x: f64, a: f64, b: f64) -> f64 {
112 if x <= 0.0 {
113 return 0.0;
114 }
115 if x >= 1.0 {
116 return 1.0;
117 }
118 if a <= 0.0 || b <= 0.0 {
119 return f64::NAN;
120 }
121
122 if x > (a + 1.0) / (a + b + 2.0) {
125 return 1.0 - pbeta_raw(1.0 - x, b, a);
126 }
127
128 let ln_beta = libm::lgamma(a) + libm::lgamma(b) - libm::lgamma(a + b);
129 let front = (a * x.ln() + b * (1.0 - x).ln() - ln_beta).exp() / a;
130
131 let mut f = 1.0 + beta_cf_term(1, a, b, x);
133 if !f.is_finite() || f == 0.0 {
134 f = 1e-30;
135 }
136 let mut c = f;
137 let mut d = 1.0;
138
139 for m in 2..200 {
140 let term = beta_cf_term(m, a, b, x);
141 d = 1.0 + term * d;
142 if d.abs() < 1e-30 {
143 d = 1e-30;
144 }
145 c = 1.0 + term / c;
146 if c.abs() < 1e-30 {
147 c = 1e-30;
148 }
149 d = 1.0 / d;
150 let delta = c * d;
151 f *= delta;
152 if (delta - 1.0).abs() < 3.0 * DBL_EPSILON {
153 break;
154 }
155 }
156
157 front * f
158}
159
160fn beta_cf_term(m: i32, a: f64, b: f64, x: f64) -> f64 {
162 let m_f = m as f64;
163 if m % 2 == 0 {
164 let k = m_f / 2.0;
165 (k * (b - k) * x) / ((a + 2.0 * k - 1.0) * (a + 2.0 * k))
166 } else {
167 let k = (m_f - 1.0) / 2.0;
168 -((a + k) * (a + b + k) * x) / ((a + 2.0 * k) * (a + 2.0 * k + 1.0))
169 }
170}
171
172pub fn trigamma(x: f64) -> f64 {
174 let mut x = x;
175 let mut result = 0.0;
176 while x < 6.0 {
178 result += 1.0 / (x * x);
179 x += 1.0;
180 }
181 let x2 = 1.0 / (x * x);
183 result
184 + 1.0 / x
185 + x2 / 2.0
186 + x2 / x * (1.0 / 6.0 - x2 * (1.0 / 30.0 - x2 * (1.0 / 42.0 - x2 / 30.0)))
187}
188
189pub fn tetragamma(x: f64) -> f64 {
191 let mut x = x;
192 let mut result = 0.0;
193 while x < 6.0 {
194 result -= 2.0 / (x * x * x);
195 x += 1.0;
196 }
197 let x2 = 1.0 / (x * x);
198 result - 1.0 / (x * x) - 1.0 / (x * x * x)
199 + x2 * x2 * (-1.0 / 3.0 + x2 * (1.0 / 5.0 - x2 * (1.0 / 7.0)))
200}
201
202pub fn pentagamma(x: f64) -> f64 {
204 let mut x = x;
205 let mut result = 0.0;
206 while x < 6.0 {
207 result += 6.0 / (x * x * x * x);
208 x += 1.0;
209 }
210 let x2 = 1.0 / (x * x);
211 let x3 = x2 / x;
212 result + 2.0 * x3 + 3.0 * x2 * x2 + x2 * x3 * (2.0 + x2 * (-2.0 + x2 * (3.0)))
213}
214
215pub fn psigamma_fn(x: f64, deriv: f64) -> f64 {
217 let n = deriv as i32;
218 match n {
219 0 => digamma_fn(x),
220 1 => trigamma(x),
221 2 => tetragamma(x),
222 3 => pentagamma(x),
223 _ => f64::NAN,
224 }
225}
226
227pub fn digamma_fn(x: f64) -> f64 {
229 let mut x = x;
230 let mut result = 0.0;
231 while x < 6.0 {
232 result -= 1.0 / x;
233 x += 1.0;
234 }
235 result += x.ln() - 0.5 / x;
236 let x2 = 1.0 / (x * x);
237 result - x2 * (1.0 / 12.0 - x2 * (1.0 / 120.0 - x2 * (1.0 / 252.0 - x2 / 240.0)))
238}
239
240pub fn beta_fn(a: f64, b: f64) -> f64 {
242 (libm::lgamma(a) + libm::lgamma(b) - libm::lgamma(a + b)).exp()
243}
244
245pub fn lbeta_fn(a: f64, b: f64) -> f64 {
247 libm::lgamma(a) + libm::lgamma(b) - libm::lgamma(a + b)
248}
249
250pub fn choose_fn(n: f64, k: f64) -> f64 {
252 if k < 0.0 || k > n {
253 return 0.0;
254 }
255 if k == 0.0 || k == n {
256 return 1.0;
257 }
258 (libm::lgamma(n + 1.0) - libm::lgamma(k + 1.0) - libm::lgamma(n - k + 1.0)).exp()
260}
261
262pub fn lchoose_fn(n: f64, k: f64) -> f64 {
264 if k < 0.0 || k > n {
265 return f64::NEG_INFINITY;
266 }
267 if k == 0.0 || k == n {
268 return 0.0;
269 }
270 libm::lgamma(n + 1.0) - libm::lgamma(k + 1.0) - libm::lgamma(n - k + 1.0)
271}
272
273pub fn log1pmx_fn(x: f64) -> f64 {
275 libm::log1p(x) - x
276}
277
278pub fn lgamma1p_fn(a: f64) -> f64 {
280 libm::lgamma(1.0 + a)
281}
282
283pub fn logspace_add_fn(lx: f64, ly: f64) -> f64 {
285 if lx > ly {
286 lx + libm::log1p((ly - lx).exp())
287 } else {
288 ly + libm::log1p((lx - ly).exp())
289 }
290}
291
292pub fn logspace_sub_fn(lx: f64, ly: f64) -> f64 {
294 lx + libm::log1p(-(ly - lx).exp())
295}
296
297fn p_transform(p: f64, lower_tail: c_int, log_p: c_int) -> f64 {
303 let p = if lower_tail != 0 { p } else { 1.0 - p };
304 if log_p != 0 {
305 p.ln()
306 } else {
307 p
308 }
309}
310
311fn q_decode(p: f64, lower_tail: c_int, log_p: c_int) -> f64 {
313 let p = if log_p != 0 { p.exp() } else { p };
314 if lower_tail != 0 {
315 p
316 } else {
317 1.0 - p
318 }
319}
320
321fn d_log(d: f64, give_log: c_int) -> f64 {
323 if give_log != 0 {
324 d.ln()
325 } else {
326 d
327 }
328}
329
330#[no_mangle]
335pub extern "C" fn Rf_dnorm4(x: f64, mu: f64, sigma: f64, give_log: c_int) -> f64 {
336 if !r_finite(sigma) || sigma < 0.0 {
337 return f64::NAN;
338 }
339 if sigma == 0.0 {
340 return if x == mu {
341 f64::INFINITY
342 } else {
343 d_log(0.0, give_log)
344 };
345 }
346 let z = (x - mu) / sigma;
347 let d = (-0.5 * z * z - LN_SQRT_2PI - sigma.ln()).exp();
348 d_log(d, give_log)
349}
350
351#[no_mangle]
352pub extern "C" fn Rf_pnorm5(x: f64, mu: f64, sigma: f64, lower_tail: c_int, log_p: c_int) -> f64 {
353 if !r_finite(sigma) || sigma < 0.0 {
354 return f64::NAN;
355 }
356 if sigma == 0.0 {
357 return p_transform(if x < mu { 0.0 } else { 1.0 }, lower_tail, log_p);
358 }
359 let z = (x - mu) / sigma;
360 let p = 0.5 * libm::erfc(-z / std::f64::consts::SQRT_2);
361 p_transform(p, lower_tail, log_p)
362}
363
364#[no_mangle]
365pub extern "C" fn Rf_qnorm5(p: f64, mu: f64, sigma: f64, lower_tail: c_int, log_p: c_int) -> f64 {
366 if !r_finite(sigma) || sigma < 0.0 {
367 return f64::NAN;
368 }
369 let p = q_decode(p, lower_tail, log_p);
370 if !(0.0..=1.0).contains(&p) {
371 return f64::NAN;
372 }
373 if p == 0.0 {
374 return f64::NEG_INFINITY;
375 }
376 if p == 1.0 {
377 return f64::INFINITY;
378 }
379 mu + sigma * qnorm_standard(p)
381}
382
383#[allow(clippy::excessive_precision)]
385fn qnorm_standard(p: f64) -> f64 {
386 const A: [f64; 6] = [
388 -3.969683028665376e+01,
389 2.209460984245205e+02,
390 -2.759285104469687e+02,
391 1.383577518672690e+02,
392 -3.066479806614716e+01,
393 2.506628277459239e+00,
394 ];
395 const B: [f64; 5] = [
396 -5.447609879822406e+01,
397 1.615858368580409e+02,
398 -1.556989798598866e+02,
399 6.680131188771972e+01,
400 -1.328068155288572e+01,
401 ];
402 const C: [f64; 6] = [
403 -7.784894002430293e-03,
404 -3.223964580411365e-01,
405 -2.400758277161838e+00,
406 -2.549732539343734e+00,
407 4.374664141464968e+00,
408 2.938163982698783e+00,
409 ];
410 const D: [f64; 4] = [
411 7.784695709041462e-03,
412 3.224671290700398e-01,
413 2.445134137142996e+00,
414 3.754408661907416e+00,
415 ];
416
417 const P_LOW: f64 = 0.02425;
418 const P_HIGH: f64 = 1.0 - P_LOW;
419
420 if p < P_LOW {
421 let q = (-2.0 * p.ln()).sqrt();
422 (((((C[0] * q + C[1]) * q + C[2]) * q + C[3]) * q + C[4]) * q + C[5])
423 / ((((D[0] * q + D[1]) * q + D[2]) * q + D[3]) * q + 1.0)
424 } else if p <= P_HIGH {
425 let q = p - 0.5;
426 let r = q * q;
427 (((((A[0] * r + A[1]) * r + A[2]) * r + A[3]) * r + A[4]) * r + A[5]) * q
428 / (((((B[0] * r + B[1]) * r + B[2]) * r + B[3]) * r + B[4]) * r + 1.0)
429 } else {
430 let q = (-2.0 * (1.0 - p).ln()).sqrt();
431 -(((((C[0] * q + C[1]) * q + C[2]) * q + C[3]) * q + C[4]) * q + C[5])
432 / ((((D[0] * q + D[1]) * q + D[2]) * q + D[3]) * q + 1.0)
433 }
434}
435
436#[no_mangle]
437pub extern "C" fn Rf_rnorm(mu: f64, sigma: f64) -> f64 {
438 let u1 = unif_rand();
441 let u2 = unif_rand();
442 let z = (-2.0 * u1.ln()).sqrt() * (2.0 * std::f64::consts::PI * u2).cos();
443 mu + sigma * z
444}
445
446#[no_mangle]
447pub extern "C" fn Rf_pnorm_both(x: f64, cum: *mut f64, ccum: *mut f64, _lt: c_int, _lg: c_int) {
448 let p = 0.5 * libm::erfc(-x / std::f64::consts::SQRT_2);
449 if !cum.is_null() {
450 unsafe {
451 *cum = p;
452 }
453 }
454 if !ccum.is_null() {
455 unsafe {
456 *ccum = 1.0 - p;
457 }
458 }
459}
460
461#[no_mangle]
466pub extern "C" fn Rf_dunif(x: f64, a: f64, b: f64, give_log: c_int) -> f64 {
467 if b <= a {
468 return f64::NAN;
469 }
470 let d = if x < a || x > b { 0.0 } else { 1.0 / (b - a) };
471 d_log(d, give_log)
472}
473
474#[no_mangle]
475pub extern "C" fn Rf_punif(x: f64, a: f64, b: f64, lower_tail: c_int, log_p: c_int) -> f64 {
476 if b <= a {
477 return f64::NAN;
478 }
479 let p = if x <= a {
480 0.0
481 } else if x >= b {
482 1.0
483 } else {
484 (x - a) / (b - a)
485 };
486 p_transform(p, lower_tail, log_p)
487}
488
489#[no_mangle]
490pub extern "C" fn Rf_qunif(p: f64, a: f64, b: f64, lower_tail: c_int, log_p: c_int) -> f64 {
491 if b <= a {
492 return f64::NAN;
493 }
494 let p = q_decode(p, lower_tail, log_p);
495 if !(0.0..=1.0).contains(&p) {
496 return f64::NAN;
497 }
498 a + p * (b - a)
499}
500
501#[no_mangle]
502pub extern "C" fn Rf_runif(a: f64, b: f64) -> f64 {
503 let u = unif_rand();
504 a + u * (b - a)
505}
506
507#[no_mangle]
512pub extern "C" fn Rf_dexp(x: f64, scale: f64, give_log: c_int) -> f64 {
513 if scale <= 0.0 {
514 return f64::NAN;
515 }
516 let d = if x < 0.0 {
517 0.0
518 } else {
519 (-x / scale).exp() / scale
520 };
521 d_log(d, give_log)
522}
523
524#[no_mangle]
525pub extern "C" fn Rf_pexp(x: f64, scale: f64, lower_tail: c_int, log_p: c_int) -> f64 {
526 if scale <= 0.0 {
527 return f64::NAN;
528 }
529 let p = if x <= 0.0 {
530 0.0
531 } else {
532 -libm::expm1(-x / scale)
533 };
534 p_transform(p, lower_tail, log_p)
535}
536
537#[no_mangle]
538pub extern "C" fn Rf_qexp(p: f64, scale: f64, lower_tail: c_int, log_p: c_int) -> f64 {
539 if scale <= 0.0 {
540 return f64::NAN;
541 }
542 let p = q_decode(p, lower_tail, log_p);
543 if !(0.0..=1.0).contains(&p) {
544 return f64::NAN;
545 }
546 -scale * libm::log1p(-p)
547}
548
549#[no_mangle]
550pub extern "C" fn Rf_rexp(scale: f64) -> f64 {
551 let u = unif_rand();
552 -scale * u.ln()
553}
554
555#[no_mangle]
560pub extern "C" fn Rf_dgamma(x: f64, shape: f64, scale: f64, give_log: c_int) -> f64 {
561 if shape <= 0.0 || scale <= 0.0 {
562 return f64::NAN;
563 }
564 if x < 0.0 {
565 return d_log(0.0, give_log);
566 }
567 if x == 0.0 {
568 if shape < 1.0 {
569 return f64::INFINITY;
570 }
571 if shape == 1.0 {
572 return d_log(1.0 / scale, give_log);
573 }
574 return d_log(0.0, give_log);
575 }
576 let log_d = (shape - 1.0) * x.ln() - x / scale - shape * scale.ln() - libm::lgamma(shape);
577 if give_log != 0 {
578 log_d
579 } else {
580 log_d.exp()
581 }
582}
583
584#[no_mangle]
585pub extern "C" fn Rf_pgamma(
586 x: f64,
587 shape: f64,
588 scale: f64,
589 lower_tail: c_int,
590 log_p: c_int,
591) -> f64 {
592 if shape <= 0.0 || scale <= 0.0 {
593 return f64::NAN;
594 }
595 let p = pgamma_raw(shape, x / scale);
596 p_transform(p, lower_tail, log_p)
597}
598
599#[no_mangle]
600pub extern "C" fn Rf_qgamma(
601 p: f64,
602 shape: f64,
603 scale: f64,
604 lower_tail: c_int,
605 log_p: c_int,
606) -> f64 {
607 if shape <= 0.0 || scale <= 0.0 {
608 return f64::NAN;
609 }
610 let p = q_decode(p, lower_tail, log_p);
611 if !(0.0..=1.0).contains(&p) {
612 return f64::NAN;
613 }
614 if p == 0.0 {
615 return 0.0;
616 }
617 if p == 1.0 {
618 return f64::INFINITY;
619 }
620 let z = qnorm_standard(p);
622 let mut x = shape * (1.0 - 1.0 / (9.0 * shape) + z / (3.0 * shape.sqrt())).powi(3);
623 if x <= 0.0 {
624 x = DBL_EPSILON;
625 }
626 for _ in 0..50 {
627 let px = pgamma_raw(shape, x);
628 let dx = Rf_dgamma(x, shape, 1.0, 0);
629 if dx <= 0.0 {
630 break;
631 }
632 let delta = (px - p) / dx;
633 x -= delta;
634 if x <= 0.0 {
635 x = DBL_EPSILON;
636 }
637 if delta.abs() < x * 1e-12 {
638 break;
639 }
640 }
641 x * scale
642}
643
644#[no_mangle]
645pub extern "C" fn Rf_rgamma(shape: f64, scale: f64) -> f64 {
646 if shape <= 0.0 || scale <= 0.0 {
648 return f64::NAN;
649 }
650 let (d_shape, boost) = if shape < 1.0 {
651 (shape + 1.0, true)
652 } else {
653 (shape, false)
654 };
655 let d = d_shape - 1.0 / 3.0;
656 let c = 1.0 / (9.0 * d).sqrt();
657 let x = loop {
658 let (z, v) = loop {
659 let z = Rf_rnorm(0.0, 1.0);
660 let v = 1.0 + c * z;
661 if v > 0.0 {
662 break (z, v * v * v);
663 }
664 };
665 let u = unif_rand();
666 if u < 1.0 - 0.0331 * (z * z) * (z * z) {
667 break d * v;
668 }
669 if u.ln() < 0.5 * z * z + d * (1.0 - v + v.ln()) {
670 break d * v;
671 }
672 };
673 if boost {
674 let u = unif_rand();
675 x * u.powf(1.0 / shape) * scale
676 } else {
677 x * scale
678 }
679}
680
681#[no_mangle]
686pub extern "C" fn Rf_dbeta(x: f64, a: f64, b: f64, give_log: c_int) -> f64 {
687 if a <= 0.0 || b <= 0.0 {
688 return f64::NAN;
689 }
690 if !(0.0..=1.0).contains(&x) {
691 return d_log(0.0, give_log);
692 }
693 if x == 0.0 {
694 if a < 1.0 {
695 return f64::INFINITY;
696 }
697 if a == 1.0 {
698 return d_log(b, give_log);
699 }
700 return d_log(0.0, give_log);
701 }
702 if x == 1.0 {
703 if b < 1.0 {
704 return f64::INFINITY;
705 }
706 if b == 1.0 {
707 return d_log(a, give_log);
708 }
709 return d_log(0.0, give_log);
710 }
711 let log_d = (a - 1.0) * x.ln() + (b - 1.0) * (1.0 - x).ln() - lbeta_fn(a, b);
712 if give_log != 0 {
713 log_d
714 } else {
715 log_d.exp()
716 }
717}
718
719#[no_mangle]
720pub extern "C" fn Rf_pbeta(x: f64, a: f64, b: f64, lower_tail: c_int, log_p: c_int) -> f64 {
721 if a <= 0.0 || b <= 0.0 {
722 return f64::NAN;
723 }
724 let p = pbeta_raw(x, a, b);
725 p_transform(p, lower_tail, log_p)
726}
727
728#[no_mangle]
729pub extern "C" fn Rf_qbeta(p: f64, a: f64, b: f64, lower_tail: c_int, log_p: c_int) -> f64 {
730 if a <= 0.0 || b <= 0.0 {
731 return f64::NAN;
732 }
733 let p = q_decode(p, lower_tail, log_p);
734 if !(0.0..=1.0).contains(&p) {
735 return f64::NAN;
736 }
737 if p == 0.0 {
738 return 0.0;
739 }
740 if p == 1.0 {
741 return 1.0;
742 }
743 let mut x = p; for _ in 0..100 {
746 let px = pbeta_raw(x, a, b);
747 let dx = Rf_dbeta(x, a, b, 0);
748 if dx <= 0.0 || !dx.is_finite() {
749 break;
750 }
751 let delta = (px - p) / dx;
752 x -= delta;
753 x = x.clamp(DBL_EPSILON, 1.0 - DBL_EPSILON);
754 if delta.abs() < x * 1e-12 {
755 break;
756 }
757 }
758 x
759}
760
761#[no_mangle]
762pub extern "C" fn Rf_rbeta(a: f64, b: f64) -> f64 {
763 let x = Rf_rgamma(a, 1.0);
764 let y = Rf_rgamma(b, 1.0);
765 x / (x + y)
766}
767
768#[no_mangle]
773pub extern "C" fn Rf_dchisq(x: f64, df: f64, give_log: c_int) -> f64 {
774 Rf_dgamma(x, df / 2.0, 2.0, give_log)
775}
776
777#[no_mangle]
778pub extern "C" fn Rf_pchisq(x: f64, df: f64, lower_tail: c_int, log_p: c_int) -> f64 {
779 Rf_pgamma(x, df / 2.0, 2.0, lower_tail, log_p)
780}
781
782#[no_mangle]
783pub extern "C" fn Rf_qchisq(p: f64, df: f64, lower_tail: c_int, log_p: c_int) -> f64 {
784 Rf_qgamma(p, df / 2.0, 2.0, lower_tail, log_p)
785}
786
787#[no_mangle]
788pub extern "C" fn Rf_rchisq(df: f64) -> f64 {
789 Rf_rgamma(df / 2.0, 2.0)
790}
791
792#[no_mangle]
794pub extern "C" fn Rf_dnchisq(x: f64, df: f64, ncp: f64, give_log: c_int) -> f64 {
795 if df <= 0.0 || ncp < 0.0 {
796 return f64::NAN;
797 }
798 if x < 0.0 {
799 return d_log(0.0, give_log);
800 }
801 let lambda = ncp / 2.0;
803 let max_terms = 100.min((lambda + 20.0 * lambda.sqrt()) as usize + 10);
804 let mut sum = 0.0;
805 let mut poisson_weight = (-lambda).exp();
806 for j in 0..max_terms {
807 let chi_df = df + 2.0 * j as f64;
808 let chi_dens = Rf_dgamma(x, chi_df / 2.0, 2.0, 0);
809 sum += poisson_weight * chi_dens;
810 poisson_weight *= lambda / (j as f64 + 1.0);
811 }
812 d_log(sum, give_log)
813}
814
815#[no_mangle]
816pub extern "C" fn Rf_pnchisq(x: f64, df: f64, ncp: f64, lower_tail: c_int, log_p: c_int) -> f64 {
817 if df <= 0.0 || ncp < 0.0 {
818 return f64::NAN;
819 }
820 if x <= 0.0 {
821 return p_transform(0.0, lower_tail, log_p);
822 }
823 let lambda = ncp / 2.0;
824 let max_terms = 100.min((lambda + 20.0 * lambda.sqrt()) as usize + 10);
825 let mut sum = 0.0;
826 let mut poisson_weight = (-lambda).exp();
827 for j in 0..max_terms {
828 let chi_df = df + 2.0 * j as f64;
829 let chi_cdf = pgamma_raw(chi_df / 2.0, x / 2.0);
830 sum += poisson_weight * chi_cdf;
831 poisson_weight *= lambda / (j as f64 + 1.0);
832 }
833 p_transform(sum, lower_tail, log_p)
834}
835
836#[no_mangle]
837pub extern "C" fn Rf_qnchisq(p: f64, df: f64, ncp: f64, lower_tail: c_int, log_p: c_int) -> f64 {
838 let p = q_decode(p, lower_tail, log_p);
839 if !(0.0..=1.0).contains(&p) || df <= 0.0 || ncp < 0.0 {
840 return f64::NAN;
841 }
842 let mut x = Rf_qchisq(p, df + ncp, 1, 0);
844 if x <= 0.0 {
845 x = df + ncp;
846 }
847 for _ in 0..50 {
848 let px = Rf_pnchisq(x, df, ncp, 1, 0);
849 let dx = Rf_dnchisq(x, df, ncp, 0);
850 if dx <= 0.0 {
851 break;
852 }
853 let delta = (px - p) / dx;
854 x -= delta;
855 if x <= 0.0 {
856 x = DBL_EPSILON;
857 }
858 if delta.abs() < x * 1e-12 {
859 break;
860 }
861 }
862 x
863}
864
865#[no_mangle]
866pub extern "C" fn Rf_rnchisq(df: f64, ncp: f64) -> f64 {
867 if ncp == 0.0 {
869 return Rf_rchisq(df);
870 }
871 let z = Rf_rnorm(ncp.sqrt(), 1.0);
872 z * z + Rf_rchisq(df - 1.0)
873}
874
875#[no_mangle]
880pub extern "C" fn Rf_dt(x: f64, df: f64, give_log: c_int) -> f64 {
881 if df <= 0.0 {
882 return f64::NAN;
883 }
884 let log_d = libm::lgamma((df + 1.0) / 2.0)
885 - libm::lgamma(df / 2.0)
886 - 0.5 * (df * std::f64::consts::PI).ln()
887 - ((df + 1.0) / 2.0) * (1.0 + x * x / df).ln();
888 if give_log != 0 {
889 log_d
890 } else {
891 log_d.exp()
892 }
893}
894
895#[no_mangle]
896pub extern "C" fn Rf_pt(x: f64, df: f64, lower_tail: c_int, log_p: c_int) -> f64 {
897 if df <= 0.0 {
898 return f64::NAN;
899 }
900 let t2 = x * x;
902 let p = pbeta_raw(df / (df + t2), df / 2.0, 0.5);
903 let p = if x <= 0.0 { p / 2.0 } else { 1.0 - p / 2.0 };
904 p_transform(p, lower_tail, log_p)
905}
906
907#[no_mangle]
908pub extern "C" fn Rf_qt(p: f64, df: f64, lower_tail: c_int, log_p: c_int) -> f64 {
909 if df <= 0.0 {
910 return f64::NAN;
911 }
912 let p = q_decode(p, lower_tail, log_p);
913 if !(0.0..=1.0).contains(&p) {
914 return f64::NAN;
915 }
916 if p == 0.0 {
917 return f64::NEG_INFINITY;
918 }
919 if p == 1.0 {
920 return f64::INFINITY;
921 }
922 if p == 0.5 {
923 return 0.0;
924 }
925 let mut x = qnorm_standard(p);
927 for _ in 0..50 {
928 let px = Rf_pt(x, df, 1, 0);
929 let dx = Rf_dt(x, df, 0);
930 if dx <= 0.0 {
931 break;
932 }
933 let delta = (px - p) / dx;
934 x -= delta;
935 if delta.abs() < x.abs() * 1e-12 {
936 break;
937 }
938 }
939 x
940}
941
942#[no_mangle]
943pub extern "C" fn Rf_rt(df: f64) -> f64 {
944 Rf_rnorm(0.0, 1.0) / (Rf_rchisq(df) / df).sqrt()
945}
946
947#[no_mangle]
952pub extern "C" fn Rf_df(x: f64, df1: f64, df2: f64, give_log: c_int) -> f64 {
953 if df1 <= 0.0 || df2 <= 0.0 {
954 return f64::NAN;
955 }
956 if x < 0.0 {
957 return d_log(0.0, give_log);
958 }
959 if x == 0.0 {
960 if df1 < 2.0 {
961 return f64::INFINITY;
962 }
963 if df1 == 2.0 {
964 return d_log(1.0, give_log);
965 }
966 return d_log(0.0, give_log);
967 }
968 let log_d = (df1 / 2.0) * (df1 / df2).ln() + (df1 / 2.0 - 1.0) * x.ln()
969 - lbeta_fn(df1 / 2.0, df2 / 2.0)
970 - ((df1 + df2) / 2.0) * (1.0 + df1 * x / df2).ln();
971 if give_log != 0 {
972 log_d
973 } else {
974 log_d.exp()
975 }
976}
977
978#[no_mangle]
979pub extern "C" fn Rf_pf(x: f64, df1: f64, df2: f64, lower_tail: c_int, log_p: c_int) -> f64 {
980 if df1 <= 0.0 || df2 <= 0.0 {
981 return f64::NAN;
982 }
983 if x <= 0.0 {
984 return p_transform(0.0, lower_tail, log_p);
985 }
986 let v = df1 * x / (df1 * x + df2);
987 let p = pbeta_raw(v, df1 / 2.0, df2 / 2.0);
988 p_transform(p, lower_tail, log_p)
989}
990
991#[no_mangle]
992pub extern "C" fn Rf_qf(p: f64, df1: f64, df2: f64, lower_tail: c_int, log_p: c_int) -> f64 {
993 if df1 <= 0.0 || df2 <= 0.0 {
994 return f64::NAN;
995 }
996 let p = q_decode(p, lower_tail, log_p);
997 if !(0.0..=1.0).contains(&p) {
998 return f64::NAN;
999 }
1000 if p == 0.0 {
1001 return 0.0;
1002 }
1003 if p == 1.0 {
1004 return f64::INFINITY;
1005 }
1006 let bq = Rf_qbeta(p, df1 / 2.0, df2 / 2.0, 1, 0);
1008 (df2 * bq) / (df1 * (1.0 - bq))
1009}
1010
1011#[no_mangle]
1012pub extern "C" fn Rf_rf(df1: f64, df2: f64) -> f64 {
1013 (Rf_rchisq(df1) / df1) / (Rf_rchisq(df2) / df2)
1014}
1015
1016#[no_mangle]
1021pub extern "C" fn Rf_dlnorm(x: f64, meanlog: f64, sdlog: f64, give_log: c_int) -> f64 {
1022 if sdlog <= 0.0 {
1023 return f64::NAN;
1024 }
1025 if x <= 0.0 {
1026 return d_log(0.0, give_log);
1027 }
1028 let z = (x.ln() - meanlog) / sdlog;
1029 let log_d = -0.5 * z * z - LN_SQRT_2PI - sdlog.ln() - x.ln();
1030 if give_log != 0 {
1031 log_d
1032 } else {
1033 log_d.exp()
1034 }
1035}
1036
1037#[no_mangle]
1038pub extern "C" fn Rf_plnorm(
1039 x: f64,
1040 meanlog: f64,
1041 sdlog: f64,
1042 lower_tail: c_int,
1043 log_p: c_int,
1044) -> f64 {
1045 if sdlog <= 0.0 {
1046 return f64::NAN;
1047 }
1048 if x <= 0.0 {
1049 return p_transform(0.0, lower_tail, log_p);
1050 }
1051 Rf_pnorm5(x.ln(), meanlog, sdlog, lower_tail, log_p)
1052}
1053
1054#[no_mangle]
1055pub extern "C" fn Rf_qlnorm(
1056 p: f64,
1057 meanlog: f64,
1058 sdlog: f64,
1059 lower_tail: c_int,
1060 log_p: c_int,
1061) -> f64 {
1062 Rf_qnorm5(p, meanlog, sdlog, lower_tail, log_p).exp()
1063}
1064
1065#[no_mangle]
1066pub extern "C" fn Rf_rlnorm(meanlog: f64, sdlog: f64) -> f64 {
1067 Rf_rnorm(meanlog, sdlog).exp()
1068}
1069
1070#[no_mangle]
1075pub extern "C" fn Rf_dcauchy(x: f64, location: f64, scale: f64, give_log: c_int) -> f64 {
1076 if scale <= 0.0 {
1077 return f64::NAN;
1078 }
1079 let z = (x - location) / scale;
1080 let d = 1.0 / (std::f64::consts::PI * scale * (1.0 + z * z));
1081 d_log(d, give_log)
1082}
1083
1084#[no_mangle]
1085pub extern "C" fn Rf_pcauchy(
1086 x: f64,
1087 location: f64,
1088 scale: f64,
1089 lower_tail: c_int,
1090 log_p: c_int,
1091) -> f64 {
1092 if scale <= 0.0 {
1093 return f64::NAN;
1094 }
1095 let p = 0.5 + libm::atan((x - location) / scale) / std::f64::consts::PI;
1096 p_transform(p, lower_tail, log_p)
1097}
1098
1099#[no_mangle]
1100pub extern "C" fn Rf_qcauchy(
1101 p: f64,
1102 location: f64,
1103 scale: f64,
1104 lower_tail: c_int,
1105 log_p: c_int,
1106) -> f64 {
1107 if scale <= 0.0 {
1108 return f64::NAN;
1109 }
1110 let p = q_decode(p, lower_tail, log_p);
1111 if !(0.0..=1.0).contains(&p) {
1112 return f64::NAN;
1113 }
1114 location + scale * libm::tan(std::f64::consts::PI * (p - 0.5))
1115}
1116
1117#[no_mangle]
1118pub extern "C" fn Rf_rcauchy(location: f64, scale: f64) -> f64 {
1119 let u = unif_rand();
1120 location + scale * libm::tan(std::f64::consts::PI * (u - 0.5))
1121}
1122
1123#[no_mangle]
1128pub extern "C" fn Rf_dweibull(x: f64, shape: f64, scale: f64, give_log: c_int) -> f64 {
1129 if shape <= 0.0 || scale <= 0.0 {
1130 return f64::NAN;
1131 }
1132 if x < 0.0 {
1133 return d_log(0.0, give_log);
1134 }
1135 if x == 0.0 {
1136 if shape < 1.0 {
1137 return f64::INFINITY;
1138 }
1139 if shape == 1.0 {
1140 return d_log(1.0 / scale, give_log);
1141 }
1142 return d_log(0.0, give_log);
1143 }
1144 let z = x / scale;
1145 let log_d = (shape - 1.0) * z.ln() + shape.ln() - shape * scale.ln() - z.powf(shape);
1146 if give_log != 0 {
1147 log_d
1148 } else {
1149 log_d.exp()
1150 }
1151}
1152
1153#[no_mangle]
1154pub extern "C" fn Rf_pweibull(
1155 x: f64,
1156 shape: f64,
1157 scale: f64,
1158 lower_tail: c_int,
1159 log_p: c_int,
1160) -> f64 {
1161 if shape <= 0.0 || scale <= 0.0 {
1162 return f64::NAN;
1163 }
1164 if x <= 0.0 {
1165 return p_transform(0.0, lower_tail, log_p);
1166 }
1167 let p = -libm::expm1(-(x / scale).powf(shape));
1168 p_transform(p, lower_tail, log_p)
1169}
1170
1171#[no_mangle]
1172pub extern "C" fn Rf_qweibull(
1173 p: f64,
1174 shape: f64,
1175 scale: f64,
1176 lower_tail: c_int,
1177 log_p: c_int,
1178) -> f64 {
1179 if shape <= 0.0 || scale <= 0.0 {
1180 return f64::NAN;
1181 }
1182 let p = q_decode(p, lower_tail, log_p);
1183 if !(0.0..=1.0).contains(&p) {
1184 return f64::NAN;
1185 }
1186 scale * (-libm::log1p(-p)).powf(1.0 / shape)
1187}
1188
1189#[no_mangle]
1190pub extern "C" fn Rf_rweibull(shape: f64, scale: f64) -> f64 {
1191 let u = unif_rand();
1192 scale * (-u.ln()).powf(1.0 / shape)
1193}
1194
1195#[no_mangle]
1200pub extern "C" fn Rf_dlogis(x: f64, location: f64, scale: f64, give_log: c_int) -> f64 {
1201 if scale <= 0.0 {
1202 return f64::NAN;
1203 }
1204 let z = (x - location) / scale;
1205 let e = (-z.abs()).exp();
1206 let d = e / (scale * (1.0 + e) * (1.0 + e));
1207 d_log(d, give_log)
1208}
1209
1210#[no_mangle]
1211pub extern "C" fn Rf_plogis(
1212 x: f64,
1213 location: f64,
1214 scale: f64,
1215 lower_tail: c_int,
1216 log_p: c_int,
1217) -> f64 {
1218 if scale <= 0.0 {
1219 return f64::NAN;
1220 }
1221 let z = (x - location) / scale;
1222 let p = 1.0 / (1.0 + (-z).exp());
1223 p_transform(p, lower_tail, log_p)
1224}
1225
1226#[no_mangle]
1227pub extern "C" fn Rf_qlogis(
1228 p: f64,
1229 location: f64,
1230 scale: f64,
1231 lower_tail: c_int,
1232 log_p: c_int,
1233) -> f64 {
1234 if scale <= 0.0 {
1235 return f64::NAN;
1236 }
1237 let p = q_decode(p, lower_tail, log_p);
1238 if !(0.0..=1.0).contains(&p) {
1239 return f64::NAN;
1240 }
1241 location + scale * (p / (1.0 - p)).ln()
1242}
1243
1244#[no_mangle]
1245pub extern "C" fn Rf_rlogis(location: f64, scale: f64) -> f64 {
1246 let u = unif_rand();
1247 location + scale * (u / (1.0 - u)).ln()
1248}
1249
1250#[no_mangle]
1255pub extern "C" fn Rf_dpois(x: f64, lambda: f64, give_log: c_int) -> f64 {
1256 if lambda < 0.0 {
1257 return f64::NAN;
1258 }
1259 if x < 0.0 || x != x.floor() {
1260 return d_log(0.0, give_log);
1261 }
1262 let k = x as i64;
1263 let log_d = k as f64 * lambda.ln() - lambda - libm::lgamma(x + 1.0);
1264 if give_log != 0 {
1265 log_d
1266 } else {
1267 log_d.exp()
1268 }
1269}
1270
1271#[no_mangle]
1272pub extern "C" fn Rf_ppois(x: f64, lambda: f64, lower_tail: c_int, log_p: c_int) -> f64 {
1273 if lambda < 0.0 {
1274 return f64::NAN;
1275 }
1276 if x < 0.0 {
1277 return p_transform(0.0, lower_tail, log_p);
1278 }
1279 let k = x.floor();
1280 let p = qgamma_raw(k + 1.0, lambda);
1282 p_transform(p, lower_tail, log_p)
1283}
1284
1285#[no_mangle]
1286pub extern "C" fn Rf_qpois(p: f64, lambda: f64, lower_tail: c_int, log_p: c_int) -> f64 {
1287 if lambda < 0.0 {
1288 return f64::NAN;
1289 }
1290 let p = q_decode(p, lower_tail, log_p);
1291 if !(0.0..=1.0).contains(&p) {
1292 return f64::NAN;
1293 }
1294 if p == 0.0 {
1295 return 0.0;
1296 }
1297 if p == 1.0 {
1298 return f64::INFINITY;
1299 }
1300 let mut k = (lambda + 0.5).floor();
1302 loop {
1303 let pk = Rf_ppois(k, lambda, 1, 0);
1304 if pk >= p {
1305 break;
1306 }
1307 k += 1.0;
1308 if k > 1e15 {
1309 return f64::INFINITY;
1310 }
1311 }
1312 while k > 0.0 {
1314 let pk = Rf_ppois(k - 1.0, lambda, 1, 0);
1315 if pk < p {
1316 break;
1317 }
1318 k -= 1.0;
1319 }
1320 k
1321}
1322
1323#[no_mangle]
1324pub extern "C" fn Rf_rpois(lambda: f64) -> f64 {
1325 if lambda <= 0.0 {
1326 return 0.0;
1327 }
1328 if lambda < 30.0 {
1330 let l = (-lambda).exp();
1331 let mut k = 0.0;
1332 let mut p = 1.0;
1333 loop {
1334 k += 1.0;
1335 p *= unif_rand();
1336 if p <= l {
1337 return k - 1.0;
1338 }
1339 }
1340 }
1341 loop {
1343 let x = Rf_rnorm(lambda, lambda.sqrt());
1344 let k = (x + 0.5).floor();
1345 if k >= 0.0 {
1346 return k;
1347 }
1348 }
1349}
1350
1351#[no_mangle]
1356pub extern "C" fn Rf_dbinom(x: f64, n: f64, p: f64, give_log: c_int) -> f64 {
1357 if n < 0.0 || !(0.0..=1.0).contains(&p) || n != n.floor() {
1358 return f64::NAN;
1359 }
1360 if x < 0.0 || x > n || x != x.floor() {
1361 return d_log(0.0, give_log);
1362 }
1363 let log_d = lchoose_fn(n, x) + x * p.ln() + (n - x) * (1.0 - p).ln();
1364 if give_log != 0 {
1365 log_d
1366 } else {
1367 log_d.exp()
1368 }
1369}
1370
1371#[no_mangle]
1372pub extern "C" fn Rf_pbinom(x: f64, n: f64, p: f64, lower_tail: c_int, log_p: c_int) -> f64 {
1373 if n < 0.0 || !(0.0..=1.0).contains(&p) || n != n.floor() {
1374 return f64::NAN;
1375 }
1376 if x < 0.0 {
1377 return p_transform(0.0, lower_tail, log_p);
1378 }
1379 if x >= n {
1380 return p_transform(1.0, lower_tail, log_p);
1381 }
1382 let k = x.floor();
1383 let cdf = pbeta_raw(1.0 - p, n - k, k + 1.0);
1385 p_transform(cdf, lower_tail, log_p)
1386}
1387
1388#[no_mangle]
1389pub extern "C" fn Rf_qbinom(p: f64, n: f64, prob: f64, lower_tail: c_int, log_p: c_int) -> f64 {
1390 if n < 0.0 || !(0.0..=1.0).contains(&prob) || n != n.floor() {
1391 return f64::NAN;
1392 }
1393 let p = q_decode(p, lower_tail, log_p);
1394 if !(0.0..=1.0).contains(&p) {
1395 return f64::NAN;
1396 }
1397 if p == 0.0 {
1398 return 0.0;
1399 }
1400 if p == 1.0 {
1401 return n;
1402 }
1403 let mu = n * prob;
1405 let mut k = mu.floor();
1406 loop {
1407 let pk = Rf_pbinom(k, n, prob, 1, 0);
1408 if pk >= p {
1409 break;
1410 }
1411 k += 1.0;
1412 if k > n {
1413 return n;
1414 }
1415 }
1416 while k > 0.0 {
1417 let pk = Rf_pbinom(k - 1.0, n, prob, 1, 0);
1418 if pk < p {
1419 break;
1420 }
1421 k -= 1.0;
1422 }
1423 k
1424}
1425
1426#[no_mangle]
1427pub extern "C" fn Rf_rbinom(n: f64, p: f64) -> f64 {
1428 if n <= 0.0 || p <= 0.0 {
1429 return 0.0;
1430 }
1431 if p >= 1.0 {
1432 return n;
1433 }
1434 let ni = n as i64;
1435 if ni <= 20 {
1436 let mut x = 0i64;
1438 for _ in 0..ni {
1439 if unif_rand() < p {
1440 x += 1;
1441 }
1442 }
1443 return x as f64;
1444 }
1445 let x = Rf_rnorm(n * p, (n * p * (1.0 - p)).sqrt());
1447 x.round().clamp(0.0, n)
1448}
1449
1450#[no_mangle]
1451pub extern "C" fn rmultinom(_n: c_int, _prob: *mut f64, _k: c_int, _rn: *mut c_int) {
1452 }
1454
1455#[no_mangle]
1460pub extern "C" fn Rf_dgeom(x: f64, p: f64, give_log: c_int) -> f64 {
1461 if p <= 0.0 || p > 1.0 {
1462 return f64::NAN;
1463 }
1464 if x < 0.0 || x != x.floor() {
1465 return d_log(0.0, give_log);
1466 }
1467 let log_d = p.ln() + x * (1.0 - p).ln();
1468 if give_log != 0 {
1469 log_d
1470 } else {
1471 log_d.exp()
1472 }
1473}
1474
1475#[no_mangle]
1476pub extern "C" fn Rf_pgeom(x: f64, p: f64, lower_tail: c_int, log_p: c_int) -> f64 {
1477 if p <= 0.0 || p > 1.0 {
1478 return f64::NAN;
1479 }
1480 if x < 0.0 {
1481 return p_transform(0.0, lower_tail, log_p);
1482 }
1483 let k = x.floor();
1484 let cdf = 1.0 - (1.0 - p).powf(k + 1.0);
1485 p_transform(cdf, lower_tail, log_p)
1486}
1487
1488#[no_mangle]
1489pub extern "C" fn Rf_qgeom(p: f64, prob: f64, lower_tail: c_int, log_p: c_int) -> f64 {
1490 if prob <= 0.0 || prob > 1.0 {
1491 return f64::NAN;
1492 }
1493 let p = q_decode(p, lower_tail, log_p);
1494 if !(0.0..=1.0).contains(&p) {
1495 return f64::NAN;
1496 }
1497 if p == 0.0 {
1498 return 0.0;
1499 }
1500 if p == 1.0 {
1501 return f64::INFINITY;
1502 }
1503 (libm::log1p(-p) / libm::log1p(-prob)).ceil() - 1.0
1505}
1506
1507#[no_mangle]
1508pub extern "C" fn Rf_rgeom(p: f64) -> f64 {
1509 let u = unif_rand();
1510 (u.ln() / libm::log1p(-p)).floor()
1511}
1512
1513#[no_mangle]
1518pub extern "C" fn Rf_dhyper(x: f64, r: f64, b: f64, n: f64, give_log: c_int) -> f64 {
1519 if r < 0.0 || b < 0.0 || n < 0.0 {
1520 return f64::NAN;
1521 }
1522 if x < 0.0 || x != x.floor() || x > r || x > n || n - x > b {
1523 return d_log(0.0, give_log);
1524 }
1525 let log_d = lchoose_fn(r, x) + lchoose_fn(b, n - x) - lchoose_fn(r + b, n);
1526 if give_log != 0 {
1527 log_d
1528 } else {
1529 log_d.exp()
1530 }
1531}
1532
1533#[no_mangle]
1534pub extern "C" fn Rf_phyper(
1535 x: f64,
1536 r: f64,
1537 b: f64,
1538 n: f64,
1539 lower_tail: c_int,
1540 log_p: c_int,
1541) -> f64 {
1542 if r < 0.0 || b < 0.0 || n < 0.0 {
1543 return f64::NAN;
1544 }
1545 if x < 0.0 {
1546 return p_transform(0.0, lower_tail, log_p);
1547 }
1548 let k = x.floor();
1549 let lo = 0.0_f64.max(n - b);
1550 let hi = r.min(n);
1551 if k >= hi {
1552 return p_transform(1.0, lower_tail, log_p);
1553 }
1554 let mut sum = 0.0;
1555 let mut i = lo;
1556 while i <= k {
1557 sum += Rf_dhyper(i, r, b, n, 0);
1558 i += 1.0;
1559 }
1560 p_transform(sum, lower_tail, log_p)
1561}
1562
1563#[no_mangle]
1564pub extern "C" fn Rf_qhyper(
1565 p: f64,
1566 r: f64,
1567 b: f64,
1568 n: f64,
1569 lower_tail: c_int,
1570 log_p: c_int,
1571) -> f64 {
1572 let p = q_decode(p, lower_tail, log_p);
1573 if !(0.0..=1.0).contains(&p) || r < 0.0 || b < 0.0 || n < 0.0 {
1574 return f64::NAN;
1575 }
1576 let lo = 0.0_f64.max(n - b);
1577 let hi = r.min(n);
1578 let mut k = lo;
1579 let mut cum = 0.0;
1580 while k <= hi {
1581 cum += Rf_dhyper(k, r, b, n, 0);
1582 if cum >= p {
1583 return k;
1584 }
1585 k += 1.0;
1586 }
1587 hi
1588}
1589
1590#[no_mangle]
1591pub extern "C" fn Rf_rhyper(r: f64, b: f64, n: f64) -> f64 {
1592 let total = r + b;
1594 if total <= 0.0 || n <= 0.0 {
1595 return 0.0;
1596 }
1597 let mut whites = r;
1598 let mut remaining = total;
1599 let mut drawn = 0.0;
1600 let ni = n.min(total) as i64;
1601 for _ in 0..ni {
1602 let u = unif_rand();
1603 if u < whites / remaining {
1604 drawn += 1.0;
1605 whites -= 1.0;
1606 }
1607 remaining -= 1.0;
1608 }
1609 drawn
1610}
1611
1612#[no_mangle]
1617pub extern "C" fn Rf_dnbinom(x: f64, size: f64, prob: f64, give_log: c_int) -> f64 {
1618 if size <= 0.0 || prob <= 0.0 || prob > 1.0 {
1619 return f64::NAN;
1620 }
1621 if x < 0.0 || x != x.floor() {
1622 return d_log(0.0, give_log);
1623 }
1624 let log_d = lchoose_fn(x + size - 1.0, x) + size * prob.ln() + x * (1.0 - prob).ln();
1625 if give_log != 0 {
1626 log_d
1627 } else {
1628 log_d.exp()
1629 }
1630}
1631
1632#[no_mangle]
1633pub extern "C" fn Rf_pnbinom(x: f64, size: f64, prob: f64, lower_tail: c_int, log_p: c_int) -> f64 {
1634 if size <= 0.0 || prob <= 0.0 || prob > 1.0 {
1635 return f64::NAN;
1636 }
1637 if x < 0.0 {
1638 return p_transform(0.0, lower_tail, log_p);
1639 }
1640 let k = x.floor();
1641 let p = pbeta_raw(prob, size, k + 1.0);
1643 p_transform(p, lower_tail, log_p)
1644}
1645
1646#[no_mangle]
1647pub extern "C" fn Rf_qnbinom(p: f64, size: f64, prob: f64, lower_tail: c_int, log_p: c_int) -> f64 {
1648 if size <= 0.0 || prob <= 0.0 || prob > 1.0 {
1649 return f64::NAN;
1650 }
1651 let p = q_decode(p, lower_tail, log_p);
1652 if !(0.0..=1.0).contains(&p) {
1653 return f64::NAN;
1654 }
1655 if p == 0.0 {
1656 return 0.0;
1657 }
1658 if p == 1.0 {
1659 return f64::INFINITY;
1660 }
1661 let mu = size * (1.0 - prob) / prob;
1662 let mut k = mu.floor();
1663 loop {
1664 let pk = Rf_pnbinom(k, size, prob, 1, 0);
1665 if pk >= p {
1666 break;
1667 }
1668 k += 1.0;
1669 if k > 1e15 {
1670 return f64::INFINITY;
1671 }
1672 }
1673 while k > 0.0 {
1674 let pk = Rf_pnbinom(k - 1.0, size, prob, 1, 0);
1675 if pk < p {
1676 break;
1677 }
1678 k -= 1.0;
1679 }
1680 k
1681}
1682
1683#[no_mangle]
1684pub extern "C" fn Rf_rnbinom(size: f64, prob: f64) -> f64 {
1685 let rate = (1.0 - prob) / prob;
1686 let g = Rf_rgamma(size, rate);
1687 Rf_rpois(g)
1688}
1689
1690#[no_mangle]
1692pub extern "C" fn Rf_dnbinom_mu(x: f64, size: f64, mu: f64, give_log: c_int) -> f64 {
1693 if size <= 0.0 || mu < 0.0 {
1694 return f64::NAN;
1695 }
1696 let prob = size / (size + mu);
1697 Rf_dnbinom(x, size, prob, give_log)
1698}
1699
1700#[no_mangle]
1701pub extern "C" fn Rf_pnbinom_mu(
1702 x: f64,
1703 size: f64,
1704 mu: f64,
1705 lower_tail: c_int,
1706 log_p: c_int,
1707) -> f64 {
1708 if size <= 0.0 || mu < 0.0 {
1709 return f64::NAN;
1710 }
1711 let prob = size / (size + mu);
1712 Rf_pnbinom(x, size, prob, lower_tail, log_p)
1713}
1714
1715#[no_mangle]
1716pub extern "C" fn Rf_qnbinom_mu(
1717 x: f64,
1718 size: f64,
1719 mu: f64,
1720 lower_tail: c_int,
1721 log_p: c_int,
1722) -> f64 {
1723 if size <= 0.0 || mu < 0.0 {
1724 return f64::NAN;
1725 }
1726 let prob = size / (size + mu);
1727 Rf_qnbinom(x, size, prob, lower_tail, log_p)
1728}
1729
1730#[no_mangle]
1735pub extern "C" fn Rf_dnbeta(x: f64, a: f64, b: f64, ncp: f64, give_log: c_int) -> f64 {
1736 if a <= 0.0 || b <= 0.0 || ncp < 0.0 {
1737 return f64::NAN;
1738 }
1739 if ncp == 0.0 {
1740 return Rf_dbeta(x, a, b, give_log);
1741 }
1742 let lambda = ncp / 2.0;
1744 let max_terms = 100.min((lambda + 20.0 * lambda.sqrt()) as usize + 10);
1745 let mut sum = 0.0;
1746 let mut pw = (-lambda).exp();
1747 for j in 0..max_terms {
1748 sum += pw * Rf_dbeta(x, a + j as f64, b, 0);
1749 pw *= lambda / (j as f64 + 1.0);
1750 }
1751 d_log(sum, give_log)
1752}
1753
1754#[no_mangle]
1755pub extern "C" fn Rf_pnbeta(
1756 x: f64,
1757 a: f64,
1758 b: f64,
1759 ncp: f64,
1760 lower_tail: c_int,
1761 log_p: c_int,
1762) -> f64 {
1763 if a <= 0.0 || b <= 0.0 || ncp < 0.0 {
1764 return f64::NAN;
1765 }
1766 if ncp == 0.0 {
1767 return Rf_pbeta(x, a, b, lower_tail, log_p);
1768 }
1769 let lambda = ncp / 2.0;
1770 let max_terms = 100.min((lambda + 20.0 * lambda.sqrt()) as usize + 10);
1771 let mut sum = 0.0;
1772 let mut pw = (-lambda).exp();
1773 for j in 0..max_terms {
1774 sum += pw * pbeta_raw(x, a + j as f64, b);
1775 pw *= lambda / (j as f64 + 1.0);
1776 }
1777 p_transform(sum, lower_tail, log_p)
1778}
1779
1780#[no_mangle]
1781pub extern "C" fn Rf_qnbeta(
1782 p: f64,
1783 a: f64,
1784 b: f64,
1785 ncp: f64,
1786 lower_tail: c_int,
1787 log_p: c_int,
1788) -> f64 {
1789 if a <= 0.0 || b <= 0.0 || ncp < 0.0 {
1790 return f64::NAN;
1791 }
1792 let p = q_decode(p, lower_tail, log_p);
1793 if !(0.0..=1.0).contains(&p) {
1794 return f64::NAN;
1795 }
1796 let mut x = Rf_qbeta(p, a, b, 1, 0);
1798 for _ in 0..50 {
1799 let px = Rf_pnbeta(x, a, b, ncp, 1, 0);
1800 let dx = Rf_dnbeta(x, a, b, ncp, 0);
1801 if dx <= 0.0 {
1802 break;
1803 }
1804 let delta = (px - p) / dx;
1805 x -= delta;
1806 x = x.clamp(DBL_EPSILON, 1.0 - DBL_EPSILON);
1807 if delta.abs() < x * 1e-12 {
1808 break;
1809 }
1810 }
1811 x
1812}
1813
1814#[no_mangle]
1819pub extern "C" fn Rf_dnf(x: f64, df1: f64, df2: f64, ncp: f64, give_log: c_int) -> f64 {
1820 if df1 <= 0.0 || df2 <= 0.0 || ncp < 0.0 {
1821 return f64::NAN;
1822 }
1823 if x <= 0.0 {
1824 return d_log(0.0, give_log);
1825 }
1826 let y = df1 * x / (df1 * x + df2);
1828 let dy_dx = df1 * df2 / ((df1 * x + df2) * (df1 * x + df2));
1829 let d = Rf_dnbeta(y, df1 / 2.0, df2 / 2.0, ncp, 0) * dy_dx;
1830 d_log(d, give_log)
1831}
1832
1833#[no_mangle]
1834pub extern "C" fn Rf_pnf(
1835 x: f64,
1836 df1: f64,
1837 df2: f64,
1838 ncp: f64,
1839 lower_tail: c_int,
1840 log_p: c_int,
1841) -> f64 {
1842 if df1 <= 0.0 || df2 <= 0.0 || ncp < 0.0 {
1843 return f64::NAN;
1844 }
1845 if x <= 0.0 {
1846 return p_transform(0.0, lower_tail, log_p);
1847 }
1848 let y = df1 * x / (df1 * x + df2);
1849 Rf_pnbeta(y, df1 / 2.0, df2 / 2.0, ncp, lower_tail, log_p)
1850}
1851
1852#[no_mangle]
1853pub extern "C" fn Rf_qnf(
1854 p: f64,
1855 df1: f64,
1856 df2: f64,
1857 ncp: f64,
1858 lower_tail: c_int,
1859 log_p: c_int,
1860) -> f64 {
1861 if df1 <= 0.0 || df2 <= 0.0 || ncp < 0.0 {
1862 return f64::NAN;
1863 }
1864 let bq = Rf_qnbeta(p, df1 / 2.0, df2 / 2.0, ncp, lower_tail, log_p);
1865 (df2 * bq) / (df1 * (1.0 - bq))
1866}
1867
1868#[no_mangle]
1873pub extern "C" fn Rf_dnt(x: f64, df: f64, ncp: f64, give_log: c_int) -> f64 {
1874 if df <= 0.0 {
1875 return f64::NAN;
1876 }
1877 if ncp == 0.0 {
1878 return Rf_dt(x, df, give_log);
1879 }
1880 let h = 1e-7 * (1.0 + x.abs());
1882 let d = (Rf_pnt(x + h, df, ncp, 1, 0) - Rf_pnt(x - h, df, ncp, 1, 0)) / (2.0 * h);
1883 if d < 0.0 {
1884 return d_log(0.0, give_log);
1885 }
1886 d_log(d, give_log)
1887}
1888
1889#[no_mangle]
1890pub extern "C" fn Rf_pnt(x: f64, df: f64, ncp: f64, lower_tail: c_int, log_p: c_int) -> f64 {
1891 if df <= 0.0 {
1892 return f64::NAN;
1893 }
1894 if ncp == 0.0 {
1895 return Rf_pt(x, df, lower_tail, log_p);
1896 }
1897 let z = x * (1.0 - 1.0 / (4.0 * df)).sqrt() - ncp;
1899 let p = Rf_pnorm5(z, 0.0, 1.0, 1, 0);
1900 p_transform(p, lower_tail, log_p)
1901}
1902
1903#[no_mangle]
1904pub extern "C" fn Rf_qnt(p: f64, df: f64, ncp: f64, lower_tail: c_int, log_p: c_int) -> f64 {
1905 if df <= 0.0 {
1906 return f64::NAN;
1907 }
1908 let p = q_decode(p, lower_tail, log_p);
1909 if !(0.0..=1.0).contains(&p) {
1910 return f64::NAN;
1911 }
1912 let mut x = qnorm_standard(p) + ncp;
1914 for _ in 0..50 {
1915 let px = Rf_pnt(x, df, ncp, 1, 0);
1916 let dx = Rf_dnt(x, df, ncp, 0);
1917 if dx <= 0.0 || !dx.is_finite() {
1918 break;
1919 }
1920 let delta = (px - p) / dx;
1921 x -= delta;
1922 if delta.abs() < x.abs() * 1e-10 {
1923 break;
1924 }
1925 }
1926 x
1927}
1928
1929#[no_mangle]
1934pub extern "C" fn Rf_ptukey(_q: f64, _rr: f64, _cc: f64, _df: f64, _lt: c_int, _lg: c_int) -> f64 {
1935 f64::NAN
1937}
1938
1939#[no_mangle]
1940pub extern "C" fn Rf_qtukey(_p: f64, _rr: f64, _cc: f64, _df: f64, _lt: c_int, _lg: c_int) -> f64 {
1941 f64::NAN
1942}
1943
1944#[no_mangle]
1949pub extern "C" fn Rf_dwilcox(x: f64, m: f64, n: f64, give_log: c_int) -> f64 {
1950 if m < 0.0 || n < 0.0 {
1951 return f64::NAN;
1952 }
1953 if x < 0.0 || x != x.floor() || x > m * n {
1954 return d_log(0.0, give_log);
1955 }
1956 let total = choose_fn(m + n, n);
1958 if total == 0.0 {
1959 return d_log(0.0, give_log);
1960 }
1961 let mu = m * n / 2.0;
1964 let sigma = (m * n * (m + n + 1.0) / 12.0).sqrt();
1965 if sigma <= 0.0 {
1966 return d_log(if x == mu { 1.0 } else { 0.0 }, give_log);
1967 }
1968 Rf_dnorm4(x, mu, sigma, give_log)
1970}
1971
1972#[no_mangle]
1973pub extern "C" fn Rf_pwilcox(x: f64, m: f64, n: f64, lower_tail: c_int, log_p: c_int) -> f64 {
1974 if m < 0.0 || n < 0.0 {
1975 return f64::NAN;
1976 }
1977 let mu = m * n / 2.0;
1978 let sigma = (m * n * (m + n + 1.0) / 12.0).sqrt();
1979 if sigma <= 0.0 {
1980 return p_transform(if x >= mu { 1.0 } else { 0.0 }, lower_tail, log_p);
1981 }
1982 Rf_pnorm5(x + 0.5, mu, sigma, lower_tail, log_p)
1984}
1985
1986#[no_mangle]
1987pub extern "C" fn Rf_qwilcox(p: f64, m: f64, n: f64, lower_tail: c_int, log_p: c_int) -> f64 {
1988 if m < 0.0 || n < 0.0 {
1989 return f64::NAN;
1990 }
1991 let mu = m * n / 2.0;
1992 let sigma = (m * n * (m + n + 1.0) / 12.0).sqrt();
1993 if sigma <= 0.0 {
1994 return mu;
1995 }
1996 let q = Rf_qnorm5(p, mu, sigma, lower_tail, log_p);
1997 q.round().clamp(0.0, m * n)
1998}
1999
2000#[no_mangle]
2001pub extern "C" fn Rf_rwilcox(m: f64, n: f64) -> f64 {
2002 let total = (m + n) as usize;
2004 let mi = m as usize;
2005 let mut sum = 0.0;
2007 let mut remaining = total;
2008 let mut need = mi;
2009 for rank in 1..=total {
2010 let u = unif_rand();
2011 if (u * remaining as f64) < need as f64 {
2012 sum += rank as f64;
2013 need -= 1;
2014 if need == 0 {
2015 break;
2016 }
2017 }
2018 remaining -= 1;
2019 }
2020 sum - m * (m + 1.0) / 2.0
2022}
2023
2024#[no_mangle]
2029pub extern "C" fn Rf_dsignrank(x: f64, n: f64, give_log: c_int) -> f64 {
2030 if n < 0.0 {
2031 return f64::NAN;
2032 }
2033 let mu = n * (n + 1.0) / 4.0;
2034 let sigma = (n * (n + 1.0) * (2.0 * n + 1.0) / 24.0).sqrt();
2035 if sigma <= 0.0 {
2036 return d_log(if x == mu { 1.0 } else { 0.0 }, give_log);
2037 }
2038 Rf_dnorm4(x, mu, sigma, give_log)
2039}
2040
2041#[no_mangle]
2042pub extern "C" fn Rf_psignrank(x: f64, n: f64, lower_tail: c_int, log_p: c_int) -> f64 {
2043 if n < 0.0 {
2044 return f64::NAN;
2045 }
2046 let mu = n * (n + 1.0) / 4.0;
2047 let sigma = (n * (n + 1.0) * (2.0 * n + 1.0) / 24.0).sqrt();
2048 if sigma <= 0.0 {
2049 return p_transform(if x >= mu { 1.0 } else { 0.0 }, lower_tail, log_p);
2050 }
2051 Rf_pnorm5(x + 0.5, mu, sigma, lower_tail, log_p)
2052}
2053
2054#[no_mangle]
2055pub extern "C" fn Rf_qsignrank(p: f64, n: f64, lower_tail: c_int, log_p: c_int) -> f64 {
2056 if n < 0.0 {
2057 return f64::NAN;
2058 }
2059 let mu = n * (n + 1.0) / 4.0;
2060 let sigma = (n * (n + 1.0) * (2.0 * n + 1.0) / 24.0).sqrt();
2061 if sigma <= 0.0 {
2062 return mu;
2063 }
2064 let q = Rf_qnorm5(p, mu, sigma, lower_tail, log_p);
2065 q.round().clamp(0.0, n * (n + 1.0) / 2.0)
2066}
2067
2068#[no_mangle]
2069pub extern "C" fn Rf_rsignrank(n: f64) -> f64 {
2070 let ni = n as i64;
2071 let mut sum = 0.0;
2072 for i in 1..=ni {
2073 if unif_rand() > 0.5 {
2074 sum += i as f64;
2075 }
2076 }
2077 sum
2078}
2079
2080#[no_mangle]
2085pub extern "C" fn Rf_bessel_j(x: f64, alpha: f64) -> f64 {
2086 if alpha == 0.0 {
2087 return libm::j0(x);
2088 }
2089 if alpha == 1.0 {
2090 return libm::j1(x);
2091 }
2092 if alpha == alpha.floor() && alpha >= 0.0 {
2093 return libm::jn(alpha as i32, x);
2094 }
2095 bessel_j_series(x, alpha)
2097}
2098
2099#[no_mangle]
2100pub extern "C" fn Rf_bessel_y(x: f64, alpha: f64) -> f64 {
2101 if x <= 0.0 {
2102 return f64::NEG_INFINITY;
2103 }
2104 if alpha == 0.0 {
2105 return libm::y0(x);
2106 }
2107 if alpha == 1.0 {
2108 return libm::y1(x);
2109 }
2110 if alpha == alpha.floor() && alpha >= 0.0 {
2111 return libm::yn(alpha as i32, x);
2112 }
2113 let pi_a = alpha * std::f64::consts::PI;
2115 (Rf_bessel_j(x, alpha) * pi_a.cos() - Rf_bessel_j(x, -alpha)) / pi_a.sin()
2116}
2117
2118#[no_mangle]
2119pub extern "C" fn Rf_bessel_i(x: f64, alpha: f64, expo: f64) -> f64 {
2120 let val = bessel_i_series(x, alpha);
2122 if expo != 1.0 {
2123 val
2124 } else {
2125 val * (-x.abs()).exp()
2126 }
2127}
2128
2129#[no_mangle]
2130pub extern "C" fn Rf_bessel_k(x: f64, alpha: f64, expo: f64) -> f64 {
2131 if x <= 0.0 {
2132 return f64::INFINITY;
2133 }
2134 let val = if (alpha - alpha.round()).abs() < 1e-15 {
2137 bessel_k_int(x, alpha.round() as i32)
2139 } else {
2140 let pi_a = alpha * std::f64::consts::PI;
2141 std::f64::consts::PI / 2.0 * (bessel_i_series(x, -alpha) - bessel_i_series(x, alpha))
2142 / pi_a.sin()
2143 };
2144 if expo != 1.0 {
2145 val
2146 } else {
2147 val * x.exp()
2148 }
2149}
2150
2151fn bessel_j_series(x: f64, alpha: f64) -> f64 {
2152 let half_x = x / 2.0;
2153 let mut term = half_x.powf(alpha) / libm::tgamma(alpha + 1.0);
2154 let mut sum = term;
2155 let x2_neg = -half_x * half_x;
2156 for m in 1..100 {
2157 term *= x2_neg / (m as f64 * (alpha + m as f64));
2158 sum += term;
2159 if term.abs() < sum.abs() * DBL_EPSILON {
2160 break;
2161 }
2162 }
2163 sum
2164}
2165
2166fn bessel_i_series(x: f64, alpha: f64) -> f64 {
2167 let half_x = x / 2.0;
2168 let mut term = half_x.powf(alpha) / libm::tgamma(alpha + 1.0);
2169 let mut sum = term;
2170 let x2 = half_x * half_x;
2171 for m in 1..100 {
2172 term *= x2 / (m as f64 * (alpha + m as f64));
2173 sum += term;
2174 if term.abs() < sum.abs() * DBL_EPSILON {
2175 break;
2176 }
2177 }
2178 sum
2179}
2180
2181fn bessel_k_int(x: f64, n: i32) -> f64 {
2182 if n == 0 {
2184 return bessel_k0(x);
2185 }
2186 if n == 1 {
2187 return bessel_k1(x);
2188 }
2189 let mut km1 = bessel_k0(x);
2190 let mut k = bessel_k1(x);
2191 for i in 1..n.unsigned_abs() {
2192 let kp1 = km1 + 2.0 * i as f64 / x * k;
2193 km1 = k;
2194 k = kp1;
2195 }
2196 k
2197}
2198
2199fn bessel_k0(x: f64) -> f64 {
2200 if x <= 2.0 {
2201 let y = x * x / 4.0;
2202 -x.ln() * bessel_i_series(x, 0.0)
2203 + (-0.57721566
2204 + y * (0.42278420
2205 + y * (0.23069756 + y * (0.03488590 + y * (0.00262698 + y * 0.00010750)))))
2206 } else {
2207 let y = 2.0 / x;
2208 ((-x).exp() / x.sqrt())
2209 * (1.25331414
2210 + y * (-0.07832358
2211 + y * (0.02189568 + y * (-0.01062446 + y * (0.00587872 + y * (-0.00251540))))))
2212 }
2213}
2214
2215fn bessel_k1(x: f64) -> f64 {
2216 if x <= 2.0 {
2217 let y = x * x / 4.0;
2218 x.ln() * bessel_i_series(x, 1.0)
2219 + (1.0 / x)
2220 * (1.0
2221 + y * (0.15443144
2222 + y * (-0.67278579
2223 + y * (-0.18156897 + y * (-0.01919402 + y * (-0.00110404))))))
2224 } else {
2225 let y = 2.0 / x;
2226 ((-x).exp() / x.sqrt())
2227 * (1.25331414
2228 + y * (0.23498619
2229 + y * (-0.03655620 + y * (0.01504268 + y * (-0.00780353 + y * 0.00325614)))))
2230 }
2231}
2232
2233#[no_mangle]
2235pub extern "C" fn Rf_bessel_i_ex(x: f64, alpha: f64, expo: f64, bi: *mut f64) -> f64 {
2236 let val = Rf_bessel_i(x, alpha, expo);
2237 if !bi.is_null() {
2238 unsafe {
2239 *bi = val;
2240 }
2241 }
2242 val
2243}
2244
2245#[no_mangle]
2246pub extern "C" fn Rf_bessel_j_ex(x: f64, alpha: f64, bj: *mut f64) -> f64 {
2247 let val = Rf_bessel_j(x, alpha);
2248 if !bj.is_null() {
2249 unsafe {
2250 *bj = val;
2251 }
2252 }
2253 val
2254}
2255
2256#[no_mangle]
2257pub extern "C" fn Rf_bessel_k_ex(x: f64, alpha: f64, expo: f64, bk: *mut f64) -> f64 {
2258 let val = Rf_bessel_k(x, alpha, expo);
2259 if !bk.is_null() {
2260 unsafe {
2261 *bk = val;
2262 }
2263 }
2264 val
2265}
2266
2267#[no_mangle]
2268pub extern "C" fn Rf_bessel_y_ex(x: f64, alpha: f64, by: *mut f64) -> f64 {
2269 let val = Rf_bessel_y(x, alpha);
2270 if !by.is_null() {
2271 unsafe {
2272 *by = val;
2273 }
2274 }
2275 val
2276}
2277
2278#[no_mangle]
2279pub extern "C" fn Rf_hypot(a: f64, b: f64) -> f64 {
2280 a.hypot(b)
2281}
2282
2283