Shared Rust kernels
ported/depreciation_family
All modules · quoted at commit 9e1884369a67 of DnaCalc/DnaCalc. Comments are the source's own.
validate_finite · 7 lines · calc-func/src/ported/depreciation_family.rs on GitHubfn validate_finite(values: &[f64]) -> Result<(), WorksheetErrorCode> {
if values.iter().all(|value| value.is_finite()) {
Ok(())
} else {
Err(WorksheetErrorCode::Num)
}
}
Used by 5 functions.
publish_depreciation · 9 lines · calc-func/src/ported/depreciation_family.rs on GitHubfn publish_depreciation(value: f64) -> Result<f64, WorksheetErrorCode> {
if !value.is_finite() {
Err(WorksheetErrorCode::Num)
} else if value.abs() < f64::MIN_POSITIVE {
Ok(0.0)
} else {
Ok(value)
}
}
Used by 4 functions.
depreciation_integer_power · 13 lines · calc-func/src/ported/depreciation_family.rs on GitHubfn depreciation_integer_power(mut base: f64, mut exponent: u32) -> f64 {
let mut product = 1.0;
while exponent > 0 {
if exponent & 1 != 0 {
product = crate::ported::excel_numeric::excel_x87_mul(product, base);
}
exponent >>= 1;
if exponent > 0 {
base = crate::ported::excel_numeric::excel_x87_mul(base, base);
}
}
product
}
Used by 3 functions.
ddb_period_depreciation · 46 lines · calc-func/src/ported/depreciation_family.rs on GitHubfn ddb_period_depreciation(
cost: f64,
salvage: f64,
life: f64,
period: f64,
factor: f64,
) -> Result<f64, WorksheetErrorCode> {
let rate = crate::ported::excel_numeric::excel_x87_div(factor, life);
// DDB publishes its division stage before the cost product. A subnormal
// rate is zero even if multiplication by cost could make it normal again.
let rate = if rate.abs() < f64::MIN_POSITIVE {
0.0
} else {
rate
};
// The financial power dispatch shares POWER's bounded integer substrate,
// but its count sentinel is u32::MAX rather than the worksheet wrapper's
// wider integer range (W111 large-period discriminator).
let power = if period <= 1.0 {
1.0
} else {
let base = crate::ported::excel_numeric::excel_x87_sub(1.0, rate).max(0.0);
let exponent = period - 1.0;
if exponent.fract() == 0.0 && exponent < u32::MAX as f64 {
// Each accumulator product is rounded through the x87 store. The
// ordinary POWER binary64 body differs on large integer periods.
let value = depreciation_integer_power(base, exponent as u32);
if value.abs() < f64::MIN_POSITIVE {
0.0
} else {
value
}
} else if exponent >= u32::MAX as f64 && base != 0.0 {
crate::ported::excel_numeric::excel_pow_positive(base, exponent)
} else {
crate::ported::power_fn::power_kernel(base, exponent)?
}
};
let book = crate::ported::excel_numeric::excel_x87_mul(cost, power);
let declining = crate::ported::excel_numeric::excel_x87_mul(book, rate);
// Overflow is observable before salvage clipping, including cost<salvage.
if !declining.is_finite() {
return Err(WorksheetErrorCode::Num);
}
publish_depreciation(declining.min(book - salvage).max(0.0))
}
Used by 2 functions.