use std::{cell::RefCell, thread_local};
use fnv::FnvHashMap;
thread_local! {
static W: RefCell<FnvHashMap<usize, FnvHashMap<usize, FnvHashMap<usize, f64>>>> = RefCell::new(FnvHashMap::default());
}
pub fn reset_wilcox_statics() {
W.with(|W_| *W_.borrow_mut() = FnvHashMap::default());
}
pub fn cwilcox(mut k: i32, m: usize, n: usize) -> f64 {
let mut c = 0;
let mut u = 0;
let mut i = 0;
let mut j = 0;
u = m * n;
if k < 0 || k > u as i32 {
return 0.0;
}
c = u / 2;
if k > c as i32 {
k = u as i32 - k;
}
if m < n {
i = m;
j = n;
} else {
i = n;
j = m;
}
if j == 0 {
return if k == 0 { 1.0 } else { 0.0 };
}
if j > 0 && k < j as i32 {
return cwilcox(k, i, k as usize);
}
let mut w_current = W.with(|W_| {
let mut w = W_.borrow_mut();
*w.entry(i)
.or_insert_with(FnvHashMap::default)
.entry(j)
.or_insert_with(FnvHashMap::default)
.entry(k as usize)
.or_insert(-1.0)
});
w_current = if w_current < 0.0 {
let w_temp = if j == 0 {
if k == 0 {
1.0
} else {
0.0
}
} else {
cwilcox(k - j as i32, i - 1, j) + cwilcox(k, i, j - 1)
};
W.with(|W_| {
let mut w = W_.borrow_mut();
*w.entry(i)
.or_insert_with(FnvHashMap::default)
.entry(j)
.or_insert_with(FnvHashMap::default)
.entry(k as usize)
.or_insert(-1.0) = w_temp;
});
w_temp
} else {
w_current
};
return w_current;
}