use crate::Rational;
use core::cmp::Ordering::{self, *};
use malachite_base::num::comparison::traits::{OrdProducts, OrdProductsNeg};
use malachite_base::num::logic::traits::SignificantBits;
use malachite_nz::natural::Natural;
fn screen_4(o_1: Ordering, o_2: Ordering, o_3: Ordering, o_4: Ordering) -> Option<Ordering> {
let os = [o_1, o_2, o_3, o_4];
if os.iter().all(|&o| o != Greater) {
Some(if os.iter().all(|&o| o == Equal) {
Equal
} else {
Less
})
} else if os.iter().all(|&o| o != Less) {
Some(Greater)
} else {
None
}
}
#[allow(clippy::too_many_arguments)]
fn cmp_products_magnitudes(
nw: &Natural,
dw: &Natural,
nx: &Natural,
dx: &Natural,
ny: &Natural,
dy: &Natural,
nz: &Natural,
dz: &Natural,
) -> Ordering {
let left_bits = nw.significant_bits()
+ nx.significant_bits()
+ dy.significant_bits()
+ dz.significant_bits();
let right_bits = ny.significant_bits()
+ nz.significant_bits()
+ dw.significant_bits()
+ dx.significant_bits();
if right_bits + 4 <= left_bits {
return Greater;
} else if left_bits + 4 <= right_bits {
return Less;
}
if let Some(o) = screen_4(nw.cmp(dw), nx.cmp(dx), dy.cmp(ny), dz.cmp(nz)) {
return o;
}
if let Some(o) = screen_4(nw.cmp(ny), nx.cmp(nz), dy.cmp(dw), dz.cmp(dx)) {
return o;
}
if let Some(o) = screen_4(nw.cmp(nz), nx.cmp(ny), dy.cmp(dx), dz.cmp(dw)) {
return o;
}
Natural::cmp_products(&(nw * nx), &(dy * dz), &(ny * nz), &(dw * dx))
}
fn cmp_products_helper(
w: &Rational,
x: &Rational,
y: &Rational,
z: &Rational,
negate_right: bool,
) -> Ordering {
let left_zero = w.numerator == 0u32 || x.numerator == 0u32;
let right_zero = y.numerator == 0u32 || z.numerator == 0u32;
let left_positive = w.sign == x.sign;
let right_positive = (y.sign == z.sign) != negate_right;
let magnitudes = || {
cmp_products_magnitudes(
&w.numerator,
&w.denominator,
&x.numerator,
&x.denominator,
&y.numerator,
&y.denominator,
&z.numerator,
&z.denominator,
)
};
if left_zero {
if right_zero {
Equal
} else if right_positive {
Less
} else {
Greater
}
} else if left_positive {
if right_zero || !right_positive {
Greater
} else {
magnitudes()
}
} else if right_zero || right_positive {
Less
} else {
magnitudes().reverse()
}
}
impl OrdProducts for Rational {
#[inline]
fn cmp_products(w: &Self, x: &Self, y: &Self, z: &Self) -> Ordering {
cmp_products_helper(w, x, y, z, false)
}
}
impl OrdProductsNeg for Rational {
#[inline]
fn cmp_products_neg(w: &Self, x: &Self, y: &Self, z: &Self) -> Ordering {
cmp_products_helper(w, x, y, z, true)
}
}