o1_utils/
chunked_polynomial.rs

1//! This module contains a type [ChunkedPolynomial],
2//! and a number of helper methods to deal with chunked polynomials.
3//! Polynomials that cut in several polynomials of the same length.
4
5use ark_ff::Field;
6use ark_poly::polynomial::{univariate::DensePolynomial, Polynomial};
7
8/// This struct contains multiple chunk polynomials with degree `size-1`.
9#[derive(Clone)]
10pub struct ChunkedPolynomial<F: Field> {
11    /// The chunk polynomials.
12    pub polys: Vec<DensePolynomial<F>>,
13
14    /// Each chunk polynomial has degree `size-1`.
15    pub size: usize,
16}
17
18impl<F: Field> ChunkedPolynomial<F> {
19    /// This function evaluates polynomial in chunks.
20    pub fn evaluate_chunks(&self, elm: F) -> Vec<F> {
21        let mut res: Vec<F> = vec![];
22        for poly in &self.polys {
23            let eval = poly.evaluate(&elm);
24            res.push(eval);
25        }
26        res
27    }
28
29    /// Multiplies the chunks of a polynomial with powers of zeta^n to make it of degree n-1.
30    /// For example, if a polynomial can be written `f = f0 + x^n f1 + x^2n f2`
31    /// (where f0, f1, f2 are of degree n-1), then this function returns the new semi-evaluated
32    /// `f'(x) = f0(x) + zeta^n f1(x) + zeta^2n f2(x)`.
33    pub fn linearize(&self, zeta_n: F) -> DensePolynomial<F> {
34        let mut scale = F::one();
35        let mut coeffs = vec![F::zero(); self.size];
36
37        for poly in &self.polys {
38            for (coeff, poly_coeff) in coeffs.iter_mut().zip(&poly.coeffs) {
39                *coeff += scale * poly_coeff;
40            }
41
42            scale *= zeta_n;
43        }
44
45        while coeffs.last().map_or(false, |c| c.is_zero()) {
46            coeffs.pop();
47        }
48
49        DensePolynomial { coeffs }
50    }
51}