diff --git a/src/game.rs b/src/game.rs index f766a0c..083d4de 100644 --- a/src/game.rs +++ b/src/game.rs @@ -13,16 +13,16 @@ pub struct Game { impl Game { pub fn new(teams: Vec>, result: Vec, p_draw: f64) -> Self { if !result.is_empty() { - assert!( + debug_assert!( teams.len() == result.len(), "len(result) and (len(teams) != len(result))" ); } - assert!(p_draw >= 0.0 && p_draw < 1.0, "0.0 <= p_draw < 1.0"); + debug_assert!(p_draw >= 0.0 && p_draw < 1.0, "0.0 <= p_draw < 1.0"); if p_draw == 0.0 { - assert!( + debug_assert!( result.iter().collect::>().len() == result.len(), "(p_draw == 0.0) and (len(result) > 0) and (len(set(result)) != len(result))" ); diff --git a/src/gaussian.rs b/src/gaussian.rs index e502b9f..d9e00b8 100644 --- a/src/gaussian.rs +++ b/src/gaussian.rs @@ -9,34 +9,42 @@ pub struct Gaussian { } impl Gaussian { + #[inline] pub const fn new(mu: f64, sigma: f64) -> Self { Gaussian { mu, sigma } } + #[inline] pub fn mu(&self) -> f64 { self.mu } + #[inline] pub fn sigma(&self) -> f64 { self.sigma } + #[inline] pub fn tau(&self) -> f64 { self.mu * self.pi() } + #[inline] pub fn pi(&self) -> f64 { self.sigma.powi(-2) } + #[inline] pub fn forget(&self, gamma: f64, t: f64) -> Self { Self::new(self.mu, (self.sigma().powi(2) + t * gamma.powi(2)).sqrt()) } + #[inline] pub fn delta(&self, m: Gaussian) -> (f64, f64) { ((self.mu() - m.mu()).abs(), (self.sigma() - m.sigma()).abs()) } + #[inline] pub fn exclude(&self, m: Gaussian) -> Self { Self::new( self.mu() - m.mu(), @@ -46,6 +54,7 @@ impl Gaussian { } impl Default for Gaussian { + #[inline] fn default() -> Self { Gaussian { mu: MU, @@ -57,6 +66,7 @@ impl Default for Gaussian { impl ops::Add for Gaussian { type Output = Gaussian; + #[inline] fn add(self, rhs: Gaussian) -> Self::Output { Gaussian { mu: self.mu + rhs.mu, @@ -68,6 +78,7 @@ impl ops::Add for Gaussian { impl ops::Sub for Gaussian { type Output = Gaussian; + #[inline] fn sub(self, rhs: Gaussian) -> Self::Output { Gaussian { mu: self.mu - rhs.mu, @@ -79,6 +90,7 @@ impl ops::Sub for Gaussian { impl ops::Mul for Gaussian { type Output = Gaussian; + #[inline] fn mul(self, rhs: Gaussian) -> Self::Output { let (mu, sigma) = utils::mu_sigma(self.tau() + rhs.tau(), self.pi() + rhs.pi()); @@ -89,6 +101,7 @@ impl ops::Mul for Gaussian { impl ops::Div for Gaussian { type Output = Gaussian; + #[inline] fn div(self, rhs: Gaussian) -> Self::Output { let (mu, sigma) = utils::mu_sigma(self.tau() - rhs.tau(), self.pi() - rhs.pi()); diff --git a/src/utils.rs b/src/utils.rs index ad5b3cd..3dc92c7 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,10 +1,11 @@ -use std::cmp::{Ordering, Reverse}; +use std::cmp::Reverse; use std::f64::consts::{FRAC_1_SQRT_2, FRAC_2_SQRT_PI, SQRT_2}; use crate::Gaussian; const SQRT_TAU: f64 = 2.5066282746310002; +#[inline] fn erfc(x: f64) -> f64 { let z = x.abs(); let t = 1.0 / (1.0 + z / 2.0); @@ -27,6 +28,7 @@ fn erfc(x: f64) -> f64 { } } +#[inline] fn erfc_inv(mut y: f64) -> f64 { if y >= 2.0 { return f64::NEG_INFINITY; @@ -59,10 +61,12 @@ fn erfc_inv(mut y: f64) -> f64 { } } +#[inline] fn ppf(p: f64, mu: f64, sigma: f64) -> f64 { mu - sigma * SQRT_2 * erfc_inv(2.0 * p) } +#[inline] pub(crate) fn mu_sigma(tau: f64, pi: f64) -> (f64, f64) { if pi > 0.0 { return (tau / pi, (1.0 / pi).sqrt()); @@ -75,12 +79,14 @@ pub(crate) fn mu_sigma(tau: f64, pi: f64) -> (f64, f64) { (0.0, f64::INFINITY) } +#[inline] pub(crate) fn cdf(x: f64, mu: f64, sigma: f64) -> f64 { let z = -(x - mu) / (sigma * SQRT_2); 0.5 * erfc(z) } +#[inline] fn pdf(x: f64, mu: f64, sigma: f64) -> f64 { let normalizer = (SQRT_TAU * sigma).powi(-1); let functional = (-((x - mu).powi(2)) / (2.0 * sigma.powi(2))).exp(); @@ -93,6 +99,7 @@ def ppf(p, mu, sigma): return mu - sigma * sqrt2 * erfcinv(2 * p) */ +#[inline] fn v_w(mu: f64, sigma: f64, margin: f64, tie: bool) -> (f64, f64) { if !tie { let alpha = (margin - mu) / sigma; @@ -115,6 +122,7 @@ fn v_w(mu: f64, sigma: f64, margin: f64, tie: bool) -> (f64, f64) { } } +#[inline] pub(crate) fn trunc(mu: f64, sigma: f64, margin: f64, tie: bool) -> (f64, f64) { let (v, w) = v_w(mu, sigma, margin, tie); @@ -124,12 +132,14 @@ pub(crate) fn trunc(mu: f64, sigma: f64, margin: f64, tie: bool) -> (f64, f64) { (mu_trunc, sigma_trunc) } +#[inline] pub(crate) fn approx(n: Gaussian, margin: f64, tie: bool) -> Gaussian { let (mu, sigma) = trunc(n.mu(), n.sigma(), margin, tie); Gaussian::new(mu, sigma) } +#[inline] pub(crate) fn compute_margin(p_draw: f64, sd: f64) -> f64 { ppf(0.5 - p_draw / 2.0, 0.0, sd).abs() }