Skip to main content

ancdec/ancdec128/
cmp.rs

1use super::AncDec128;
2use crate::util::pow10_128;
3use core::cmp::Ordering;
4
5/// Compare absolute values
6#[inline(always)]
7pub(crate) fn cmp_abs_128(a: &AncDec128, b: &AncDec128) -> Ordering {
8    if a.int != b.int {
9        return a.int.cmp(&b.int);
10    }
11
12    let (a_frac, b_frac) = if a.scale == b.scale {
13        (a.frac, b.frac)
14    } else if a.scale > b.scale {
15        // SAFETY: frac < 10^scale by invariant, product < 10^38 < u128::MAX
16        (a.frac, b.frac * pow10_128(a.scale - b.scale))
17    } else {
18        (a.frac * pow10_128(b.scale - a.scale), b.frac)
19    };
20    a_frac.cmp(&b_frac)
21}
22
23/// Ord trait
24impl Ord for AncDec128 {
25    #[inline(always)]
26    fn cmp(&self, other: &Self) -> Ordering {
27        // 0 == -0
28        if self.is_zero() && other.is_zero() {
29            return Ordering::Equal;
30        }
31
32        match (self.neg, other.neg) {
33            (false, true) => Ordering::Greater,
34            (true, false) => Ordering::Less,
35            (false, false) => cmp_abs_128(self, other),
36            (true, true) => cmp_abs_128(self, other).reverse(),
37        }
38    }
39}
40
41impl PartialOrd for AncDec128 {
42    #[inline(always)]
43    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
44        Some(self.cmp(other))
45    }
46}
47
48impl PartialEq for AncDec128 {
49    #[inline(always)]
50    fn eq(&self, other: &Self) -> bool {
51        self.cmp(other) == Ordering::Equal
52    }
53}
54
55impl Eq for AncDec128 {}