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