use fermat_core::{Decimal, RoundingMode};
fn d(m: i128, s: u8) -> Decimal {
Decimal::new(m, s).unwrap()
}
#[test]
fn add_is_deterministic() {
let a = d(150_000_000, 6);
let b = d(2_500_000, 6);
let first = a.checked_add(b).unwrap();
for _ in 0..100 {
assert_eq!(a.checked_add(b).unwrap(), first);
}
}
#[test]
fn sub_is_deterministic() {
let a = d(150_000_000, 6);
let b = d(2_500_000, 6);
let first = a.checked_sub(b).unwrap();
for _ in 0..100 {
assert_eq!(a.checked_sub(b).unwrap(), first);
}
}
#[test]
fn mul_is_deterministic() {
let a = d(150_000_000, 6);
let b = d(2_500_000, 6);
let first = a.checked_mul(b).unwrap();
for _ in 0..100 {
assert_eq!(a.checked_mul(b).unwrap(), first);
}
}
#[test]
fn div_is_deterministic() {
let a = d(150_000_000, 6);
let b = d(2_500_000, 6);
let first = a.checked_div(b).unwrap();
for _ in 0..100 {
assert_eq!(a.checked_div(b).unwrap(), first);
}
}
#[test]
fn mul_div_is_deterministic() {
let a = d(i128::MAX / 4, 0);
let b = d(3, 0);
let c = d(4, 0);
let first = a.checked_mul_div(b, c).unwrap();
for _ in 0..100 {
assert_eq!(a.checked_mul_div(b, c).unwrap(), first);
}
}
#[test]
fn round_half_even_is_deterministic() {
let a = d(1_234_567_890, 9);
let first = a.round(6, RoundingMode::HalfEven).unwrap();
for _ in 0..100 {
assert_eq!(a.round(6, RoundingMode::HalfEven).unwrap(), first);
}
}
#[test]
fn add_order_independence() {
let a = d(100_000, 6);
let b = d(200_000, 6);
let c = d(300_000, 6);
let lhs = a.checked_add(b).unwrap().checked_add(c).unwrap();
let rhs = c.checked_add(b).unwrap().checked_add(a).unwrap();
assert_eq!(lhs, rhs);
}
#[test]
fn mul_order_independence() {
let a = d(7, 0);
let b = d(11, 0);
let c = d(13, 0);
let lhs = a.checked_mul(b).unwrap().checked_mul(c).unwrap();
let rhs = c.checked_mul(b).unwrap().checked_mul(a).unwrap();
assert_eq!(lhs, rhs);
}
#[test]
fn chained_interest_accrual_is_stable() {
let mut index = d(1_000_000, 6); let monthly_rate = d(4_167, 6);
for _ in 0..12 {
let interest = index.checked_mul(monthly_rate).unwrap();
index = index.checked_add(interest).unwrap();
index = index.round(6, RoundingMode::HalfEven).unwrap();
}
assert_eq!(index.to_i128_truncated(), 1);
assert!(index.mantissa() > 1_050_000);
assert!(index.mantissa() < 1_053_000);
}
#[test]
fn repeated_rescale_is_idempotent() {
let a = d(1_500_000, 6);
let rescaled = a.rescale_up(6).unwrap(); assert_eq!(rescaled, a);
}