1mod traits;
4
5pub use self::traits::Integer;
6
7use std::cmp::Ordering;
8
9macro_rules! imp {
10 ($lhs:expr, $rhs:expr, |$min:ident, $max:ident| $align:expr) => {{
11 let (lhs, rhs) = ($lhs, $rhs);
12
13 let (lhs, rhs, reversed) = if lhs.copy().lt(rhs.copy()) {
14 (rhs, lhs, true)
15 } else if lhs.copy().eq(rhs.copy()) {
16 return Ordering::Equal;
17 } else {
18 (lhs, rhs, false)
19 };
20
21 let lhs = match (lhs.copy(), rhs.copy()) {
25 ($max, $min) => $align,
26 };
27
28 if lhs.lt(rhs) ^ reversed {
29 Ordering::Less
30 } else {
31 Ordering::Greater
34 }
35 }};
36}
37
38#[must_use]
67pub fn cmp_int<T: Integer>(lhs: T, rhs: T, radix: u32) -> Ordering {
68 if radix == 0 {
69 panic!("`radix` must be greater than 0");
70 }
71
72 imp!(lhs, rhs, |min, max| max
73 .copy()
74 .invpow(radix, max.ilog(radix) - min.ilog(radix)))
75}
76
77#[must_use]
88pub fn cmp_dec<T: Integer>(lhs: T, rhs: T) -> Ordering {
89 imp!(lhs, rhs, |min, max| max
90 .copy()
91 .invpow(10_u32, max.ilog10() - min.ilog10()))
92}
93
94#[cfg(test)]
95mod tests {
96 #[cfg(not(feature = "alloc"))]
97 extern crate alloc;
98
99 use alloc::string::ToString;
100
101 use super::*;
102
103 #[test]
104 fn matches_str_cmp() {
105 #[track_caller]
106 fn check<T: Copy + Integer + Ord + ToString>(lhs: T, rhs: T) {
107 let expected = lhs.to_string().cmp(&rhs.to_string());
108 assert_eq!(cmp_int(lhs, rhs, 10), expected);
109 assert_eq!(cmp_int(rhs, lhs, 10), expected.reverse(), "reverse");
110 assert_eq!(cmp_dec(lhs, rhs), expected, "dec");
111 assert_eq!(cmp_dec(rhs, lhs), expected.reverse(), "dec,reverse");
112 assert_eq!(cmp_int(lhs, rhs, 1), lhs.cmp(&rhs));
113 assert_eq!(cmp_int(rhs, lhs, 1), rhs.cmp(&lhs));
114 }
115
116 check(0_u64, 0_u64);
118
119 check(1_u64, 0_u64);
121 check(10_u64, 0_u64);
122 check(42_u64, 0_u64);
123
124 check(1_u64, 1_u64);
126 check(1_u64, 4_u64);
127
128 check(2_u64, 42_u64);
130 check(4_u64, 42_u64);
131 check(5_u64, 42_u64);
132 check(2_u64, 40_u64);
133 check(4_u64, 40_u64);
134 check(5_u64, 40_u64);
135
136 check(42_u64, 24_u64);
140 check(42_u64, 20_u64);
141
142 check(42_u64, 42_u64);
144 check(42_u64, 40_u64);
145 check(42_u64, 41_u64);
146 check(42_u64, 43_u64);
147
148 check(42_u64, 52_u64);
150 check(42_u64, 50_u64);
151
152 check(42_u64, 200_u64);
156 check(42_u64, 240_u64);
157 check(42_u64, 241_u64);
158 check(42_u64, 2410_u64);
159
160 check(42_u64, 410_u64);
162 check(42_u64, 411_u64);
163 check(42_u64, 4100_u64);
164 check(42_u64, 4110_u64);
165 check(42_u64, 4111_u64);
166 check(42_u64, 420_u64);
167 check(42_u64, 421_u64);
168 check(42_u64, 4211_u64);
169 check(42_u64, 4200_u64);
170 check(42_u64, 4210_u64);
171 check(42_u64, 430_u64);
172 check(42_u64, 431_u64);
173 check(42_u64, 4300_u64);
174 check(42_u64, 4310_u64);
175 check(42_u64, 4311_u64);
176
177 check(42_u64, 500_u64);
179 check(42_u64, 540_u64);
180 check(42_u64, 542_u64);
181 check(42_u64, 5420_u64);
182
183 check(u8::MAX, 1);
185 check(u8::MAX, u8::MAX - 1);
186 check(u16::MAX, 1);
187 check(u16::MAX, u16::MAX - 1);
188 check(u32::MAX, 1);
189 check(u32::MAX, u32::MAX - 1);
190 check(u64::MAX, 1);
191 check(u64::MAX, u64::MAX - 1);
192 check(usize::MAX, 1);
193 check(usize::MAX, usize::MAX - 1);
194 check(u128::MAX, 1);
195 check(u128::MAX, u128::MAX - 1);
196 }
197}