#[cfg(test)]
mod rounding_tests {
use crate::decimal::Decimal;
use crate::rounding::RoundingMode;
fn d(m: i128, s: u8) -> Decimal {
Decimal::new(m, s).unwrap()
}
fn r(m: i128, s: u8, dp: u8, mode: RoundingMode) -> i128 {
d(m, s).round(dp, mode).unwrap().mantissa()
}
#[test]
fn toward_zero_positive_above() {
assert_eq!(r(19, 1, 0, RoundingMode::TowardZero), 1);
}
#[test]
fn toward_zero_positive_below() {
assert_eq!(r(11, 1, 0, RoundingMode::TowardZero), 1);
}
#[test]
fn toward_zero_negative_above() {
assert_eq!(r(-11, 1, 0, RoundingMode::TowardZero), -1);
}
#[test]
fn toward_zero_negative_below() {
assert_eq!(r(-19, 1, 0, RoundingMode::TowardZero), -1);
}
#[test]
fn toward_zero_at_midpoint() {
assert_eq!(r(15, 1, 0, RoundingMode::TowardZero), 1);
}
#[test]
fn toward_zero_exact() {
assert_eq!(r(20, 1, 0, RoundingMode::TowardZero), 2);
}
#[test]
fn toward_zero_multi_dp() {
assert_eq!(r(1234, 3, 1, RoundingMode::TowardZero), 12);
}
#[test]
fn away_from_zero_positive() {
assert_eq!(r(11, 1, 0, RoundingMode::AwayFromZero), 2);
}
#[test]
fn away_from_zero_negative() {
assert_eq!(r(-11, 1, 0, RoundingMode::AwayFromZero), -2);
}
#[test]
fn away_from_zero_exact_no_change() {
assert_eq!(r(20, 1, 0, RoundingMode::AwayFromZero), 2);
}
#[test]
fn away_from_zero_at_midpoint_pos() {
assert_eq!(r(15, 1, 0, RoundingMode::AwayFromZero), 2);
}
#[test]
fn away_from_zero_at_midpoint_neg() {
assert_eq!(r(-15, 1, 0, RoundingMode::AwayFromZero), -2);
}
#[test]
fn away_from_zero_small_frac() {
assert_eq!(r(1, 3, 0, RoundingMode::AwayFromZero), 1);
}
#[test]
fn away_from_zero_small_frac_neg() {
assert_eq!(r(-1, 3, 0, RoundingMode::AwayFromZero), -1);
}
#[test]
fn down_positive() {
assert_eq!(r(19, 1, 0, RoundingMode::Down), 1);
}
#[test]
fn down_negative_rounds_further_from_zero() {
assert_eq!(r(-11, 1, 0, RoundingMode::Down), -2);
}
#[test]
fn down_negative_big_frac() {
assert_eq!(r(-99, 1, 0, RoundingMode::Down), -10);
}
#[test]
fn down_exact() {
assert_eq!(r(20, 1, 0, RoundingMode::Down), 2);
}
#[test]
fn down_at_midpoint_pos() {
assert_eq!(r(15, 1, 0, RoundingMode::Down), 1);
}
#[test]
fn down_at_midpoint_neg() {
assert_eq!(r(-15, 1, 0, RoundingMode::Down), -2);
}
#[test]
fn down_multi_dp() {
assert_eq!(r(1999, 3, 1, RoundingMode::Down), 19);
}
#[test]
fn up_positive_rounds_up() {
assert_eq!(r(11, 1, 0, RoundingMode::Up), 2);
}
#[test]
fn up_negative_rounds_toward_zero() {
assert_eq!(r(-11, 1, 0, RoundingMode::Up), -1);
}
#[test]
fn up_exact_no_change() {
assert_eq!(r(20, 1, 0, RoundingMode::Up), 2);
}
#[test]
fn up_at_midpoint_pos() {
assert_eq!(r(15, 1, 0, RoundingMode::Up), 2);
}
#[test]
fn up_at_midpoint_neg() {
assert_eq!(r(-15, 1, 0, RoundingMode::Up), -1);
}
#[test]
fn up_small_fraction() {
assert_eq!(r(1001, 3, 0, RoundingMode::Up), 2);
}
#[test]
fn up_small_fraction_neg() {
assert_eq!(r(-1001, 3, 0, RoundingMode::Up), -1);
}
#[test]
fn half_up_below_mid_positive() {
assert_eq!(r(14, 1, 0, RoundingMode::HalfUp), 1);
}
#[test]
fn half_up_at_mid_positive() {
assert_eq!(r(15, 1, 0, RoundingMode::HalfUp), 2);
}
#[test]
fn half_up_above_mid_positive() {
assert_eq!(r(16, 1, 0, RoundingMode::HalfUp), 2);
}
#[test]
fn half_up_below_mid_negative() {
assert_eq!(r(-14, 1, 0, RoundingMode::HalfUp), -1);
}
#[test]
fn half_up_at_mid_negative() {
assert_eq!(r(-15, 1, 0, RoundingMode::HalfUp), -2);
}
#[test]
fn half_up_above_mid_negative() {
assert_eq!(r(-16, 1, 0, RoundingMode::HalfUp), -2);
}
#[test]
fn half_up_two_dp() {
assert_eq!(r(1235, 3, 2, RoundingMode::HalfUp), 124);
}
#[test]
fn half_down_below_mid() {
assert_eq!(r(14, 1, 0, RoundingMode::HalfDown), 1);
}
#[test]
fn half_down_at_mid_positive() {
assert_eq!(r(15, 1, 0, RoundingMode::HalfDown), 1);
}
#[test]
fn half_down_above_mid_positive() {
assert_eq!(r(16, 1, 0, RoundingMode::HalfDown), 2);
}
#[test]
fn half_down_at_mid_negative() {
assert_eq!(r(-15, 1, 0, RoundingMode::HalfDown), -1);
}
#[test]
fn half_down_above_mid_negative() {
assert_eq!(r(-16, 1, 0, RoundingMode::HalfDown), -2);
}
#[test]
fn half_even_0_5_rounds_to_0() {
assert_eq!(r(5, 1, 0, RoundingMode::HalfEven), 0);
}
#[test]
fn half_even_1_5_rounds_to_2() {
assert_eq!(r(15, 1, 0, RoundingMode::HalfEven), 2);
}
#[test]
fn half_even_2_5_rounds_to_2() {
assert_eq!(r(25, 1, 0, RoundingMode::HalfEven), 2);
}
#[test]
fn half_even_3_5_rounds_to_4() {
assert_eq!(r(35, 1, 0, RoundingMode::HalfEven), 4);
}
#[test]
fn half_even_4_5_rounds_to_4() {
assert_eq!(r(45, 1, 0, RoundingMode::HalfEven), 4);
}
#[test]
fn half_even_below_midpoint() {
assert_eq!(r(14, 1, 0, RoundingMode::HalfEven), 1);
}
#[test]
fn half_even_above_midpoint() {
assert_eq!(r(16, 1, 0, RoundingMode::HalfEven), 2);
}
#[test]
fn half_even_negative_midpoint_to_even() {
assert_eq!(r(-25, 1, 0, RoundingMode::HalfEven), -2);
}
#[test]
fn half_even_negative_midpoint_to_even_odd() {
assert_eq!(r(-15, 1, 0, RoundingMode::HalfEven), -2);
}
#[test]
fn token_amount_roundtrip_6dp() {
use crate::convert::*;
let amount = 1_234_567u64;
let dec = Decimal::from_token_amount(amount, 6).unwrap();
let back = dec.to_token_amount(6, RoundingMode::HalfEven).unwrap();
assert_eq!(back, amount);
}
#[test]
fn token_amount_round_down_for_withdrawal() {
let dec = Decimal::from_token_amount(1_999_999, 6).unwrap(); let out = dec.to_token_amount(5, RoundingMode::Down).unwrap();
assert_eq!(out, 199_999u64); }
#[test]
fn rescale_up_then_round() {
let x = d(15, 1).rescale_up(3).unwrap();
assert_eq!(x.mantissa(), 1500);
let rounded = x.round(0, RoundingMode::HalfEven).unwrap();
assert_eq!(rounded.mantissa(), 2); }
#[test]
fn round_scale_28_to_27() {
let x = Decimal::new(15, 28).unwrap(); let rounded = x.round(27, RoundingMode::HalfEven).unwrap();
assert_eq!(rounded.mantissa(), 2); }
#[test]
fn round_to_scale_exceeded() {
assert!(d(1, 0).round(29, RoundingMode::HalfEven).is_err());
}
}