uninum 0.1.1

A robust, ergonomic unified number type for Rust with automatic overflow handling, type promotion, and cross-type consistency.
Documentation
use uninum::{Number, num};

#[test]
fn ref_division_preserves_integer_results() {
    let lhs = Number::from(20u64);
    let rhs = Number::from(5u64);

    let result = &lhs / &rhs;

    assert_eq!(result, Number::from(4u64));
}

#[test]
fn ref_division_promotes_on_inexact_results() {
    let lhs = Number::from(1u64);
    let rhs = Number::from(3u64);

    let result = &lhs / &rhs;
    let expected = num!(1.0 / 3.0);

    assert!(result.approx_eq(&expected, 1e-12, 0.0));

    #[cfg(feature = "decimal")]
    assert!(result.try_get_decimal().is_some());
    #[cfg(not(feature = "decimal"))]
    assert!(result.try_get_f64().is_some());
}

#[test]
fn ref_division_handles_signed_overflow_case() {
    let lhs = Number::from(i64::MIN);
    let rhs = Number::from(-1i64);

    let result = &lhs / &rhs;

    #[cfg(feature = "decimal")]
    {
        let decimal = result.try_get_decimal().expect("expected decimal");
        assert!(decimal.is_sign_positive());
    }
    #[cfg(not(feature = "decimal"))]
    {
        let value = result.try_get_f64().expect("expected f64");
        assert!(value.abs() >= (i64::MAX as f64));
        let expected = Number::from((i64::MAX as f64) + 1.0);
        assert!(
            result.approx_eq(&expected, 1e-6, 0.0),
            "expected approximately {expected:?}, got {result:?}"
        );
    }
}

#[test]
fn ref_remainder_matches_integer_path() {
    let lhs = Number::from(10u64);
    let rhs = Number::from(3u64);

    let result = &lhs % &rhs;

    assert_eq!(result, Number::from(1u64));
}

#[test]
fn ref_remainder_reports_nan_on_zero_divisor() {
    let lhs = Number::from(10u64);
    let rhs = Number::from(0u64);

    let result = &lhs % &rhs;

    assert!(result.is_nan());
}

#[cfg(feature = "decimal")]
#[test]
fn ref_division_decimal_zero_divisor_yields_infinity() {
    use rust_decimal::Decimal;

    let numerator = Number::from(Decimal::new(42, 1));
    let denominator = Number::from(Decimal::ZERO);

    let result = &numerator / &denominator;

    assert!(result.is_infinite());
    assert!(result.is_positive());
}