use ark_ff::Field;
use ark_poly::{univariate::DensePolynomial, Polynomial, UVPolynomial};
use rayon::prelude::*;
use crate::chunked_polynomial::ChunkedPolynomial;
pub trait ExtendedDensePolynomial<F: Field> {
fn scale(&self, elm: F) -> Self;
fn shiftr(&self, size: usize) -> Self;
fn eval_polynomial(coeffs: &[F], x: F) -> F;
fn to_chunked_polynomial(&self, num_chunks: usize, size: usize) -> ChunkedPolynomial<F>;
}
impl<F: Field> ExtendedDensePolynomial<F> for DensePolynomial<F> {
fn scale(&self, elm: F) -> Self {
let mut result = self.clone();
result
.coeffs
.par_iter_mut()
.for_each(|coeff| *coeff *= &elm);
result
}
fn shiftr(&self, size: usize) -> Self {
let mut result = vec![F::zero(); size];
result.extend(self.coeffs.clone());
DensePolynomial::<F>::from_coefficients_vec(result)
}
fn eval_polynomial(coeffs: &[F], x: F) -> F {
DensePolynomial::from_coefficients_slice(coeffs).evaluate(&x)
}
fn to_chunked_polynomial(&self, num_chunks: usize, chunk_size: usize) -> ChunkedPolynomial<F> {
let mut chunk_polys: Vec<DensePolynomial<F>> = Vec::with_capacity(num_chunks);
for chunk in self.coeffs.chunks(chunk_size) {
chunk_polys.push(DensePolynomial::from_coefficients_slice(chunk));
}
for _ in chunk_polys.len()..num_chunks {
chunk_polys.push(DensePolynomial::from_coefficients_vec(vec![]));
}
assert_eq!(chunk_polys.len(), num_chunks);
ChunkedPolynomial {
polys: chunk_polys,
size: chunk_size,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use ark_ff::One;
use ark_poly::{univariate::DensePolynomial, UVPolynomial};
use mina_curves::pasta::Fp;
#[test]
fn test_chunk() {
let one = Fp::one();
let two = one + one;
let three = two + one;
let num_chunks = 4;
let coeffs = [one, one, one, one, one, one, one, one];
let f = DensePolynomial::from_coefficients_slice(&coeffs);
let evals = f.to_chunked_polynomial(num_chunks, 2).evaluate_chunks(two);
assert_eq!(evals.len(), num_chunks);
for eval in evals.into_iter().take(num_chunks) {
assert!(eval == three);
}
}
}