use ark_ff::{PrimeField, Zero};
use ark_poly::{univariate::DensePolynomial, DenseUVPolynomial, Polynomial};
use ark_std::{cfg_into_iter, vec::Vec};
#[cfg(feature = "parallel")]
use rayon::prelude::*;
pub fn multiply_poly<F: PrimeField>(
left: &DensePolynomial<F>,
right: &DensePolynomial<F>,
) -> DensePolynomial<F> {
let mut product = (0..(left.degree() + right.degree() + 1))
.map(|_| F::zero())
.collect::<Vec<_>>();
for i in 0..=left.degree() {
for j in 0..=right.degree() {
product[i + j] += left.coeffs[i] * right.coeffs[j];
}
}
DensePolynomial::from_coefficients_vec(product)
}
pub fn multiply_many_polys<F: PrimeField>(polys: Vec<DensePolynomial<F>>) -> DensePolynomial<F> {
#[cfg(not(feature = "parallel"))]
let r = polys
.into_iter()
.reduce(|a, b| multiply_poly(&a, &b))
.unwrap();
#[cfg(feature = "parallel")]
let r = {
use ark_std::vec;
let one = || DensePolynomial::from_coefficients_vec(vec![F::one()]);
polys
.into_par_iter()
.reduce(one, |a, b| multiply_poly(&a, &b))
};
r
}
pub fn inner_product_poly<F: PrimeField>(
polys: &[DensePolynomial<F>],
coeffs: Vec<F>,
) -> DensePolynomial<F> {
let product = cfg_into_iter!(coeffs)
.zip(cfg_into_iter!(polys))
.map(|(f, p)| p * f);
let zero = DensePolynomial::zero;
cfg_iter_sum!(product, zero)
}
pub fn poly_from_roots<F: PrimeField>(roots: &[F]) -> DensePolynomial<F> {
if roots.is_empty() {
return DensePolynomial::zero();
}
let terms = cfg_into_iter!(roots)
.map(|i| DensePolynomial::from_coefficients_slice(&[-*i, F::one()]))
.collect::<Vec<_>>();
multiply_many_polys(terms)
}