sciforge 0.0.3

A comprehensive scientific computing library in pure Rust with zero dependencies
Documentation
pub fn telomere_attrition(initial_length: f64, loss_per_division: f64, divisions: usize) -> f64 {
    (initial_length - loss_per_division * divisions as f64).max(0.0)
}

pub fn telomerase_elongation(current_length: f64, rate: f64, telomerase_activity: f64) -> f64 {
    current_length + rate * telomerase_activity
}

pub fn replicative_limit(initial_length: f64, loss_per_division: f64, critical_length: f64) -> f64 {
    if loss_per_division <= 0.0 {
        return f64::INFINITY;
    }
    ((initial_length - critical_length) / loss_per_division)
        .max(0.0)
        .floor()
}

pub fn telomere_length_distribution(mean: f64, std_dev: f64, n_chromosomes: usize) -> Vec<f64> {
    let mut lengths = Vec::with_capacity(n_chromosomes);
    for i in 0..n_chromosomes {
        let x = (i as f64 / n_chromosomes as f64 - 0.5) * 2.0;
        lengths.push((mean + std_dev * x).max(0.0));
    }
    lengths
}

pub fn critical_shortening_probability(mean_length: f64, std_dev: f64, critical: f64) -> f64 {
    if std_dev <= 0.0 {
        return if mean_length <= critical { 1.0 } else { 0.0 };
    }
    let z = (critical - mean_length) / std_dev;
    0.5 * (1.0 + erf_approx(z / std::f64::consts::SQRT_2))
}

fn erf_approx(x: f64) -> f64 {
    let a = 0.3275911;
    let a1 = 0.254829592;
    let a2 = -0.284496736;
    let a3 = 1.421413741;
    let a4 = -1.453152027;
    let a5 = 1.061405429;
    let sign = if x < 0.0 { -1.0 } else { 1.0 };
    let x = x.abs();
    let t = 1.0 / (1.0 + a * x);
    let y = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * (-x * x).exp();
    sign * y
}

pub fn shelterin_protection(telomere_length: f64, shelterin_kd: f64) -> f64 {
    telomere_length / (shelterin_kd + telomere_length)
}

pub fn end_replication_problem(lagging_strand_loss: f64, divisions: usize) -> f64 {
    lagging_strand_loss * divisions as f64
}

pub fn alt_pathway_elongation(
    recombination_rate: f64,
    donor_length: f64,
    recipient_length: f64,
) -> f64 {
    recipient_length + recombination_rate * (donor_length - recipient_length).max(0.0)
}

pub fn telomere_age_regression(age: f64, birth_length: f64, annual_loss: f64) -> f64 {
    (birth_length - annual_loss * age).max(0.0)
}