use comnum_math::gf2m::Field;
pub(crate) fn berlekamp_massey(f: &Field, syn: &[u32]) -> (Vec<u32>, usize) {
let mut lambda = vec![1u32];
let mut b_poly = vec![1u32];
let (mut l, mut shift, mut b_disc) = (0usize, 1usize, 1u32);
for step in 0..syn.len() {
let mut d = syn[step];
for i in 1..=l.min(lambda.len() - 1) {
d ^= f.mul(lambda[i], syn[step - i]);
}
if d == 0 {
shift += 1;
continue;
}
let coef = f.div(d, b_disc);
let mut next = lambda.clone();
if next.len() < b_poly.len() + shift {
next.resize(b_poly.len() + shift, 0);
}
for (i, &bv) in b_poly.iter().enumerate() {
next[i + shift] ^= f.mul(coef, bv);
}
if 2 * l <= step {
b_poly = lambda;
l = step + 1 - l;
b_disc = d;
shift = 1;
} else {
shift += 1;
}
lambda = next;
}
while lambda.len() > 1 && lambda.last() == Some(&0) {
lambda.pop();
}
(lambda, l)
}
pub(crate) fn eval_at_power(f: &Field, p: &[u32], e: usize) -> u32 {
p.iter().enumerate().fold(0u32, |acc, (d, &a)| acc ^ f.mul(a, f.pow(d * e)))
}
pub(crate) fn chien_search(f: &Field, p: &[u32], n: usize, locator_exp: impl Fn(usize) -> usize) -> Vec<usize> {
let order = f.order();
(0..n).filter(|&i| eval_at_power(f, p, (order - locator_exp(i)) % order) == 0).collect()
}