use decimal_scaled::{D9, D18, D38};
type D9_2 = D9<2>;
type D18_2 = D18<2>;
type D38_2 = D38<2>;
#[test]
fn eq_d38_all_signed_ints() {
let v = D38_2::from_int(42);
assert_eq!(v, 42i8);
assert_eq!(42i8, v);
assert_eq!(v, 42i16);
assert_eq!(42i16, v);
assert_eq!(v, 42i32);
assert_eq!(42i32, v);
assert_eq!(v, 42i64);
assert_eq!(42i64, v);
assert_eq!(v, 42isize);
assert_eq!(42isize, v);
assert_eq!(v, 42i128);
assert_eq!(42i128, v);
let frac = D38_2::from_bits(4_201); assert_ne!(frac, 42i32);
assert_ne!(frac, 42i64);
assert_ne!(frac, 42i128);
assert_ne!(v, 41i32);
let neg = D38_2::from_int(-7);
assert_eq!(neg, -7i32);
assert_ne!(neg, 7i32);
}
#[test]
fn eq_d38_all_unsigned_ints_and_sign_rejection() {
let v = D38_2::from_int(42);
assert_eq!(v, 42u8);
assert_eq!(42u8, v);
assert_eq!(v, 42u16);
assert_eq!(42u16, v);
assert_eq!(v, 42u32);
assert_eq!(42u32, v);
assert_eq!(v, 42u64);
assert_eq!(42u64, v);
assert_eq!(v, 42usize);
assert_eq!(42usize, v);
assert_eq!(v, 42u128);
assert_eq!(42u128, v);
let neg = D38_2::from_int(-1);
assert_ne!(neg, 0u32);
assert_ne!(neg, 0u128);
assert_ne!(neg, 5u32);
let frac = D38_2::from_bits(4_201);
assert_ne!(frac, 42u32);
assert_ne!(frac, 42u128);
}
#[test]
fn eq_narrow_signed_unsigned_int() {
let v9 = D9_2::from_int(7);
assert_eq!(v9, 7i8);
assert_eq!(v9, 7u8);
assert_eq!(v9, 7i32);
assert_eq!(v9, 7u32);
let neg9 = D9_2::from_int(-3);
assert_ne!(neg9, 0u8);
let v18 = D18_2::from_int(100);
assert_eq!(v18, 100i16);
assert_eq!(v18, 100u16);
assert_eq!(v18, 100i64);
assert_eq!(v18, 100u64);
let neg18 = D18_2::from_int(-1);
assert_ne!(neg18, 0u64);
assert_ne!(neg18, 0u128);
}
#[cfg(feature = "wide")]
#[test]
fn eq_wide_int() {
use decimal_scaled::D76;
type D76_2 = D76<2>;
let v: D76_2 = D38_2::from_int(42).into();
assert_eq!(v, 42i32);
assert_eq!(42i32, v);
assert_eq!(v, 42u32);
assert_eq!(v, 42i128);
assert_eq!(v, 42u128);
let frac: D76_2 = D38_2::from_bits(4_201).into();
assert_ne!(frac, 42i32);
assert_ne!(frac, 42u32);
let neg: D76_2 = D38_2::from_int(-1).into();
assert_ne!(neg, 0u32);
assert_ne!(neg, 0u128);
}
#[cfg(feature = "std")]
#[test]
fn eq_d38_floats() {
let v = D38_2::from_int(42);
assert_eq!(v, 42.0_f64);
assert_eq!(42.0_f64, v);
assert_eq!(v, 42.0_f32);
assert_ne!(v, f64::NAN);
assert_ne!(v, f64::INFINITY);
assert_ne!(v, f64::NEG_INFINITY);
assert_ne!(v, f32::NAN);
}
#[test]
fn from_int_narrow_signed() {
assert_eq!(D9_2::from_int(7).to_bits(), 700);
assert_eq!(D18_2::from_int(100).to_bits(), 10_000);
assert_eq!(D38_2::from_int(42).to_bits(), 4_200);
assert_eq!(D38_2::from_int(-5).to_bits(), -500);
}
#[test]
fn from_primitive_paths_d38() {
let _ = D38_2::from(7_i8);
let _ = D38_2::from(7_i16);
let _ = D38_2::from(7_i32);
let _ = D38_2::from(7_i64);
let _ = D38_2::from(7_u8);
let _ = D38_2::from(7_u16);
let _ = D38_2::from(7_u32);
let _ = D38_2::from(7_u64);
assert_eq!(D38_2::from_int(0i64).to_bits(), 0);
let _: D38_2 = i128::from(0i32).try_into().unwrap_or(D38_2::ZERO);
}
#[test]
fn from_primitive_paths_d9_d18() {
let _ = D9_2::from(7_i8);
let _ = D9_2::from(7_i16);
let _ = D9_2::from(7_u8);
let _ = D9_2::from(7_u16);
let _ = D18_2::from(7_i8);
let _ = D18_2::from(7_i16);
let _ = D18_2::from(7_i32);
let _ = D18_2::from(7_u8);
let _ = D18_2::from(7_u16);
let _ = D18_2::from(7_u32);
}
#[test]
fn overflow_variants_add_d9_d18() {
let a = D9_2::MAX;
let b = D9_2::from_int(1);
assert!(a.checked_add(b).is_none());
assert_eq!(a.saturating_add(b), D9_2::MAX);
let (_, ov) = a.overflowing_add(b);
assert!(ov);
let _ = a.wrapping_add(b);
let a = D18_2::MAX;
let b = D18_2::from_int(1);
assert!(a.checked_add(b).is_none());
assert_eq!(a.saturating_add(b), D18_2::MAX);
}
#[test]
fn overflow_variants_sub_d9_d18() {
let a = D9_2::MIN;
let b = D9_2::from_int(1);
assert!(a.checked_sub(b).is_none());
assert_eq!(a.saturating_sub(b), D9_2::MIN);
let (_, ov) = a.overflowing_sub(b);
assert!(ov);
let _ = a.wrapping_sub(b);
}
#[test]
fn overflow_variants_neg_d9_d18() {
assert!(D9_2::MIN.checked_neg().is_none());
assert_eq!(D9_2::MIN.saturating_neg(), D9_2::MAX);
let (_, ov) = D9_2::MIN.overflowing_neg();
assert!(ov);
let _ = D9_2::MIN.wrapping_neg();
assert_eq!(D9_2::from_int(5).checked_neg().unwrap(), D9_2::from_int(-5));
}
#[test]
fn overflow_variants_mul_d9_d18() {
let a = D9_2::MAX;
let b = D9_2::from_int(2);
assert!(a.checked_mul(b).is_none());
assert_eq!(a.saturating_mul(b), D9_2::MAX);
let (_, ov) = a.overflowing_mul(b);
assert!(ov);
let _ = a.wrapping_mul(b);
let neg_max = D9_2::MIN;
let big = D9_2::from_int(3);
assert_eq!(neg_max.saturating_mul(big), D9_2::MIN);
let a = D18_2::MAX;
let b = D18_2::from_int(2);
assert!(a.checked_mul(b).is_none());
}
#[test]
fn overflow_variants_div_rem_d9_d18() {
let a = D9_2::from_int(7);
let b = D9_2::from_int(2);
let q = a.checked_div(b).unwrap();
assert_eq!(q.to_bits(), 350);
assert!(D9_2::from_int(7).checked_div(D9_2::ZERO).is_none());
assert_eq!(D9_2::from_int(7).saturating_div(D9_2::ZERO), D9_2::MAX);
let r = a.checked_rem(b).unwrap();
let _ = r;
assert!(D9_2::from_int(7).checked_rem(D9_2::ZERO).is_none());
let a = D18_2::from_int(7);
let b = D18_2::from_int(2);
let _ = a.checked_div(b).unwrap();
let _ = a.checked_rem(b).unwrap();
}
#[cfg(feature = "wide")]
#[test]
fn overflow_variants_wide_d76() {
use decimal_scaled::D76;
type D76_2 = D76<2>;
let a = D76_2::MAX;
let b: D76_2 = D38_2::from_int(2).into();
assert!(a.checked_mul(b).is_none());
assert_eq!(a.saturating_mul(b), D76_2::MAX);
let _ = a.wrapping_mul(b);
let (_, ov) = a.overflowing_mul(b);
assert!(ov);
let one: D76_2 = D38_2::from_int(1).into();
assert!(D76_2::MAX.checked_add(one).is_none());
assert!(D76_2::MIN.checked_sub(one).is_none());
assert!(D76_2::MIN.checked_neg().is_none());
assert!(D76_2::MAX.checked_div(D76_2::ZERO).is_none());
assert!(D76_2::MAX.checked_rem(D76_2::ZERO).is_none());
}
#[test]
fn num_traits_zero_one_bounded() {
use num_traits::{Bounded, One, Zero};
assert_eq!(<D38_2 as Zero>::zero(), D38_2::ZERO);
assert!(<D38_2 as Zero>::zero().is_zero());
assert!(!D38_2::ONE.is_zero());
assert_eq!(<D38_2 as One>::one(), D38_2::ONE);
assert!(<D38_2 as One>::one().is_one());
assert_eq!(<D38_2 as Bounded>::min_value(), D38_2::MIN);
assert_eq!(<D38_2 as Bounded>::max_value(), D38_2::MAX);
assert_eq!(<D9_2 as Zero>::zero(), D9_2::ZERO);
assert_eq!(<D18_2 as Zero>::zero(), D18_2::ZERO);
assert!(<D9_2 as Zero>::zero().is_zero());
assert!(<D18_2 as One>::one().is_one());
assert_eq!(<D9_2 as Bounded>::min_value(), D9_2::MIN);
assert_eq!(<D18_2 as Bounded>::max_value(), D18_2::MAX);
}
#[cfg(feature = "wide")]
#[test]
fn num_traits_wide() {
use decimal_scaled::D76;
use num_traits::{Bounded, One, Zero};
type D76_2 = D76<2>;
assert!(<D76_2 as Zero>::zero().is_zero());
assert!(<D76_2 as One>::one().is_one());
assert_eq!(<D76_2 as Bounded>::min_value(), D76_2::MIN);
assert_eq!(<D76_2 as Bounded>::max_value(), D76_2::MAX);
}
#[test]
fn bitwise_ops_d9_d18() {
use core::ops::*;
let a = D9_2::from_bits(0b1100);
let b = D9_2::from_bits(0b1010);
assert_eq!((a & b).to_bits(), 0b1000);
assert_eq!((a | b).to_bits(), 0b1110);
assert_eq!((a ^ b).to_bits(), 0b0110);
let mut c = a;
c &= b;
assert_eq!(c.to_bits(), 0b1000);
let mut c = a;
c |= b;
assert_eq!(c.to_bits(), 0b1110);
let mut c = a;
c ^= b;
assert_eq!(c.to_bits(), 0b0110);
assert_eq!((!D9_2::from_bits(0)).to_bits(), !0i32);
let s = D9_2::from_bits(1);
assert_eq!((s.shl(3_u32)).to_bits(), 8);
assert_eq!((D9_2::from_bits(16).shr(2_u32)).to_bits(), 4);
let a = D18_2::from_bits(0b1100);
let b = D18_2::from_bits(0b1010);
assert_eq!((a & b).to_bits(), 0b1000);
assert_eq!((a | b).to_bits(), 0b1110);
assert_eq!((a ^ b).to_bits(), 0b0110);
}
#[cfg(feature = "std")]
#[test]
fn float_bridge_narrow() {
assert_eq!(D38_2::from_f64(1.5).to_bits(), 150);
assert_eq!(D38_2::ZERO.to_f64(), 0.0);
assert_eq!(D38_2::from_f64(f64::NAN), D38_2::ZERO);
assert_eq!(D38_2::from_f64(f64::INFINITY), D38_2::MAX);
assert_eq!(D38_2::from_f64(f64::NEG_INFINITY), D38_2::MIN);
assert_eq!(D9_2::from_f64(1.5).to_bits(), 150);
assert_eq!(D18_2::from_f64(1.5).to_bits(), 150);
assert_eq!(D9_2::from_f64(2.5).to_bits(), 250);
assert_eq!(D18_2::from_f64(2.5).to_bits(), 250);
assert_eq!(D9_2::from_f64(f64::INFINITY), D9_2::MAX);
assert_eq!(D9_2::from_f64(f64::NEG_INFINITY), D9_2::MIN);
assert_eq!(D9_2::from_f64(f64::NAN), D9_2::ZERO);
assert_eq!(D18_2::from_f64(f64::INFINITY), D18_2::MAX);
assert_eq!(D9_2::from_int(1).to_f32(), 1.0_f32);
assert_eq!(D9_2::from_int(1).to_f64(), 1.0);
assert_eq!(D18_2::from_int(1).to_f32(), 1.0_f32);
assert_eq!(D18_2::from_int(1).to_f64(), 1.0);
use decimal_scaled::RoundingMode;
let v = D38_2::from_f64_with(1.5, RoundingMode::HalfToEven);
assert_eq!(v.to_bits(), 150);
let v = D38_2::from_f64_with(1.5, RoundingMode::Trunc);
assert_eq!(v.to_bits(), 150);
}
#[test]
fn try_from_narrowing_d38_to_d9_in_range() {
let v = D38_2::from_int(5);
let r: D9_2 = v.try_into().unwrap();
assert_eq!(r.to_bits(), 500);
}
#[test]
fn try_from_narrowing_d38_to_d9_out_of_range() {
let v = D38_2::from_int(900_000_000);
let r: Result<D9_2, _> = v.try_into();
assert!(r.is_err());
}
#[test]
fn try_from_d38_to_d18_in_range() {
let v = D38_2::from_int(5);
let r: D18_2 = v.try_into().unwrap();
assert_eq!(r.to_bits(), 500);
}
#[test]
fn try_from_d18_to_d9_in_range_out_of_range() {
let v = D18_2::from_int(7);
let r: D9_2 = v.try_into().unwrap();
assert_eq!(r.to_bits(), 700);
let big = D18_2::from_int(50_000_000);
let r: Result<D9_2, _> = big.try_into();
assert!(r.is_err());
}
#[test]
fn default_impls() {
assert_eq!(D9_2::default(), D9_2::ZERO);
assert_eq!(D18_2::default(), D18_2::ZERO);
assert_eq!(D38_2::default(), D38_2::ZERO);
}
#[test]
fn from_bits_zero_one_max_min() {
assert_eq!(D9_2::ZERO.to_bits(), 0);
assert_eq!(D18_2::ZERO.to_bits(), 0);
assert_eq!(D38_2::ZERO.to_bits(), 0);
assert_eq!(D9_2::ONE.to_bits(), 100);
assert_eq!(D18_2::ONE.to_bits(), 100);
assert_eq!(D38_2::ONE.to_bits(), 100);
assert!(D9_2::MAX > D9_2::ZERO);
assert!(D18_2::MAX > D18_2::ZERO);
assert!(D38_2::MAX > D38_2::ZERO);
}
#[test]
fn d38_mul_overflow_wraps_in_release() {
let a = D38_2::MAX;
let b = D38_2::from_int(2);
assert!(a.checked_mul(b).is_none());
let (_v, ov) = a.overflowing_mul(b);
assert!(ov);
assert_eq!(a.saturating_mul(b), D38_2::MAX);
}
#[test]
fn d38_div_by_zero_overflow() {
assert!(D38_2::ONE.checked_div(D38_2::ZERO).is_none());
}
#[test]
fn d38_add_sub_overflow() {
assert!(D38_2::MAX.checked_add(D38_2::ONE).is_none());
assert!(D38_2::MIN.checked_sub(D38_2::ONE).is_none());
let (_, ov) = D38_2::MAX.overflowing_add(D38_2::ONE);
assert!(ov);
let (_, ov) = D38_2::MIN.overflowing_sub(D38_2::ONE);
assert!(ov);
}
#[test]
fn decimal_trait_methods() {
use decimal_scaled::Decimal;
let v = D38_2::from_int(7);
assert_eq!(v.scale(), 2);
assert_eq!(<D38_2 as Decimal>::multiplier(), 100_i128);
assert!(!v.is_zero());
assert!(D38_2::ZERO.is_zero());
assert_eq!(v.signum(), D38_2::from_int(1));
assert_eq!(D38_2::ZERO.signum(), D38_2::ZERO);
assert_eq!(D38_2::from_int(-5).signum(), D38_2::from_int(-1));
}