#![allow(non_snake_case)]
use crate::RSLifeResult;
use crate::int_rate_convert::{eff_i_to_nom_d, eff_i_to_nom_i};
use bon::builder;
#[builder]
pub fn aan(
i: f64,
n: u32,
#[builder(default = 0)] t: u32,
#[builder(default = 1)] m: u32,
) -> RSLifeResult<f64> {
if n == 0 {
return Ok(0.0);
}
let v = 1.0 / (1.0 + i);
let nom_d = eff_i_to_nom_d(i, m);
let n = n as f64;
let t = t as f64;
let result = v.powf(t) * (1.0 - v.powf(n)) / nom_d;
Ok(result)
}
#[builder]
pub fn an(
i: f64,
n: u32,
#[builder(default = 0)] t: u32,
#[builder(default = 1)] m: u32,
) -> RSLifeResult<f64> {
let nom_i = eff_i_to_nom_i(i, m);
let nom_d = eff_i_to_nom_d(i, m);
let due = aan().i(i).n(n).t(t).m(m).call()?;
let result = due * nom_d / nom_i;
Ok(result)
}
#[builder]
pub fn Iaan(
i: f64,
n: u32,
#[builder(default = 0)] t: u32,
#[builder(default = 1)] m: u32,
) -> RSLifeResult<f64> {
if n == 0 {
return Ok(0.0);
}
let v = 1.0 / (1.0 + i);
let nom_d = eff_i_to_nom_d(i, m);
let aan = aan().i(i).n(n).t(t).call()?;
let n = n as f64;
let t = t as f64;
let result = v.powf(t) * (aan - n * v.powf(n)) / nom_d;
Ok(result)
}
#[builder]
pub fn Ian(
i: f64,
n: u32,
#[builder(default = 0)] t: u32,
#[builder(default = 1)] m: u32,
) -> RSLifeResult<f64> {
let nom_i = eff_i_to_nom_i(i, m);
let nom_d = eff_i_to_nom_d(i, m);
let due = Iaan().i(i).n(n).t(t).m(m).call()?;
let result = due * nom_d / nom_i;
Ok(result)
}
#[builder]
pub fn Dan(
i: f64,
n: u32,
#[builder(default = 0)] t: u32,
#[builder(default = 1)] m: u32,
) -> RSLifeResult<f64> {
if n == 0 {
return Ok(0.0);
}
let v = 1.0 / (1.0 + i);
let nom_i = eff_i_to_nom_i(i, m);
let an = an().i(i).n(n).t(t).call()?;
let n = n as f64;
let t = t as f64;
let result = v.powf(t) * (n - an) / nom_i;
Ok(result)
}
#[builder]
pub fn Daan(
i: f64,
n: u32,
#[builder(default = 0)] t: u32,
#[builder(default = 1)] m: u32,
) -> RSLifeResult<f64> {
let nom_i = eff_i_to_nom_i(i, m);
let nom_d = eff_i_to_nom_d(i, m);
let immediate = Dan().i(i).n(n).t(t).m(m).call()?;
let result = immediate * nom_i / nom_d;
Ok(result)
}
#[builder]
pub fn ssn(
i: f64,
n: u32,
#[builder(default = 0)] t: u32,
#[builder(default = 1)] m: u32,
) -> RSLifeResult<f64> {
let annuity = aan().i(i).n(n).t(t).m(m).call()?;
let factor = (1.0 + i).powf(n as f64);
Ok(annuity * factor)
}
#[builder]
pub fn sn(
i: f64,
n: u32,
#[builder(default = 0)] t: u32,
#[builder(default = 1)] m: u32,
) -> RSLifeResult<f64> {
let annuity = an().i(i).n(n).t(t).m(m).call()?;
let factor = (1.0 + i).powf(n as f64);
Ok(annuity * factor)
}
#[builder]
pub fn Issn(
i: f64,
n: u32,
#[builder(default = 0)] t: u32,
#[builder(default = 1)] m: u32,
) -> RSLifeResult<f64> {
let annuity = Iaan().i(i).n(n).t(t).m(m).call()?;
let factor = (1.0 + i).powf(n as f64);
Ok(annuity * factor)
}
#[builder]
pub fn Isn(
i: f64,
n: u32,
#[builder(default = 0)] t: u32,
#[builder(default = 1)] m: u32,
) -> RSLifeResult<f64> {
let annuity = Ian().i(i).n(n).t(t).m(m).call()?;
let factor = (1.0 + i).powf(n as f64);
Ok(annuity * factor)
}
#[builder]
pub fn Dssn(
i: f64,
n: u32,
#[builder(default = 0)] t: u32,
#[builder(default = 1)] m: u32,
) -> RSLifeResult<f64> {
let annuity = Daan().i(i).n(n).t(t).m(m).call()?;
let factor = (1.0 + i).powf(n as f64);
Ok(annuity * factor)
}
#[builder]
pub fn Dsn(
i: f64,
n: u32,
#[builder(default = 0)] t: u32,
#[builder(default = 1)] m: u32,
) -> RSLifeResult<f64> {
let annuity = Dan().i(i).n(n).t(t).m(m).call()?;
let factor = (1.0 + i).powf(n as f64);
Ok(annuity * factor)
}
#[cfg(test)]
mod tests {
use super::*;
use approx::assert_abs_diff_eq;
#[test]
fn test_fn_an_01() {
let rates = [0.005, 0.01, 0.015, 0.02, 0.025];
let terms = [1, 20, 41, 80, 100];
let expected = [0.9950, 18.0456, 30.4590, 39.7445, 36.6141];
for (i, (rate, term)) in rates.iter().zip(terms.iter()).enumerate() {
let ans = an().i(*rate).n(*term).call().unwrap();
let exp = expected[i];
assert_abs_diff_eq!(ans, exp, epsilon = 1e-4);
}
}
#[test]
fn test_fn_Ian_01() {
let rates = [0.03, 0.04, 0.05, 0.06, 0.07];
let terms = [1, 23, 48, 70, 100];
let expected = [0.9709, 152.9852, 287.3239, 269.7117, 216.4693];
for (i, (rate, term)) in rates.iter().zip(terms.iter()).enumerate() {
let ans = Ian().i(*rate).n(*term).call().unwrap();
let exp = expected[i];
assert_abs_diff_eq!(ans, exp, epsilon = 1e-4);
}
}
#[test]
fn test_fn_Dan_01() {
let rates = [0.08, 0.09, 0.1, 0.12, 0.15];
let terms = [1, 34, 70, 100, 50];
let expected = [0.9259, 260.9129, 600.1266, 763.8897, 288.9299];
for (i, (rate, term)) in rates.iter().zip(terms.iter()).enumerate() {
let ans = Dan().i(*rate).n(*term).call().unwrap();
let exp = expected[i];
assert_abs_diff_eq!(ans, exp, epsilon = 1e-4);
}
}
}