use crate::cbig::CBig;
use crate::repr::Context;
use core::cmp::Ordering;
use dashu_base::AbsOrd;
use dashu_float::round::Round;
use dashu_float::Repr;
use dashu_int::Word;
pub(crate) fn lex_cmp<const B: Word>(
re1: &Repr<B>,
im1: &Repr<B>,
re2: &Repr<B>,
im2: &Repr<B>,
) -> Ordering {
match re1.cmp(re2) {
Ordering::Equal => im1.cmp(im2),
ord => ord,
}
}
impl<R1: Round, R2: Round, const B: Word> PartialEq<CBig<R2, B>> for CBig<R1, B> {
#[inline]
fn eq(&self, other: &CBig<R2, B>) -> bool {
self.re == other.re && self.im == other.im
}
}
impl<R: Round, const B: Word> Eq for CBig<R, B> {}
impl<R1: Round, R2: Round, const B: Word> PartialOrd<CBig<R2, B>> for CBig<R1, B> {
#[inline]
fn partial_cmp(&self, other: &CBig<R2, B>) -> Option<Ordering> {
Some(lex_cmp(&self.re, &self.im, &other.re, &other.im))
}
}
impl<R: Round, const B: Word> Ord for CBig<R, B> {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
lex_cmp(&self.re, &self.im, &other.re, &other.im)
}
}
impl<R: Round, const B: Word> AbsOrd for CBig<R, B> {
#[inline]
fn abs_cmp(&self, other: &Self) -> Ordering {
let unlim = Context::<R>::new(0);
let f = unlim.float();
let n1 = f.unwrap_fp(unlim.norm(self));
let n2 = f.unwrap_fp(unlim.norm(other));
n1.cmp(&n2)
}
}
#[cfg(test)]
mod tests {
use super::*;
use dashu_float::round::mode;
type C = CBig<mode::HalfAway, 10>;
#[test]
fn eq_componentwise() {
let a = C::from_parts(3.into(), 4.into());
let b = C::from_parts(3.into(), 4.into());
assert!(a == b);
let c = C::from_parts(3.into(), 5.into());
assert!(a != c);
}
#[test]
fn signed_zero_eq() {
let p = C::from_parts(3.into(), 0.into());
let n = C::new(Repr::new(3.into(), 0), Repr::neg_zero(), Context::new(0));
assert!(p == n);
}
#[test]
fn ord_lexicographic() {
let a = C::from_parts(1.into(), 9.into());
let b = C::from_parts(2.into(), 0.into());
assert!(a < b); let c = C::from_parts(1.into(), 10.into());
assert!(a < c); }
#[test]
fn absord_by_magnitude() {
let a = C::from_parts(3.into(), 4.into()); let b = C::from_parts(5.into(), 0.into()); assert!(a.abs_cmp(&b).is_eq());
let c = C::from_parts(1.into(), 1.into()); assert!(c.abs_cmp(&a).is_lt());
}
}