use crate::arithmetic::align_scales;
use crate::decimal::Decimal;
use core::cmp::Ordering;
impl PartialOrd for Decimal {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Decimal {
fn cmp(&self, other: &Self) -> Ordering {
if self.scale == other.scale {
return self.mantissa.cmp(&other.mantissa);
}
match align_scales(*self, *other) {
Ok((a, b, _)) => a.cmp(&b),
Err(_) => {
match (self.mantissa >= 0, other.mantissa >= 0) {
(true, false) => Ordering::Greater,
(false, true) => Ordering::Less,
_ => {
if self.mantissa >= 0 {
self.mantissa.cmp(&other.mantissa)
} else {
other.mantissa.cmp(&self.mantissa)
}
}
}
}
}
}
}
#[cfg(test)]
mod tests {
use crate::decimal::Decimal;
fn d(m: i128, s: u8) -> Decimal {
Decimal::new(m, s).unwrap()
}
#[test]
fn eq_same_scale() {
assert_eq!(d(100, 2).cmp(&d(100, 2)), core::cmp::Ordering::Equal);
}
#[test]
fn eq_different_scale() {
assert_eq!(d(150, 2).cmp(&d(15, 1)), core::cmp::Ordering::Equal);
}
#[test]
fn gt_same_scale() {
assert!(d(200, 2) > d(100, 2));
}
#[test]
fn lt_different_scale() {
assert!(d(9, 2) < d(1, 1));
}
#[test]
fn negative_less_than_positive() {
assert!(d(-1, 0) < d(1, 0));
}
#[test]
fn negative_cmp_negative() {
assert!(d(-2, 0) < d(-1, 0));
}
#[test]
fn zero_cmp() {
assert_eq!(Decimal::ZERO.cmp(&Decimal::ZERO), core::cmp::Ordering::Equal);
assert!(Decimal::ZERO < d(1, 0));
assert!(Decimal::ZERO > d(-1, 0));
}
#[test]
fn sort_order() {
let mut vals = [d(15, 1), d(5, 2), d(100, 0), d(-1, 0)];
vals.sort();
assert_eq!(vals[0], d(-1, 0));
assert_eq!(vals[1], d(5, 2));
assert_eq!(vals[2], d(15, 1));
assert_eq!(vals[3], d(100, 0));
}
}