Shared Rust kernels

ported/amor_depreciation_family

All modules · quoted at commit 9e1884369a67 of DnaCalc/DnaCalc. Comments are the source's own.

max_excel_serial · 3 lines · calc-func/src/ported/amor_depreciation_family.rs on GitHub
fn max_excel_serial() -> i64 {
    excel_serial_from_ymd(WorkbookDateSystem::System1900, 9999, 12, 31).unwrap() as i64
}

Used by 2 functions.

parse_basis · 12 lines · calc-func/src/ported/amor_depreciation_family.rs on GitHub
fn parse_basis(value: f64) -> Result<AmorBasis, AmorDepreciationEvalError> {
    if !value.is_finite() {
        return Err(AmorDepreciationEvalError::Domain(WorksheetErrorCode::Num));
    }
    match value.trunc() as i64 {
        0 => Ok(AmorBasis::Us30_360),
        1 => Ok(AmorBasis::ActualActual),
        3 => Ok(AmorBasis::Actual365),
        4 => Ok(AmorBasis::European30_360),
        _ => Err(AmorDepreciationEvalError::Domain(WorksheetErrorCode::Num)),
    }
}

Used by 2 functions.

parse_date_serial · 12 lines · calc-func/src/ported/amor_depreciation_family.rs on GitHub
fn parse_date_serial(value: f64) -> Result<i64, AmorDepreciationEvalError> {
    if !value.is_finite() {
        return Err(AmorDepreciationEvalError::Domain(WorksheetErrorCode::Value));
    }
    let serial = value.trunc() as i64;
    if serial < 1 || serial > max_excel_serial() {
        return Err(AmorDepreciationEvalError::Domain(WorksheetErrorCode::Value));
    }
    ymd_from_excel_serial(WorkbookDateSystem::System1900, serial as f64)
        .ok_or(AmorDepreciationEvalError::Domain(WorksheetErrorCode::Value))?;
    Ok(serial)
}

Used by 2 functions.

days_in_year · 7 lines · calc-func/src/ported/amor_depreciation_family.rs on GitHub
fn days_in_year(year: i64) -> f64 {
    if (year % 4 == 0 && year % 100 != 0) || year % 400 == 0 {
        366.0
    } else {
        365.0
    }
}

Used by 2 functions.

days_in_month · 14 lines · calc-func/src/ported/amor_depreciation_family.rs on GitHub
fn days_in_month(year: i64, month: i64) -> i64 {
    match month {
        1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
        4 | 6 | 9 | 11 => 30,
        2 => {
            if days_in_year(year) == 366.0 {
                29
            } else {
                28
            }
        }
        _ => 30,
    }
}

Used by 2 functions.

actual_days · 3 lines · calc-func/src/ported/amor_depreciation_family.rs on GitHub
fn actual_days(start: i64, end: i64) -> f64 {
    (end - start) as f64
}

Used by 2 functions.

days360_us · 21 lines · calc-func/src/ported/amor_depreciation_family.rs on GitHub
fn days360_us(start: i64, end: i64) -> Result<f64, AmorDepreciationEvalError> {
    let (sy, sm, mut sd) = ymd_from_excel_serial(WorkbookDateSystem::System1900, start as f64)
        .ok_or(AmorDepreciationEvalError::Domain(WorksheetErrorCode::Value))?;
    let (ey, em, mut ed) = ymd_from_excel_serial(WorkbookDateSystem::System1900, end as f64)
        .ok_or(AmorDepreciationEvalError::Domain(WorksheetErrorCode::Value))?;

    let start_last_feb = sm == 2 && sd == days_in_month(sy, sm);
    let end_last_feb = em == 2 && ed == days_in_month(ey, em);

    if sd == 31 || start_last_feb {
        sd = 30;
    }
    if ed == 31 && sd >= 30 {
        ed = 30;
    }
    if end_last_feb && start_last_feb {
        ed = 30;
    }

    Ok(((ey - sy) * 360 + (em - sm) * 30 + (ed - sd)) as f64)
}

Used by 2 functions.

days360_eu · 13 lines · calc-func/src/ported/amor_depreciation_family.rs on GitHub
fn days360_eu(start: i64, end: i64) -> Result<f64, AmorDepreciationEvalError> {
    let (sy, sm, mut sd) = ymd_from_excel_serial(WorkbookDateSystem::System1900, start as f64)
        .ok_or(AmorDepreciationEvalError::Domain(WorksheetErrorCode::Value))?;
    let (ey, em, mut ed) = ymd_from_excel_serial(WorkbookDateSystem::System1900, end as f64)
        .ok_or(AmorDepreciationEvalError::Domain(WorksheetErrorCode::Value))?;
    if sd == 31 {
        sd = 30;
    }
    if ed == 31 {
        ed = 30;
    }
    Ok(((ey - sy) * 360 + (em - sm) * 30 + (ed - sd)) as f64)
}

Used by 2 functions.

actual_actual_positive · 12 lines · calc-func/src/ported/amor_depreciation_family.rs on GitHub
/// The actual/actual fraction of the first period: the actual days divided by the days of the
/// purchase year, also when the period ends in a later year (dc-j9k: 40 of 40 AMORLINC and 40 of
/// 40 AMORDEGRC readings in the catalogue oracle's sheet dcj9k_closed_form; the year-split sum
/// this replaces missed every reading that crosses into a year of another length).
fn actual_actual_positive(start: i64, end: i64) -> Result<f64, AmorDepreciationEvalError> {
    if end <= start {
        return Ok(0.0);
    }
    let (sy, _, _) = ymd_from_excel_serial(WorkbookDateSystem::System1900, start as f64)
        .ok_or(AmorDepreciationEvalError::Domain(WorksheetErrorCode::Value))?;
    Ok(actual_days(start, end) / days_in_year(sy))
}

Used by 2 functions.

first_period_fraction · 18 lines · calc-func/src/ported/amor_depreciation_family.rs on GitHub
fn first_period_fraction(
    purchase: i64,
    first_period: i64,
    basis: AmorBasis,
) -> Result<f64, AmorDepreciationEvalError> {
    if purchase > first_period {
        return Err(AmorDepreciationEvalError::Domain(WorksheetErrorCode::Num));
    }
    if purchase == first_period {
        return Ok(1.0);
    }
    match basis {
        AmorBasis::Us30_360 => Ok(days360_us(purchase, first_period)? / 360.0),
        AmorBasis::ActualActual => actual_actual_positive(purchase, first_period),
        AmorBasis::Actual365 => Ok(actual_days(purchase, first_period) / 365.0),
        AmorBasis::European30_360 => Ok(days360_eu(purchase, first_period)? / 360.0),
    }
}

Used by 2 functions.

map_amor_depreciation_error_to_ws · 6 lines · calc-func/src/ported/amor_depreciation_family.rs on GitHub
pub fn map_amor_depreciation_error_to_ws(error: &AmorDepreciationEvalError) -> WorksheetErrorCode {
    match error {
        AmorDepreciationEvalError::ArityMismatch { .. } => WorksheetErrorCode::Value,
        AmorDepreciationEvalError::Domain(code) => *code,
    }
}

Used by 2 functions.