#[inline]
pub(crate) fn lcm_exp(a: &[u32], b: &[u32]) -> Vec<u32> {
a.iter().zip(b.iter()).map(|(&x, &y)| x.max(y)).collect()
}
#[inline]
pub(crate) fn monomial_divides(a: &[u32], b: &[u32]) -> bool {
a.iter().zip(b.iter()).all(|(ai, bi)| ai <= bi)
}
#[inline]
pub(crate) fn total_deg(e: &[u32]) -> u32 {
e.iter().sum()
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) struct CriticalPair {
pub(crate) sugar_deg: u32,
pub(crate) lcm_deg: u32,
pub(crate) lcm_exp: Vec<u32>,
pub(crate) i: usize,
pub(crate) j: usize,
}
impl Ord for CriticalPair {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
other
.sugar_deg
.cmp(&self.sugar_deg)
.then_with(|| other.lcm_deg.cmp(&self.lcm_deg))
.then_with(|| self.i.cmp(&other.i))
.then_with(|| self.j.cmp(&other.j))
}
}
impl PartialOrd for CriticalPair {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
pub(crate) fn update_pairs(
lead: &[Vec<u32>],
sugar: &[u32],
pairs: &mut Vec<CriticalPair>,
new_idx: usize,
) {
let lh = &lead[new_idx];
let lh_deg = total_deg(lh);
let ecart_h = sugar[new_idx].saturating_sub(lh_deg);
struct Cand {
g_idx: usize,
lcm: Vec<u32>,
ecart_g: u32,
}
let candidates: Vec<Cand> = (0..new_idx)
.filter_map(|g_idx| {
let lg = &lead[g_idx];
if lh.iter().zip(lg.iter()).all(|(&a, &b)| a == 0 || b == 0) {
return None;
}
Some(Cand {
g_idx,
lcm: lcm_exp(lh, lg),
ecart_g: sugar[g_idx].saturating_sub(total_deg(lg)),
})
})
.collect();
let c_min: Vec<&Cand> = candidates
.iter()
.filter(|ci| {
!candidates.iter().any(|cj| {
cj.g_idx != ci.g_idx && monomial_divides(&cj.lcm, &ci.lcm) && cj.lcm != ci.lcm
})
})
.collect();
pairs.retain(|p| {
let lg1 = &lead[p.i];
let lg2 = &lead[p.j];
let lcm_12 = lcm_exp(lg1, lg2);
if !monomial_divides(lh, &lcm_12) {
return true; }
if lcm_exp(lg1, lh) == lcm_12 {
return true; }
if lcm_exp(lg2, lh) == lcm_12 {
return true; }
false });
for c in c_min {
let lcm_deg = total_deg(&c.lcm);
pairs.push(CriticalPair {
sugar_deg: lcm_deg + c.ecart_g.max(ecart_h),
lcm_deg,
lcm_exp: c.lcm.clone(),
i: c.g_idx,
j: new_idx,
});
}
}