unitforge 0.4.1

A library for unit and quantity consistent computations in Rust
Documentation
use crate::MAX_ABS_QUANTITY_POWER;

fn clamp_power(power: i64) -> i32 {
    power.clamp(
        -i64::from(MAX_ABS_QUANTITY_POWER),
        i64::from(MAX_ABS_QUANTITY_POWER),
    ) as i32
}

pub fn saturating_power_add(lhs: i32, rhs: i32) -> i32 {
    clamp_power(i64::from(lhs) + i64::from(rhs))
}

pub fn saturating_power_sub(lhs: i32, rhs: i32) -> i32 {
    clamp_power(i64::from(lhs) - i64::from(rhs))
}

pub fn average_power(lhs: i32, rhs: i32) -> i32 {
    let average = (i64::from(lhs) + i64::from(rhs)) / 2;
    clamp_power(average)
}

pub fn canonicalize_quantity_parts(multiplier: f64, power: i32) -> (f64, i32) {
    if multiplier == 0.0 {
        return (0.0, 0);
    }

    if multiplier.is_nan() {
        return (f64::NAN, 0);
    }

    if multiplier.is_infinite() {
        return (multiplier, 0);
    }

    let power_on_multiplier = multiplier.abs().log10().round() as i32;
    let normalized_multiplier = multiplier / 10_f64.powi(power_on_multiplier);
    let normalized_power = saturating_power_add(power, power_on_multiplier);

    if normalized_power <= -MAX_ABS_QUANTITY_POWER {
        (0.0, 0)
    } else if normalized_power >= MAX_ABS_QUANTITY_POWER {
        if normalized_multiplier.is_sign_negative() {
            (f64::NEG_INFINITY, 0)
        } else {
            (f64::INFINITY, 0)
        }
    } else {
        (normalized_multiplier, normalized_power)
    }
}

pub fn pow10_delta(lhs: i32, rhs: i32) -> f64 {
    10_f64.powi(saturating_power_sub(lhs, rhs))
}