use uninum::{Number, num};
#[test]
fn test_display_formatting() {
assert_eq!(Number::from(42u64).to_string(), "42");
assert_eq!(Number::from(-42i64).to_string(), "-42");
assert_eq!(Number::from(1234567890u64).to_string(), "1234567890");
assert_eq!(num!(3.15159).to_string(), "3.15159");
assert_eq!(num!(f64::INFINITY).to_string(), "inf");
assert_eq!(num!(f64::NEG_INFINITY).to_string(), "-inf");
assert_eq!(num!(f64::NAN).to_string(), "NaN");
#[cfg(feature = "decimal")]
{
use rust_decimal::Decimal;
let dec = Number::from(Decimal::new(31415, 4));
assert_eq!(dec.to_string(), "3.1415");
}
}
#[test]
fn test_display_edge_cases() {
assert_eq!(
Number::from(18446744073709551615u64).to_string(),
"18446744073709551615"
);
assert_eq!(
Number::from(-9223372036854775808i64).to_string(),
"-9223372036854775808"
);
assert!(num!(1.0 / 3.0).to_string().contains("0.3333"));
assert_eq!(num!(1e-10).to_string(), "0.0000000001");
assert!(num!(1e-300).to_string().starts_with("0."));
assert!(num!(1e100).to_string().starts_with("1000"));
assert!(num!(1e308).to_string().starts_with("1000"));
}
#[test]
fn test_roundtrip_conversions_comprehensive() {
let test_cases = vec![
"0",
"1",
"-1",
"42",
"-42",
"127",
"-128",
"255",
"256",
"-129",
"32767",
"-32768",
"65535",
"65536",
"-32769",
"2147483647",
"-2147483648",
"4294967295",
"4294967296",
"9223372036854775807",
"-9223372036854775808",
"0.0",
"1.0",
"-1.0",
"3.16",
"-3.16",
"2.72",
"1.23456789",
"9876543210.123456789",
"1e10",
"1.5e-10",
"3.16e2",
"-2.5e-3",
"inf",
"-inf",
"NaN",
];
for input in test_cases {
let num = Number::try_from(input).unwrap();
let output = num.to_string();
let reparsed = Number::try_from(output.as_str()).unwrap();
match (&num, &reparsed) {
(n1, n2) if n1.is_nan() && n2.is_nan() => {
}
_ => {
assert_eq!(
num, reparsed,
"Roundtrip failed for input '{input}': {num} -> {output} -> {reparsed}"
);
}
}
}
let typed_cases = vec!["42u64", "42u64", "-42i64", "-42i64", "3.16f64"];
for input in typed_cases {
assert!(
Number::try_from(input).is_err(),
"Typed suffix should be rejected: '{input}'"
);
}
}
#[test]
#[cfg(feature = "decimal")]
fn test_decimal_display_formatting() {
use rust_decimal::Decimal;
let cases = vec![
(Decimal::new(0, 0), "0"),
(Decimal::new(42, 0), "42"),
(Decimal::new(315159, 5), "3.15159"),
(Decimal::new(-27123, 4), "-2.7123"),
(Decimal::new(1000000, 3), "1000.000"),
(Decimal::new(1, 10), "0.0000000001"),
];
for (decimal, expected) in cases {
let number = Number::from(decimal);
assert_eq!(number.to_string(), expected);
}
}
#[test]
fn test_zero_display() {
assert_eq!(Number::from(0u64).to_string(), "0");
assert_eq!(Number::from(0i64).to_string(), "0");
assert_eq!(Number::from(0u64).to_string(), "0");
assert_eq!(Number::from(0i64).to_string(), "0");
#[cfg(feature = "decimal")]
assert_eq!(num!(0.0).to_string(), "0.0");
#[cfg(not(feature = "decimal"))]
assert_eq!(num!(0.0).to_string(), "0");
assert_eq!(num!(-0.0).to_string(), "-0");
#[cfg(feature = "decimal")]
{
use rust_decimal::Decimal;
assert_eq!(Number::from(Decimal::ZERO).to_string(), "0");
assert_eq!(Number::from(-Decimal::ZERO).to_string(), "-0");
}
}
#[test]
fn test_float64_direct_instantiation() {
let f = Number::from(42.0f64);
assert_eq!(f.try_get_f64().unwrap(), 42.0);
let f_nan = Number::from(f64::NAN);
assert!(f_nan.try_get_f64().unwrap().is_nan());
let f_inf = Number::from(f64::INFINITY);
assert!(f_inf.try_get_f64().unwrap().is_infinite());
assert!(f_inf.try_get_f64().unwrap() > 0.0);
let f_neg_inf = Number::from(f64::NEG_INFINITY);
assert!(f_neg_inf.try_get_f64().unwrap().is_infinite());
assert!(f_neg_inf.try_get_f64().unwrap() < 0.0);
}
#[test]
fn test_float64_deref_trait() {
let f = Number::from(3.15159f64);
let f_val = f.try_get_f64().unwrap();
assert_eq!(f_val.floor(), 3.0);
assert_eq!(f_val.ceil(), 4.0);
assert_eq!(f_val.round(), 3.0);
assert!(f_val.is_finite());
assert!(!f_val.is_infinite());
assert!(!f_val.is_nan());
let f_nan = Number::from(f64::NAN);
assert!(f_nan.try_get_f64().unwrap().is_nan());
let f_inf = Number::from(f64::INFINITY);
assert!(f_inf.try_get_f64().unwrap().is_infinite());
assert!(!f_inf.try_get_f64().unwrap().is_finite());
let f1_val = Number::from(2.0f64).try_get_f64().unwrap();
let f2_val = Number::from(3.0f64).try_get_f64().unwrap();
assert_eq!(f1_val.powf(f2_val), 8.0);
assert_eq!(f1_val.sqrt(), std::f64::consts::SQRT_2);
}
#[test]
fn test_float64_display_trait() {
let f = num!(3.15159);
assert_eq!(format!("{f}"), "3.15159");
let f_zero = num!(0.0);
#[cfg(feature = "decimal")]
assert_eq!(format!("{f_zero}"), "0.0");
#[cfg(not(feature = "decimal"))]
assert_eq!(format!("{f_zero}"), "0");
let f_neg_zero = num!(-0.0);
assert_eq!(format!("{f_neg_zero}"), "-0");
let f_inf = num!(f64::INFINITY);
assert_eq!(format!("{f_inf}"), "inf");
let f_neg_inf = num!(f64::NEG_INFINITY);
assert_eq!(format!("{f_neg_inf}"), "-inf");
let f_nan = num!(f64::NAN);
assert_eq!(format!("{f_nan}"), "NaN");
let f_small = num!(0.000001);
assert_eq!(format!("{f_small}"), "0.000001");
let f_large = num!(1000000.0);
#[cfg(feature = "decimal")]
assert_eq!(format!("{f_large}"), "1000000.0");
#[cfg(not(feature = "decimal"))]
assert_eq!(format!("{f_large}"), "1000000");
let f_scientific = num!(1e20);
assert_eq!(format!("{f_scientific}"), "100000000000000000000");
}
#[test]
fn test_float64_default_trait() {
let f_default = Number::from(0.0f64);
assert_eq!(f_default.try_get_f64().unwrap(), 0.0);
assert!(!f_default.try_get_f64().unwrap().is_nan());
assert!(f_default.try_get_f64().unwrap().is_finite());
assert_eq!(f_default, Number::from(0.0f64));
}
#[test]
fn test_float64_from_into_traits() {
let f_from = Number::from(42.5);
assert_eq!(f_from.try_get_f64().unwrap(), 42.5);
let f_from_nan = Number::from(f64::NAN);
assert!(f_from_nan.try_get_f64().unwrap().is_nan());
let f_from_inf = Number::from(f64::INFINITY);
assert!(f_from_inf.try_get_f64().unwrap().is_infinite());
let f = Number::from(3.15159f64);
let f64_from = f.try_get_f64().unwrap();
assert_eq!(f64_from, 3.15159);
let f_nan = Number::from(f64::NAN);
let f64_from_nan = f_nan.try_get_f64().unwrap();
assert!(f64_from_nan.is_nan());
let f_inf = Number::from(f64::INFINITY);
let f64_from_inf = f_inf.try_get_f64().unwrap();
assert!(f64_from_inf.is_infinite());
}
#[test]
fn test_float64_special_values_edge_cases() {
let subnormal = Number::from(f64::MIN_POSITIVE / 2.0);
let subnormal_val = subnormal.try_get_f64().unwrap();
assert!(subnormal_val > 0.0);
assert!(subnormal_val < f64::MIN_POSITIVE);
let max_finite = Number::from(f64::MAX);
let max_val = max_finite.try_get_f64().unwrap();
assert!(max_val.is_finite());
assert!(!max_val.is_infinite());
let min_positive = Number::from(f64::MIN_POSITIVE);
let min_val = min_positive.try_get_f64().unwrap();
assert!(min_val > 0.0);
assert!(min_val.is_normal());
let epsilon = Number::from(f64::EPSILON);
let eps_val = epsilon.try_get_f64().unwrap();
assert!(eps_val > 0.0);
assert!(eps_val < 1.0);
let nan1 = Number::from(f64::NAN);
let nan2 = Number::from(f64::INFINITY - f64::INFINITY);
assert!(nan1.try_get_f64().unwrap().is_nan());
assert!(nan2.try_get_f64().unwrap().is_nan());
let pos_inf = Number::from(f64::INFINITY);
let neg_inf = Number::from(f64::NEG_INFINITY);
assert!(pos_inf.try_get_f64().unwrap().is_infinite());
assert!(neg_inf.try_get_f64().unwrap().is_infinite());
assert!(pos_inf.try_get_f64().unwrap() > 0.0);
assert!(neg_inf.try_get_f64().unwrap() < 0.0);
assert_eq!(nan1, nan2);
assert_eq!(num!(0.0), num!(-0.0));
}
#[test]
fn test_float64_clone_copy() {
let f = num!(42.0);
let f_cloned = f.clone();
let f_copied = f.clone();
assert_eq!(f_cloned, num!(42.0));
assert_eq!(f_copied, num!(42.0));
assert_eq!(f, num!(42.0));
}
#[test]
fn test_float64_debug() {
let f = num!(3.15159);
let debug_str = format!("{f:?}");
assert!(debug_str.contains("3.15159"));
let f_nan = num!(f64::NAN);
let debug_nan = format!("{f_nan:?}");
assert!(debug_nan.contains("NaN"));
let f_inf = num!(f64::INFINITY);
let debug_inf = format!("{f_inf:?}");
assert!(debug_inf.contains("inf"));
}