use crate::poly::ModPoly;
use polycore::fast::PrimeField;
use polycore::sample::Rng;
use polycore::{Fp, Modular};
pub(crate) fn degree_bounds(f: &ModPoly, g: &ModPoly, p: u64, rng: &mut Rng) -> Option<Vec<usize>> {
let field = PrimeField::new(p).expect("prime modulus");
let point: Vec<_> = (0..f.n).map(|_| rng.nonzero(p)).collect();
let aa = univariate_images(f, &point, p);
let bb = univariate_images(g, &point, p);
aa.iter()
.zip(&bb)
.map(|(a, b)| {
if a.last() == Some(&0) || b.last() == Some(&0) {
return None;
}
Some(field.gcd(a, b).len() - 1)
})
.collect()
}
pub(crate) fn univariate_images(f: &ModPoly, point: &[u64], p: u64) -> Vec<Vec<u64>> {
let point: Vec<_> = point.iter().map(|&x| Fp::new(x, p)).collect();
f.to_poly(p)
.univariate_images(&point)
.into_iter()
.zip(f.degrees())
.map(|(image, degree)| {
let mut cs: Vec<_> = image.0.iter().map(|c| c.residue_mod(p)).collect();
cs.resize(degree + 1, 0);
cs
})
.collect()
}