use strafe_type::{FloatConstraint, Natural64, Real64};
use crate::{
distribution::wilcox::cwilcox,
func::{choose, lchoose},
traits::DPQ,
};
pub fn dwilcox<R: Into<Real64>, N1: Into<Natural64>, N2: Into<Natural64>>(
x: R,
m: N1,
n: N2,
log: bool,
) -> Real64 {
let mut x = x.into().unwrap();
let mut m = m.into().unwrap();
let mut n = n.into().unwrap();
let mut d = 0.0;
m = m.round();
n = n.round();
if (x - x.round()).abs() > 1e-7 {
return f64::d_0(log).into();
}
x = x.round();
if x < 0.0 || x > m * n {
return f64::d_0(log).into();
}
let mm = m;
let nn = n;
let xx = x;
d = if log {
(cwilcox(xx as i32, mm as usize, nn as usize).ln()) - lchoose(m + n, n).unwrap()
} else {
(cwilcox(xx as i32, mm as usize, nn as usize)) / choose(m + n, n).unwrap()
};
d.into()
}