uninum 0.1.1

A robust, ergonomic unified number type for Rust with automatic overflow handling, type promotion, and cross-type consistency.
Documentation
//! Ensures primitive interop macro branches remain exercised.

use uninum::{Number, num};

#[test]
fn arithmetic_with_mixed_borrowing_patterns() {
    let number = Number::from(10u64);
    let primitive: u64 = 5;
    let number_ref = &number;
    let primitive_ref = &primitive;
    let twenty = Number::from(20u64);
    let twenty_ref = &twenty;
    let ten = Number::from(10u64);
    let ten_ref = &ten;

    assert_eq!(number.clone() + primitive, Number::from(15u64));
    assert_eq!(number.clone() + primitive_ref, Number::from(15u64));
    assert_eq!(number_ref + primitive, Number::from(15u64));
    assert_eq!(number_ref + primitive_ref, Number::from(15u64));

    assert_eq!(primitive + number.clone(), Number::from(15u64));
    assert_eq!(primitive + number_ref, Number::from(15u64));
    assert_eq!(primitive_ref + number.clone(), Number::from(15u64));
    assert_eq!(primitive_ref + number_ref, Number::from(15u64));

    assert_eq!(twenty.clone() - primitive, Number::from(15u64));
    assert_eq!(twenty.clone() - primitive_ref, Number::from(15u64));
    assert_eq!(twenty_ref - primitive, Number::from(15u64));
    assert_eq!(twenty_ref - primitive_ref, Number::from(15u64));

    assert_eq!(primitive - number.clone(), Number::from(-5i64));
    assert_eq!(primitive - number_ref, Number::from(-5i64));
    assert_eq!(primitive_ref - number.clone(), Number::from(-5i64));
    assert_eq!(primitive_ref - ten_ref, Number::from(-5i64));
}

#[test]
fn multiplication_with_mixed_borrowing_patterns() {
    let number = Number::from(3i64);
    let primitive: i32 = 4;
    let number_ref = &number;
    let primitive_ref = &primitive;

    assert_eq!(number.clone() * primitive, Number::from(12i64));
    assert_eq!(number.clone() * primitive_ref, Number::from(12i64));
    assert_eq!(number_ref * primitive, Number::from(12i64));
    assert_eq!(number_ref * primitive_ref, Number::from(12i64));

    assert_eq!(primitive * number.clone(), Number::from(12i64));
    assert_eq!(primitive * number_ref, Number::from(12i64));
    assert_eq!(primitive_ref * number.clone(), Number::from(12i64));
    assert_eq!(primitive_ref * number_ref, Number::from(12i64));
}

#[test]
fn division_with_mixed_borrowing_patterns() {
    let number = Number::from(20i64);
    let primitive: i64 = 5;
    let float_number = Number::from(10.0f64);
    let float_primitive = 2.5f64;
    let number_ref = &number;
    let primitive_ref = &primitive;
    let float_number_ref = &float_number;
    let float_primitive_ref = &float_primitive;

    assert_eq!(number.clone() / primitive, Number::from(4i64));
    assert_eq!(number.clone() / primitive_ref, Number::from(4i64));
    assert_eq!(number_ref / primitive, Number::from(4i64));
    assert_eq!(number_ref / primitive_ref, Number::from(4i64));

    for quotient in [
        primitive / number.clone(),
        primitive / number_ref,
        primitive_ref / number.clone(),
        primitive_ref / number_ref,
    ] {
        #[cfg(feature = "decimal")]
        if let Some(decimal) = quotient.try_get_decimal() {
            assert_eq!(decimal.to_string(), "0.25");
            continue;
        }

        if let Some(f64_value) = quotient.try_get_f64() {
            assert!((f64_value - 0.25).abs() < 1e-12);
        } else {
            panic!("expected quotient to be representable as Decimal or F64");
        }
    }

    let float_expected = Number::from(4.0);
    assert_eq!(float_number.clone() / float_primitive, float_expected);
    assert_eq!(float_number.clone() / float_primitive_ref, float_expected);
    assert_eq!(float_number_ref / float_primitive, float_expected);
    assert_eq!(float_number_ref / float_primitive_ref, float_expected);

    let reciprocal = float_primitive / float_number.clone();
    #[cfg(feature = "decimal")]
    assert!(reciprocal.try_get_decimal().is_some() || reciprocal.try_get_f64().is_some());
    #[cfg(not(feature = "decimal"))]
    assert!(reciprocal.try_get_f64().is_some());

    let reciprocal_ref = float_primitive_ref / float_number_ref;
    #[cfg(feature = "decimal")]
    assert!(reciprocal_ref.try_get_decimal().is_some() || reciprocal_ref.try_get_f64().is_some());
    #[cfg(not(feature = "decimal"))]
    assert!(reciprocal_ref.try_get_f64().is_some());
}

#[test]
fn remainder_with_mixed_borrowing_patterns() {
    let number = Number::from(17i64);
    let primitive: i64 = 5;
    let number_ref = &number;
    let primitive_ref = &primitive;

    assert_eq!(number.clone() % primitive, Number::from(2i64));
    assert_eq!(number.clone() % primitive_ref, Number::from(2i64));
    assert_eq!(number_ref % primitive, Number::from(2i64));
    assert_eq!(number_ref % primitive_ref, Number::from(2i64));

    assert_eq!(primitive % number.clone(), Number::from(5i64));
    assert_eq!(primitive % number_ref, Number::from(5i64));
    assert_eq!(primitive_ref % number.clone(), Number::from(5i64));
    assert_eq!(primitive_ref % number_ref, Number::from(5i64));
}

#[test]
fn comparison_between_numbers_and_primitives() {
    let number = Number::from(42u64);
    let primitive: u64 = 42;
    let number_ref = &number;

    assert_eq!(number, primitive);
    assert_eq!(primitive, number);
    assert_eq!(number_ref, primitive);
    assert_eq!(primitive, number_ref);

    let other = Number::from(100u64);
    let other_ref = &other;
    assert!(number < 100u64);
    assert!(primitive < other);
    assert!(number_ref < 100u64);
    assert!(primitive < other_ref);
}

#[test]
fn float_operations_cover_reference_paths() {
    let number = num!(2.5);
    let primitive = 2.0f64;
    let number_ref = &number;
    let primitive_ref = &primitive;

    assert_eq!(number.clone() * primitive, Number::from(5.0));
    assert_eq!(number_ref * primitive, Number::from(5.0));
    assert_eq!(primitive * number.clone(), Number::from(5.0));
    assert_eq!(primitive * number_ref, Number::from(5.0));
    assert_eq!(primitive_ref * number.clone(), Number::from(5.0));
    assert_eq!(primitive_ref * number_ref, Number::from(5.0));
}