r2rs-stats 0.1.1

Statistics programming for Rust based on R's stats package
Documentation
// "Whatever you do, work at it with all your heart, as working for the Lord,
// not for human masters, since you know that you will receive an inheritance
// from the Lord as a reward. It is the Lord Christ you are serving."
// (Col 3:23-24)

use nalgebra::DMatrix;
use num_traits::Float;
use r2rs_nmath::{distribution::NormalBuilder, traits::Distribution};
use strafe_type::FloatConstraint;

use crate::regression::glm::link::core::Link;

#[derive(Default, Clone, Debug)]
pub struct Probit {}

impl Probit {
    pub fn new() -> Self {
        Self::default()
    }
}

impl Link for Probit {
    fn link_func(&self, mu: &DMatrix<f64>) -> DMatrix<f64> {
        let cauchy = NormalBuilder::new().build();
        let mut ret = mu.clone();
        ret.iter_mut()
            .for_each(|mu| *mu = cauchy.quantile(*mu, true).unwrap());
        ret
    }

    fn link_inverse(&self, eta: &DMatrix<f64>) -> DMatrix<f64> {
        let cauchy = NormalBuilder::new().build();
        let threshold = -cauchy.quantile(f64::epsilon(), true).unwrap();
        let mut ret = eta.clone();
        ret.iter_mut().for_each(|eta| {
            *eta = cauchy
                .probability(eta.max(-threshold).min(threshold), true)
                .unwrap()
        });
        ret
    }

    fn mu_eta(&self, eta: &DMatrix<f64>) -> DMatrix<f64> {
        let cauchy = NormalBuilder::new().build();
        let mut ret = eta.clone();
        ret.iter_mut()
            .for_each(|eta| *eta = cauchy.density(*eta).unwrap().max(f64::epsilon()));
        ret
    }

    fn valid_eta(&self, _eta: &DMatrix<f64>) -> bool {
        true
    }
}