arnaucube
arnaucube/shockwave-plusPublic Self-hosted repository
shockwave-plus/shockwave_plus/src/sumcheck/unipoly.rs
shockwave_plus/src/sumcheck/unipoly.rsRaw
 1use crate::FieldExt;
 2use serde::{Deserialize, Serialize};
 3
 4#[derive(Serialize, Deserialize)]
 5pub struct UniPoly<F: FieldExt> {
 6    pub coeffs: Vec<F>,
 7}
 8
 9impl<F: FieldExt> UniPoly<F> {
10    fn eval_cubic(&self, x: F) -> F {
11        // ax^3 + bx^2 + cx + d
12        let x_sq = x.square();
13        let x_cub = x_sq * x;
14
15        let a = self.coeffs[0];
16        let b = self.coeffs[1];
17        let c = self.coeffs[2];
18        let d = self.coeffs[3];
19
20        a * x_cub + b * x_sq + c * x + d
21    }
22
23    fn eval_quadratic(&self, x: F) -> F {
24        // ax^3 + bx^2 + cx + d
25        let x_sq = x.square();
26
27        let a = self.coeffs[0];
28        let b = self.coeffs[1];
29        let c = self.coeffs[2];
30
31        a * x_sq + b * x + c
32    }
33
34    pub fn eval(&self, x: F) -> F {
35        if self.coeffs.len() == 3 {
36            self.eval_quadratic(x)
37        } else {
38            self.eval_cubic(x)
39        }
40    }
41
42    pub fn interpolate(evals: &[F]) -> Self {
43        debug_assert!(
44            evals.len() == 4 || evals.len() == 3,
45            "Only cubic and quadratic polynomials are supported"
46        );
47
48        let two_inv = F::TWO_INV;
49
50        if evals.len() == 4 {
51            // ax^3 + bx^2 + cx + d
52            let six_inv = F::from(6u64).invert().unwrap();
53
54            let d = evals[0];
55            let a = six_inv
56                * (evals[3] - evals[2] - evals[2] - evals[2] + evals[1] + evals[1] + evals[1]
57                    - evals[0]);
58            let b = two_inv
59                * (evals[0] + evals[0] - evals[1] - evals[1] - evals[1] - evals[1] - evals[1]
60                    + evals[2]
61                    + evals[2]
62                    + evals[2]
63                    + evals[2]
64                    - evals[3]);
65
66            let c = evals[1] - d - a - b;
67
68            Self {
69                coeffs: vec![a, b, c, d],
70            }
71        } else {
72            let c = evals[0];
73            let a = (evals[2] - evals[1] - evals[1] + evals[0]) * two_inv;
74            let b = evals[1] - a - c;
75
76            Self {
77                coeffs: vec![a, b, c],
78            }
79        }
80    }
81}