use crate::int::algos::support::limbs::{cmp_cross, cmp_fixed};
use crate::int::types::Int;
use core::cmp::Ordering;
#[inline]
pub(crate) const fn cmp_limbwise<const N: usize>(a: Int<N>, b: Int<N>) -> Ordering {
let sn = a.is_negative();
let so = b.is_negative();
if sn && !so {
return Ordering::Less;
}
if !sn && so {
return Ordering::Greater;
}
let a_mag = a.unsigned_abs();
let b_mag = b.unsigned_abs();
let c = cmp_fixed(a_mag.as_limbs(), b_mag.as_limbs());
let c = if sn { -c } else { c };
if c < 0 {
Ordering::Less
} else if c > 0 {
Ordering::Greater
} else {
Ordering::Equal
}
}
#[inline]
pub(crate) const fn cmp_limbwise_cross<const N: usize, const M: usize>(
a: Int<N>,
b: Int<M>,
) -> Ordering {
let sn = a.is_negative();
let so = b.is_negative();
if sn && !so {
return Ordering::Less;
}
if !sn && so {
return Ordering::Greater;
}
let a_mag = a.unsigned_abs();
let b_mag = b.unsigned_abs();
let c = cmp_cross(a_mag.as_limbs(), b_mag.as_limbs());
let c = if sn { -c } else { c };
if c < 0 {
Ordering::Less
} else if c > 0 {
Ordering::Greater
} else {
Ordering::Equal
}
}
#[cfg(test)]
mod tests {
use super::cmp_limbwise;
use crate::int::types::Int;
use core::cmp::Ordering;
#[test]
fn cmp_pos_gt_neg() {
let a = Int::<1>::from_i64(1);
let b = Int::<1>::from_i64(-1);
assert_eq!(cmp_limbwise(a, b), Ordering::Greater);
assert_eq!(cmp_limbwise(b, a), Ordering::Less);
}
#[test]
fn cmp_equal_values() {
let a = Int::<2>::from_i128(12345_i128);
let b = Int::<2>::from_i128(12345_i128);
assert_eq!(cmp_limbwise(a, b), Ordering::Equal);
}
#[test]
fn cmp_zero_zero() {
let z1 = Int::<1>::from_i64(0);
let z2 = Int::<1>::from_i64(0);
assert_eq!(cmp_limbwise(z1, z2), Ordering::Equal);
}
#[test]
fn cmp_large_positive_ordering() {
let a = Int::<2>::from_u128(1_u128 << 64); let b = Int::<2>::from_u128((1_u128 << 64) - 1); assert_eq!(cmp_limbwise(a, b), Ordering::Greater);
assert_eq!(cmp_limbwise(b, a), Ordering::Less);
}
#[test]
fn cmp_two_negatives_magnitude_order() {
let a = Int::<2>::from_i128(-100_i128);
let b = Int::<2>::from_i128(-200_i128);
assert_eq!(cmp_limbwise(a, b), Ordering::Greater);
assert_eq!(cmp_limbwise(b, a), Ordering::Less);
}
#[test]
fn cmp_min_lt_max() {
let min1 = Int::<1>::from_i64(i64::MIN);
let max1 = Int::<1>::from_i64(i64::MAX);
assert_eq!(cmp_limbwise(min1, max1), Ordering::Less);
let min2 = Int::<2>::from_i128(i128::MIN);
let max2 = Int::<2>::from_i128(i128::MAX);
assert_eq!(cmp_limbwise(min2, max2), Ordering::Less);
}
}