//! Contains utilities for performing arithmetic over univariate polynomials in //! various forms, including computing commitments to them and provably opening //! the committed polynomials at arbitrary points. use crate::arithmetic::{parallelize, Field}; use std::fmt::Debug; use std::marker::PhantomData; use std::ops::{Add, Deref, DerefMut, Index, IndexMut, Mul, RangeFrom, RangeFull, Sub}; pub mod commitment; mod domain; pub mod multiopen; pub use domain::*; /// This is an error that could occur during proving or circuit synthesis. // TODO: these errors need to be cleaned up #[derive(Debug)] pub enum Error { /// OpeningProof is not well-formed OpeningError, /// Caller needs to re-sample a point SamplingError, } /// The basis over which a polynomial is described. pub trait Basis: Clone + Debug + Send + Sync {} /// The polynomial is defined as coefficients #[derive(Clone, Debug)] pub struct Coeff; impl Basis for Coeff {} /// The polynomial is defined as coefficients of Lagrange basis polynomials #[derive(Clone, Debug)] pub struct LagrangeCoeff; impl Basis for LagrangeCoeff {} /// The polynomial is defined as coefficients of Lagrange basis polynomials in /// an extended size domain which supports multiplication #[derive(Clone, Debug)] pub struct ExtendedLagrangeCoeff; impl Basis for ExtendedLagrangeCoeff {} /// Represents a univariate polynomial defined over a field and a particular /// basis. #[derive(Clone, Debug)] pub struct Polynomial { values: Vec, _marker: PhantomData, } impl Index for Polynomial { type Output = F; fn index(&self, index: usize) -> &F { self.values.index(index) } } impl IndexMut for Polynomial { fn index_mut(&mut self, index: usize) -> &mut F { self.values.index_mut(index) } } impl Index> for Polynomial { type Output = [F]; fn index(&self, index: RangeFrom) -> &[F] { self.values.index(index) } } impl IndexMut> for Polynomial { fn index_mut(&mut self, index: RangeFrom) -> &mut [F] { self.values.index_mut(index) } } impl Index for Polynomial { type Output = [F]; fn index(&self, index: RangeFull) -> &[F] { self.values.index(index) } } impl IndexMut for Polynomial { fn index_mut(&mut self, index: RangeFull) -> &mut [F] { self.values.index_mut(index) } } impl Deref for Polynomial { type Target = [F]; fn deref(&self) -> &[F] { &self.values[..] } } impl DerefMut for Polynomial { fn deref_mut(&mut self) -> &mut [F] { &mut self.values[..] } } impl Polynomial { /// Iterate over the values, which are either in coefficient or evaluation /// form depending on the basis `B`. pub fn iter(&self) -> impl Iterator { self.values.iter() } /// Iterate over the values mutably, which are either in coefficient or /// evaluation form depending on the basis `B`. pub fn iter_mut(&mut self) -> impl Iterator { self.values.iter_mut() } /// Gets the size of this polynomial in terms of the number of /// coefficients used to describe it. pub fn num_coeffs(&self) -> usize { self.values.len() } } impl Polynomial { /// Maps every coefficient `c` in `p` to `1 - c`. pub fn one_minus(mut p: Self) -> Self { parallelize(&mut p.values, |p, _start| { for term in p { *term = F::one() - *term; } }); p } } impl<'a, F: Field, B: Basis> Add<&'a Polynomial> for Polynomial { type Output = Polynomial; fn add(mut self, rhs: &'a Polynomial) -> Polynomial { parallelize(&mut self.values, |lhs, start| { for (lhs, rhs) in lhs.iter_mut().zip(rhs.values[start..].iter()) { *lhs += *rhs; } }); self } } impl<'a, F: Field, B: Basis> Sub<&'a Polynomial> for Polynomial { type Output = Polynomial; fn sub(mut self, rhs: &'a Polynomial) -> Polynomial { parallelize(&mut self.values, |lhs, start| { for (lhs, rhs) in lhs.iter_mut().zip(rhs.values[start..].iter()) { *lhs -= *rhs; } }); self } } impl<'a, F: Field> Mul<&'a Polynomial> for Polynomial { type Output = Polynomial; fn mul( mut self, rhs: &'a Polynomial, ) -> Polynomial { parallelize(&mut self.values, |lhs, start| { for (lhs, rhs) in lhs.iter_mut().zip(rhs.values[start..].iter()) { *lhs *= *rhs; } }); self } } impl<'a, F: Field, B: Basis> Mul for Polynomial { type Output = Polynomial; fn mul(mut self, rhs: F) -> Polynomial { parallelize(&mut self.values, |lhs, _| { for lhs in lhs.iter_mut() { *lhs *= rhs; } }); self } }