#![doc = include_str!("../README.md")]
#![forbid(unsafe_code)]
#![deny(missing_docs)]
#[cfg(feature = "f64")]
pub type FP = f64;
#[cfg(feature = "f32")]
pub type FP = f32;
#[derive(Debug,PartialEq, PartialOrd)]
pub struct WilsonResult {
pub low: FP,
pub high: FP,
}
#[must_use]
pub fn wilson(successes: FP, trials: FP, z: FP) -> WilsonResult {
if trials <= 0.001 {
return WilsonResult {
low: 0.0,
high: 1.0,
};
}
let n = trials;
let s = successes;
let p = (s + 0.5 * z * z) / (n + z * z);
let d = z / (n + z * z) * (s * (n - s) / n + z * z / 4.0).sqrt();
let high = p + d;
let low = p - d;
WilsonResult { low, high }
}
#[cfg(test)]
mod tests {
use approx::assert_abs_diff_eq;
use super::*;
#[test]
fn it_works() {
{
let out = wilson(1.0, 2.0, 2.0);
assert_abs_diff_eq!(out.low, 0.09175170954, epsilon = 0.000001);
assert_abs_diff_eq!(out.high, 0.9082482905, epsilon = 0.000001);
}
{
let out = wilson(10.0, 20.0, 2.0);
assert_abs_diff_eq!(out.low, 0.2958758548, epsilon = 0.000001);
assert_abs_diff_eq!(out.high, 0.7041241452, epsilon = 0.000001);
}
{
let out = wilson(2.0, 20.0, 2.0);
assert_abs_diff_eq!(out.low, 0.02722332891, epsilon = 0.000001);
assert_abs_diff_eq!(out.high, 0.3061100044, epsilon = 0.000001);
}
{
let out = wilson(2.0, 20.0, 3.0);
assert_abs_diff_eq!(out.low, 0.01595229175, epsilon = 0.000001);
assert_abs_diff_eq!(out.high, 0.4323235703, epsilon = 0.000001);
}
{
let out = wilson(20.0, 20.0, 2.0);
assert_abs_diff_eq!(out.low, 0.8333333333, epsilon = 0.000001);
assert_abs_diff_eq!(out.high, 1.0, epsilon = 0.000001);
} {
let out = wilson(0.0, 20.0, 2.0);
assert_abs_diff_eq!(out.low, 0.0, epsilon = 0.000001);
assert_abs_diff_eq!(out.high, 0.1666666667, epsilon = 0.000001);
}
}
#[test]
fn degenerate() {
let out = wilson(0.0, 0.0, 2.0);
assert_abs_diff_eq!(out.low, 0.0, epsilon = 0.000001);
assert_abs_diff_eq!(out.high, 1.0, epsilon = 0.000001);
}
#[test]
fn degenerate2() {
let out = wilson(0.005, 0.01, 2.0);
assert_abs_diff_eq!(out.low, 0.0006238305611, epsilon = 0.000001);
assert_abs_diff_eq!(out.high, 0.9993761694, epsilon = 0.000001);
}
}