use self::helpers::is_table_layout_approved;
use super::*;
pub fn tpx(config: &MortTableConfig, x: f64, t: f64, entry_age: Option<u32>) -> PolarsResult<f64> {
if !is_table_layout_approved(config) {
return Err(PolarsError::ComputeError(
"Mortality table XML layout is not suitable for calculations".into(),
));
}
if x.fract() == 0.0 && t.fract() == 0.0 {
return whole::tpx(config, t as u32, x as u32, entry_age);
}
let x_whole = x.floor() as u32; let x_frac = x.fract(); let time_to_next_age = 1.0 - x_frac;
let qx = get_value(config, x_whole, "qx").unwrap_or(0.0);
if t <= time_to_next_age {
let survival_rate = match config.assumption {
Some(AssumptionEnum::UDD) => 1.0 - t * qx / (1.0 - x_frac * qx),
Some(AssumptionEnum::CFM) => (1.0 - qx).powf(t),
Some(AssumptionEnum::HPB) => 1.0 - t * qx / (1.0 + x_frac * qx),
_ => {
return Err(PolarsError::ComputeError(
"Unsupported assumption for fractional age".into(),
));
}
};
Ok(survival_rate)
} else {
let survival_to_next_age = tpx(config, time_to_next_age, x, entry_age)?;
let remaining_time = t - time_to_next_age;
let survival_after = tpx(config, remaining_time, (x_whole + 1) as f64, entry_age)?;
let result = survival_to_next_age * survival_after;
Ok(result)
}
}
pub fn tqx(config: &MortTableConfig, x: f64, t: f64, entry_age: Option<u32>) -> PolarsResult<f64> {
let result = 1.0 - tpx(config, x, t, entry_age)?;
Ok(result)
}
#[cfg(test)]
mod tests {
}