use crate::Rational;
use core::cmp::Ordering::{self, *};
use malachite_base::num::comparison::traits::{OrdProduct, OrdProductNeg, OrdProducts};
use malachite_base::num::logic::traits::SignificantBits;
use malachite_nz::natural::Natural;
fn screen_3(o_1: Ordering, o_2: Ordering, o_3: Ordering) -> Option<Ordering> {
if o_1 != Greater && o_2 != Greater && o_3 != Greater {
Some(if o_1 == Equal && o_2 == Equal && o_3 == Equal {
Equal
} else {
Less
})
} else if o_1 != Less && o_2 != Less && o_3 != Less {
Some(Greater)
} else {
None
}
}
fn cmp_product_magnitudes(
nx: &Natural,
dx: &Natural,
ny: &Natural,
dy: &Natural,
nz: &Natural,
dz: &Natural,
) -> Ordering {
let left_bits = nx.significant_bits() + ny.significant_bits() + dz.significant_bits();
let right_bits = nz.significant_bits() + dx.significant_bits() + dy.significant_bits();
if right_bits + 3 <= left_bits {
return Greater;
} else if left_bits + 3 <= right_bits {
return Less;
}
if let Some(o) = screen_3(nx.cmp(dx), ny.cmp(dy), dz.cmp(nz)) {
return o;
}
if let Some(o) = screen_3(nx.cmp(nz), ny.cmp(dy), dz.cmp(dx)) {
return o;
}
if let Some(o) = screen_3(nx.cmp(dx), ny.cmp(nz), dz.cmp(dy)) {
return o;
}
Natural::cmp_products(&(nx * ny), dz, &(dx * dy), nz)
}
fn cmp_product_helper(
x: &Rational,
y: &Rational,
z_sign: bool,
z_num: &Natural,
z_den: &Natural,
) -> Ordering {
let z_zero = *z_num == 0u32;
if x.numerator == 0u32 || y.numerator == 0u32 {
if z_zero {
Equal
} else if z_sign {
Less
} else {
Greater
}
} else if x.sign == y.sign {
if z_zero || !z_sign {
Greater
} else {
cmp_product_magnitudes(
&x.numerator,
&x.denominator,
&y.numerator,
&y.denominator,
z_num,
z_den,
)
}
} else if z_zero || z_sign {
Less
} else {
cmp_product_magnitudes(
&x.numerator,
&x.denominator,
&y.numerator,
&y.denominator,
z_num,
z_den,
)
.reverse()
}
}
impl OrdProduct for Rational {
#[inline]
fn cmp_product(x: &Self, y: &Self, z: &Self) -> Ordering {
cmp_product_helper(x, y, z.sign, &z.numerator, &z.denominator)
}
}
impl OrdProductNeg for Rational {
#[inline]
fn cmp_product_neg(x: &Self, y: &Self, z: &Self) -> Ordering {
cmp_product_helper(x, y, !z.sign, &z.numerator, &z.denominator)
}
}