Nova/src/spartan_with_ipa_pc/polynomial.rs
src/spartan_with_ipa_pc/polynomial.rsRaw
1use core::ops::Index;
2use ff::PrimeField;
3use rayon::prelude::*;
4
5pub struct EqPolynomial<Scalar: PrimeField> {
6 r: Vec<Scalar>,
7}
8
9impl<Scalar: PrimeField> EqPolynomial<Scalar> {
10 pub fn new(r: Vec<Scalar>) -> Self {
11 EqPolynomial { r }
12 }
13
14 pub fn evaluate(&self, rx: &[Scalar]) -> Scalar {
15 assert_eq!(self.r.len(), rx.len());
16 (0..rx.len())
17 .map(|i| rx[i] * self.r[i] + (Scalar::one() - rx[i]) * (Scalar::one() - self.r[i]))
18 .fold(Scalar::one(), |acc, item| acc * item)
19 }
20
21 pub fn evals(&self) -> Vec<Scalar> {
22 let ell = self.r.len();
23 let mut evals: Vec<Scalar> = vec![Scalar::zero(); (2_usize).pow(ell as u32)];
24 let mut size = 1;
25 evals[0] = Scalar::one();
26
27 for r in self.r.iter().rev() {
28 let (evals_left, evals_right) = evals.split_at_mut(size);
29 let (evals_right, _) = evals_right.split_at_mut(size);
30
31 evals_left
32 .par_iter_mut()
33 .zip(evals_right.par_iter_mut())
34 .for_each(|(x, y)| {
35 *y = *x * r;
36 *x -= &*y;
37 });
38
39 size *= 2;
40 }
41 evals
42 }
43}
44
45#[derive(Debug)]
46pub struct MultilinearPolynomial<Scalar: PrimeField> {
47 num_vars: usize, // the number of variables in the multilinear polynomial
48 Z: Vec<Scalar>, // evaluations of the polynomial in all the 2^num_vars Boolean inputs
49}
50
51impl<Scalar: PrimeField> MultilinearPolynomial<Scalar> {
52 pub fn new(Z: Vec<Scalar>) -> Self {
53 assert_eq!(Z.len(), (2_usize).pow((Z.len() as f64).log2() as u32));
54 MultilinearPolynomial {
55 num_vars: (Z.len() as f64).log2() as usize,
56 Z,
57 }
58 }
59
60 pub fn get_num_vars(&self) -> usize {
61 self.num_vars
62 }
63
64 pub fn len(&self) -> usize {
65 self.Z.len()
66 }
67
68 pub fn bound_poly_var_top(&mut self, r: &Scalar) {
69 let n = self.len() / 2;
70
71 let (left, right) = self.Z.split_at_mut(n);
72 let (right, _) = right.split_at(n);
73
74 left
75 .par_iter_mut()
76 .zip(right.par_iter())
77 .for_each(|(a, b)| {
78 *a += *r * (*b - *a);
79 });
80
81 self.Z.resize(n, Scalar::zero());
82 self.num_vars -= 1;
83 }
84
85 // returns Z(r) in O(n) time
86 pub fn evaluate(&self, r: &[Scalar]) -> Scalar {
87 // r must have a value for each variable
88 assert_eq!(r.len(), self.get_num_vars());
89 let chis = EqPolynomial::new(r.to_vec()).evals();
90 assert_eq!(chis.len(), self.Z.len());
91
92 (0..chis.len())
93 .into_par_iter()
94 .map(|i| chis[i] * self.Z[i])
95 .reduce(Scalar::zero, |x, y| x + y)
96 }
97}
98
99impl<Scalar: PrimeField> Index<usize> for MultilinearPolynomial<Scalar> {
100 type Output = Scalar;
101
102 #[inline(always)]
103 fn index(&self, _index: usize) -> &Scalar {
104 &(self.Z[_index])
105 }
106}
107
108pub struct SparsePolynomial<Scalar: PrimeField> {
109 num_vars: usize,
110 Z: Vec<(usize, Scalar)>,
111}
112
113impl<Scalar: PrimeField> SparsePolynomial<Scalar> {
114 pub fn new(num_vars: usize, Z: Vec<(usize, Scalar)>) -> Self {
115 SparsePolynomial { num_vars, Z }
116 }
117
118 fn compute_chi(a: &[bool], r: &[Scalar]) -> Scalar {
119 assert_eq!(a.len(), r.len());
120 let mut chi_i = Scalar::one();
121 for j in 0..r.len() {
122 if a[j] {
123 chi_i *= r[j];
124 } else {
125 chi_i *= Scalar::one() - r[j];
126 }
127 }
128 chi_i
129 }
130
131 // Takes O(n log n). TODO: do this in O(n) where n is the number of entries in Z
132 pub fn evaluate(&self, r: &[Scalar]) -> Scalar {
133 assert_eq!(self.num_vars, r.len());
134
135 let get_bits = |num: usize, num_bits: usize| -> Vec<bool> {
136 (0..num_bits)
137 .into_par_iter()
138 .map(|shift_amount| ((num & (1 << (num_bits - shift_amount - 1))) > 0))
139 .collect::<Vec<bool>>()
140 };
141
142 (0..self.Z.len())
143 .into_par_iter()
144 .map(|i| {
145 let bits = get_bits(self.Z[i].0, r.len());
146 SparsePolynomial::compute_chi(&bits, r) * self.Z[i].1
147 })
148 .reduce(Scalar::zero, |x, y| x + y)
149 }
150}