use imagnum::{Float, Int, create_float, create_int};
#[test]
fn test_int_arithmetic_and_pow() {
let a = create_int("123");
let b = create_int("456");
let res_add = a._add(&b).unwrap();
match res_add {
Int::Big(bi) => assert_eq!(bi.to_string(), "579"),
_ => panic!("expected BigInt for add result"),
}
let res_sub = b._sub(&a).unwrap();
match res_sub {
Int::Big(bi) => assert_eq!(bi.to_string(), "333"),
_ => panic!("expected BigInt for sub result"),
}
let res_mul = a._mul(&b).unwrap();
match res_mul {
Int::Big(bi) => assert_eq!(bi.to_string(), "56088"),
_ => panic!("expected BigInt for mul result"),
}
let res_div = b._div(&a).unwrap();
match res_div {
Int::Big(bi) => assert_eq!(bi.to_string(), "4"),
_ => panic!("expected BigInt for div result"),
}
let res_mod = b._modulo(&a).unwrap();
match res_mod {
Int::Big(bi) => assert_eq!(bi.to_string(), "87"),
_ => panic!("expected BigInt for modulo result"),
}
let two = create_int("2");
let res_pow = two.pow(&create_int("10")).unwrap();
match res_pow {
Int::Big(bi) => assert_eq!(bi.to_string(), "1024"),
_ => panic!("expected BigInt for pow result"),
}
}
#[test]
fn test_int_conv_and_props() {
let neg = create_int("-42");
assert_eq!(neg.to_i64().unwrap(), -42i64);
let zero = create_int("0");
assert!(zero.is_zero());
let inf_like = create_int("Infinity");
assert!(inf_like.is_zero());
}
#[test]
fn test_float_arithmetic_and_properties() {
let a = create_float("123.456");
let b = create_float("78.9");
let res_mul = a._mul(&b).unwrap();
let approx = res_mul.to_f64().unwrap();
assert!((approx - (123.456f64 * 78.9f64)).abs() < 1e-8);
let res_div = a._div(&b).unwrap();
let approx_div = res_div.to_f64().unwrap();
assert!((approx_div - (123.456f64 / 78.9f64)).abs() < 1e-8);
let exp = create_float("2");
let res_pow = a.pow(&exp).unwrap();
let approx_pow = res_pow.to_f64().unwrap();
assert!((approx_pow - 123.456f64.powf(2.0)).abs() < 1e-6);
let res_sqrt = a.sqrt().unwrap();
let approx_sqrt = res_sqrt.to_f64().unwrap();
assert!((approx_sqrt - 123.456f64.sqrt()).abs() < 1e-6);
}
#[test]
fn test_float_round_truncate_and_integer_like() {
let f = create_float("123.456789");
let r = f.round(2);
let s = match r {
Float::Big(bd) | Float::Irrational(bd) => bd.to_string(),
Float::Small(_) => panic!("unexpected small float"),
_ => panic!("unexpected float kind"),
};
assert!(s.starts_with("123.46") || s.starts_with("123.4"));
let t = f.truncate(3);
let s2 = match t {
Float::Big(bd) | Float::Irrational(bd) => bd.to_string(),
Float::Small(_) => panic!("unexpected small float"),
_ => panic!("unexpected float kind"),
};
assert!(s2.starts_with("123.456") || s2.starts_with("123.45"));
let fi = create_float("42.0");
assert!(fi.is_integer_like());
let fnl = create_float("42.5");
assert!(!fnl.is_integer_like());
}
#[test]
fn test_transcendentals_and_truncation() {
let two = create_int("2");
let s2 = two.sqrt().unwrap();
match s2 {
Float::Irrational(bd) => {
let s = bd.to_string();
assert!(s.contains('.'));
let frac_len = s.split('.').nth(1).map(|p| p.len()).unwrap_or(0);
assert!(frac_len <= 137);
}
Float::Big(_) => panic!("expected irrational for sqrt(2)"),
_ => panic!("unexpected variant for sqrt(2)"),
}
let four = create_int("4");
let s4 = four.sqrt().unwrap();
match s4 {
Float::Big(bd) | Float::Irrational(bd) => {
let s = bd.to_string();
assert!(s.starts_with("2"));
}
_ => panic!("expected finite result for sqrt(4)"),
}
let zero = create_float("0");
let s = zero.sin().unwrap();
assert!(matches!(
s,
Float::Big(_) | Float::Irrational(_) | Float::Small(_)
));
assert!(
zero.cos().unwrap().to_f64().unwrap().abs() - 1.0 < 1e-12
|| zero.cos().unwrap().to_f64().unwrap().abs() < 1e-12
);
assert!(zero.tan().unwrap().to_f64().unwrap().abs() < 1e-12);
let one = create_float("1");
let ln1 = one.ln().unwrap();
assert!(ln1.to_f64().unwrap().abs() < 1e-12);
let e1 = create_float("1");
let exp1 = e1.exp().unwrap();
let approx = exp1.to_f64().unwrap();
assert!(
(approx - std::f64::consts::E).abs() < 1e-12 || (approx - std::f64::consts::E).abs() < 1e-8
);
let ten = create_float("10");
let logt = ten.log().unwrap();
assert!(
(logt.to_f64().unwrap() - 1.0).abs() < 1e-12 || (logt.to_f64().unwrap() - 1.0).abs() < 1e-8
);
let f = create_float("3.7");
let fl = f.floor().unwrap();
let cl = f.ceil().unwrap();
assert!(fl.to_f64().unwrap().abs() - 3.0 < 1e-12 || (fl.to_f64().unwrap() - 3.0).abs() < 1e-8);
assert!(
(cl.to_f64().unwrap() - 4.0).abs() < 1e-12 || (cl.to_f64().unwrap() - 4.0).abs() < 1e-8
);
}
#[test]
fn test_nan_infinity_and_complex_imaginary() {
let nan = create_float("NaN");
assert!(nan.is_nan());
let inf = create_float("Infinity");
assert_eq!(inf.to_f64().unwrap(), std::f64::INFINITY);
let ninf = create_float("-Infinity");
assert_eq!(ninf.to_f64().unwrap(), std::f64::NEG_INFINITY);
let imag = create_float("3i");
match imag {
Float::Complex(_, _) => {}
_ => panic!("expected complex/imaginary for 3i"),
}
}
#[test]
fn test_make_irrational_and_to_int() {
let f = create_float("2.0");
let i = f.to_int().unwrap();
match i {
Int::Big(bi) => assert_eq!(bi.to_string(), "2"),
_ => panic!("expected BigInt from to_int"),
}
let mut ff = create_float("1.5");
let newf = ff.make_irrational();
match newf {
Float::Irrational(_) => {}
_ => panic!("expected Irrational after make_irrational"),
}
}