sciforge 0.0.3

A comprehensive scientific computing library in pure Rust with zero dependencies
Documentation
pub fn gompertz_mortality(a: f64, b: f64, age: f64) -> f64 {
    a * (b * age).exp()
}

pub fn gompertz_survival(a: f64, b: f64, age: f64) -> f64 {
    (-(a / b) * ((b * age).exp() - 1.0)).exp()
}

pub fn weibull_mortality(lambda: f64, k: f64, age: f64) -> f64 {
    lambda * k * (lambda * age).powf(k - 1.0)
}

pub fn weibull_survival(lambda: f64, k: f64, age: f64) -> f64 {
    (-(lambda * age).powf(k)).exp()
}

pub fn gompertz_makeham_mortality(a: f64, b: f64, c: f64, age: f64) -> f64 {
    c + a * (b * age).exp()
}

pub fn mortality_rate_doubling_time(b: f64) -> f64 {
    (2.0_f64).ln() / b
}

pub fn life_expectancy_from_survival(survival: impl Fn(f64) -> f64, max_age: f64, dt: f64) -> f64 {
    let steps = (max_age / dt) as usize;
    let mut integral = 0.0;
    for i in 0..steps {
        let t = i as f64 * dt;
        integral += survival(t) * dt;
    }
    integral
}

pub fn siler_mortality(a1: f64, b1: f64, a2: f64, a3: f64, b3: f64, age: f64) -> f64 {
    a1 * (-b1 * age).exp() + a2 + a3 * (b3 * age).exp()
}

pub fn logistic_mortality_plateau(a: f64, b: f64, c: f64, age: f64) -> f64 {
    a * (b * age).exp() / (1.0 + c * a / b * ((b * age).exp() - 1.0))
}

pub fn demographic_entropy(life_table_lx: &[f64]) -> f64 {
    let e0: f64 = life_table_lx.iter().sum::<f64>();
    if e0 <= 0.0 {
        return 0.0;
    }
    life_table_lx
        .iter()
        .filter(|&&lx| lx > 0.0)
        .map(|&lx| lx * (lx).ln())
        .sum::<f64>()
        / -e0
}

pub fn net_reproduction_rate(survivorship: &[f64], fecundity: &[f64]) -> f64 {
    survivorship
        .iter()
        .zip(fecundity.iter())
        .map(|(&l, &m)| l * m)
        .sum()
}

pub fn generation_time(survivorship: &[f64], fecundity: &[f64]) -> f64 {
    let r0: f64 = survivorship
        .iter()
        .zip(fecundity.iter())
        .map(|(&l, &m)| l * m)
        .sum();
    if r0 <= 0.0 {
        return 0.0;
    }
    let numerator: f64 = survivorship
        .iter()
        .zip(fecundity.iter())
        .enumerate()
        .map(|(x, (&l, &m))| x as f64 * l * m)
        .sum();
    numerator / r0
}

pub fn actuarial_senescence_rate(
    mortality_young: f64,
    mortality_old: f64,
    age_interval: f64,
) -> f64 {
    ((mortality_old / mortality_young).ln()) / age_interval
}

pub fn proportional_hazards(baseline_hazard: f64, covariates: &[f64], coefficients: &[f64]) -> f64 {
    let linear_predictor: f64 = covariates
        .iter()
        .zip(coefficients.iter())
        .map(|(&x, &b)| x * b)
        .sum();
    baseline_hazard * linear_predictor.exp()
}

pub fn biological_age_levine(
    chronological_age: f64,
    albumin: f64,
    creatinine: f64,
    glucose: f64,
    crp_ln: f64,
    lymphocyte_pct: f64,
    mcv: f64,
    rdw: f64,
    alkaline_phosphatase: f64,
    wbc: f64,
) -> f64 {
    -19.907 + 0.0804 * chronological_age - 0.0803 * albumin
        + 0.0095 * creatinine
        + 0.00188 * glucose
        + 0.0954 * crp_ln
        - 0.012 * lymphocyte_pct
        + 0.0268 * mcv
        + 0.3306 * rdw
        + 0.00188 * alkaline_phosphatase
        + 0.0554 * wbc
}

pub fn frailty_index(deficits_present: u32, deficits_measured: u32) -> f64 {
    deficits_present as f64 / deficits_measured.max(1) as f64
}

pub fn disability_free_life_expectancy(survival: &[f64], disability_free: &[f64]) -> f64 {
    survival
        .iter()
        .zip(disability_free.iter())
        .map(|(&s, &d)| s * d)
        .sum()
}