use std::cmp::Ordering;
use traiter::numbers::{Sign, Signed, Zeroable};
use super::digits::{compare_digits, DigitsFromNonZeroValue};
use super::types::{BigInt, Sign as BigIntSign};
impl<Digit: Ord, const DIGIT_BITNESS: usize> PartialOrd
for BigInt<Digit, DIGIT_BITNESS>
where
for<'a> &'a Self: Signed,
Self: PartialEq,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
macro_rules! big_int_partial_ord_signed_integer_impl {
($($integer:ty)*) => ($(
impl<
Digit: DigitsFromNonZeroValue<$integer> + Ord,
const DIGIT_BITNESS: usize,
> PartialOrd<$integer> for BigInt<Digit, DIGIT_BITNESS>
where
for<'a> &'a BigInt<Digit, DIGIT_BITNESS>: Signed,
Self: PartialEq<$integer>,
{
fn partial_cmp(&self, other: &$integer) -> Option<Ordering> {
Some(match self.sign.cmp(&(other.signum() as BigIntSign)) {
Ordering::Equal => match self.sign() {
Sign::Negative => compare_digits(
&Digit::digits_from_non_zero_value::<DIGIT_BITNESS>(
*other,
),
&self.digits,
),
Sign::Positive => compare_digits(
&self.digits,
&Digit::digits_from_non_zero_value::<DIGIT_BITNESS>(
*other,
),
),
Sign::Zero => Ordering::Equal,
},
value => value,
})
}
}
)*)
}
big_int_partial_ord_signed_integer_impl!(i8 i16 i32 i64 i128 isize);
macro_rules! big_int_partial_ord_unsigned_integer_impl {
($($integer:ty)*) => ($(
impl<
Digit: DigitsFromNonZeroValue<$integer> + Ord,
const DIGIT_BITNESS: usize,
> PartialOrd<$integer> for BigInt<Digit, DIGIT_BITNESS>
where
for<'a> &'a BigInt<Digit, DIGIT_BITNESS>: Signed,
Self: PartialEq<$integer>,
{
fn partial_cmp(&self, other: &$integer) -> Option<Ordering> {
Some(match self.sign() {
Sign::Negative => Ordering::Less,
Sign::Positive => {
if other.is_zero() {
Ordering::Greater
} else {
compare_digits(
&self.digits,
&Digit::digits_from_non_zero_value::<DIGIT_BITNESS>(
*other,
),
)
}
}
Sign::Zero => {
if other.is_zero() {
Ordering::Equal
} else {
Ordering::Less
}
}
})
}
}
)*)
}
big_int_partial_ord_unsigned_integer_impl!(u8 u16 u32 u64 u128 usize);
macro_rules! signed_integer_partial_ord_big_int_impl {
($($integer:ty)*) => ($(
impl<
Digit: DigitsFromNonZeroValue<$integer> + Ord,
const DIGIT_BITNESS: usize,
> PartialOrd<BigInt<Digit, DIGIT_BITNESS>> for $integer
where
for<'a> &'a BigInt<Digit, DIGIT_BITNESS>: Signed,
Self: PartialEq<BigInt<Digit, DIGIT_BITNESS>>,
{
fn partial_cmp(
&self,
other: &BigInt<Digit, DIGIT_BITNESS>,
) -> Option<Ordering> {
Some(match (self.signum() as BigIntSign).cmp(&other.sign) {
Ordering::Equal => match other.sign() {
Sign::Negative => compare_digits(
&other.digits,
&Digit::digits_from_non_zero_value::<DIGIT_BITNESS>(*self),
),
Sign::Positive => compare_digits(
&Digit::digits_from_non_zero_value::<DIGIT_BITNESS>(*self),
&other.digits,
),
Sign::Zero => Ordering::Equal,
},
value => value,
})
}
}
)*)
}
signed_integer_partial_ord_big_int_impl!(i8 i16 i32 i64 i128 isize);
macro_rules! unsigned_integer_partial_ord_big_int_impl {
($($integer:ty)*) => ($(
impl<
Digit: DigitsFromNonZeroValue<$integer> + Ord,
const DIGIT_BITNESS: usize,
> PartialOrd<BigInt<Digit, DIGIT_BITNESS>> for $integer
where
for<'a> &'a BigInt<Digit, DIGIT_BITNESS>: Signed,
Self: PartialEq<BigInt<Digit, DIGIT_BITNESS>>,
{
fn partial_cmp(
&self,
other: &BigInt<Digit, DIGIT_BITNESS>,
) -> Option<Ordering> {
Some(match other.sign() {
Sign::Negative => Ordering::Greater,
Sign::Positive => {
if self.is_zero() {
Ordering::Less
} else {
compare_digits(
&Digit::digits_from_non_zero_value::<DIGIT_BITNESS>(
*self,
),
&other.digits,
)
}
}
Sign::Zero => {
if self.is_zero() {
Ordering::Equal
} else {
Ordering::Greater
}
}
})
}
}
)*)
}
unsigned_integer_partial_ord_big_int_impl!(u8 u16 u32 u64 u128 usize);