1use crate::constants::{MAX_I32_SCALE, POWERS_10, U32_MASK, U32_MAX};
2use crate::decimal::Decimal;
3use crate::ops::common::Dec64;
4
5use core::cmp::Ordering;
6
7pub(crate) fn cmp_impl(d1: &Decimal, d2: &Decimal) -> Ordering {
8 if d2.is_zero() {
9 return if d1.is_zero() {
10 return Ordering::Equal;
11 } else if d1.is_sign_negative() {
12 Ordering::Less
13 } else {
14 Ordering::Greater
15 };
16 }
17 if d1.is_zero() {
18 return if d2.is_sign_negative() {
19 Ordering::Greater
20 } else {
21 Ordering::Less
22 };
23 }
24 if d1.is_sign_negative() != d2.is_sign_negative() {
26 return if d1.is_sign_negative() {
27 Ordering::Less
28 } else {
29 Ordering::Greater
30 };
31 }
32
33 let d1 = Dec64::new(d1);
35 let d2 = Dec64::new(d2);
36 if d1.negative {
39 cmp_internal(&d2, &d1)
40 } else {
41 cmp_internal(&d1, &d2)
42 }
43}
44
45pub(in crate::ops) fn cmp_internal(d1: &Dec64, d2: &Dec64) -> Ordering {
46 let mut d1_low = d1.low64;
48 let mut d1_high = d1.hi;
49 let mut d2_low = d2.low64;
50 let mut d2_high = d2.hi;
51
52 if d1.scale != d2.scale {
54 let mut diff = d2.scale as i32 - d1.scale as i32;
55 if diff < 0 {
56 diff = -diff;
57 if !rescale(&mut d2_low, &mut d2_high, diff as u32) {
58 return Ordering::Less;
59 }
60 } else if !rescale(&mut d1_low, &mut d1_high, diff as u32) {
61 return Ordering::Greater;
62 }
63 }
64
65 let hi_order = d1_high.cmp(&d2_high);
67 if hi_order != Ordering::Equal {
68 return hi_order;
69 }
70 d1_low.cmp(&d2_low)
71}
72
73fn rescale(low64: &mut u64, high: &mut u32, diff: u32) -> bool {
74 let mut diff = diff as i32;
75 loop {
77 let power = if diff >= MAX_I32_SCALE {
78 POWERS_10[9]
79 } else {
80 POWERS_10[diff as usize]
81 } as u64;
82 let tmp_lo_32 = (*low64 & U32_MASK) * power;
83 let mut tmp = (*low64 >> 32) * power + (tmp_lo_32 >> 32);
84 *low64 = (tmp_lo_32 & U32_MASK) + (tmp << 32);
85 tmp >>= 32;
86 tmp = tmp.wrapping_add((*high as u64) * power);
87 if tmp > U32_MAX {
89 return false;
90 }
91 *high = tmp as u32;
92
93 diff -= MAX_I32_SCALE;
95 if diff <= 0 {
96 break;
97 }
98 }
99
100 true
101}