From e669725ccb70cbec552749906df8852be51f6f3b Mon Sep 17 00:00:00 2001 From: Adegbite Ademola Kelvin Date: Mon, 16 Sep 2024 09:22:00 +0100 Subject: [PATCH] update --- .vscode/settings.json | 4 +- gkr/src/utils.rs | 1 + polynomial/src/interface.rs | 2 +- polynomial/src/lib.rs | 3 +- .../src/univariate_polynomial/interface.rs | 24 ++ polynomial/src/univariate_polynomial/mod.rs | 334 +----------------- .../univariant_coefficient.rs | 116 ++++++ .../src/univariate_polynomial/univariate.rs | 331 +++++++++++++++++ polynomial/src/util.rs | 21 ++ sum-check/src/composedsumcheck.rs | 2 +- sum-check/src/multi_composedsumcheck.rs | 6 +- 11 files changed, 505 insertions(+), 339 deletions(-) create mode 100644 polynomial/src/univariate_polynomial/interface.rs create mode 100644 polynomial/src/univariate_polynomial/univariant_coefficient.rs create mode 100644 polynomial/src/univariate_polynomial/univariate.rs diff --git a/.vscode/settings.json b/.vscode/settings.json index c9459eb..eeb1da4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,9 @@ { "cSpell.words": [ + "coeff", "composedsumcheck", "datastructure", - "multilinear" + "multilinear", + "univariant" ] } \ No newline at end of file diff --git a/gkr/src/utils.rs b/gkr/src/utils.rs index e81fe2c..c257353 100644 --- a/gkr/src/utils.rs +++ b/gkr/src/utils.rs @@ -11,6 +11,7 @@ use polynomial::{ use sum_check::multi_composedsumcheck::MultiComposedSumcheckVerifier; use sum_check::multi_composedsumcheck::{ComposedSumcheckProof, MultiComposedSumcheckProver}; use transcript::transcription::Transcript; +//look into this. pub fn label_to_binary_to_decimal(a: usize, b: usize, c: usize) -> usize { let a_shifted = a << 4; let b_shifted = b << 2; diff --git a/polynomial/src/interface.rs b/polynomial/src/interface.rs index fef0a12..93f89fb 100644 --- a/polynomial/src/interface.rs +++ b/polynomial/src/interface.rs @@ -1,4 +1,4 @@ -use crate::{ UnivariatePolynomial}; +use crate::univariate_polynomial::univariate::UnivariatePolynomial; use ark_ff::PrimeField; pub trait UnivariatePolynomialTrait { diff --git a/polynomial/src/lib.rs b/polynomial/src/lib.rs index 005ecf1..e19c23b 100644 --- a/polynomial/src/lib.rs +++ b/polynomial/src/lib.rs @@ -1,7 +1,6 @@ pub mod univariate_polynomial; pub mod multilinear; pub mod composed; -pub use univariate_polynomial::UnivariatePolynomial; pub use multilinear::coefficient_form::{MultilinearMonomial, MultilinearPolynomial}; pub mod interface; -pub mod util; \ No newline at end of file +pub mod util; diff --git a/polynomial/src/univariate_polynomial/interface.rs b/polynomial/src/univariate_polynomial/interface.rs new file mode 100644 index 0000000..f5ce4e4 --- /dev/null +++ b/polynomial/src/univariate_polynomial/interface.rs @@ -0,0 +1,24 @@ +use ark_ff::PrimeField; +pub trait PolynomialInterface { + type Point; + + /// Return the total degree of the polynomial + fn degree(&self) -> usize; + + /// Evaluates `self` at the given `point` in `Self::Point`. + fn evaluate(&self, point: &Self::Point) -> F; + + /// Checks if the polynomial is zero + fn is_zero(&self) -> bool; +} + +pub trait UnivariantPolynomialInterface: PolynomialInterface { + /// This function returs an array of co-efficents of this polynomial + fn coefficients(&self) -> &[F]; + /// This function createsa new polynomial from a list of coefficients slice + fn from_coefficients_slice(coeffs: &[F]) -> Self; + /// This function creates a new polynomial from a list of coefficients vector + fn from_coefficients_vec(coeffs: Vec) -> Self; + /// This function is used to create a new univariate polynomial using an interpolation + fn interpolate(point_ys: Vec, domain: Vec) -> Self; +} \ No newline at end of file diff --git a/polynomial/src/univariate_polynomial/mod.rs b/polynomial/src/univariate_polynomial/mod.rs index 98c4cea..e9b52aa 100644 --- a/polynomial/src/univariate_polynomial/mod.rs +++ b/polynomial/src/univariate_polynomial/mod.rs @@ -1,331 +1,3 @@ -use crate::interface::UnivariatePolynomialTrait; -use crate::util::lagrange_basis; -use ark_ff::{PrimeField, BigInteger}; -use std::{ - fmt::{Display, Formatter, Result}, - ops::{Add, Mul}, -}; - -#[derive(Clone, PartialEq, Eq, Hash, Default, Debug)] -pub struct UnivariateMonomial { - pub coeff: F, - pub pow: F, -} -#[derive(Clone, PartialEq, Eq, Hash, Default, Debug)] -pub struct UnivariatePolynomial { - pub monomial: Vec>, -} - -impl UnivariatePolynomialTrait for UnivariatePolynomial { - fn new(data: Vec) -> Self { - let mut monomial: Vec> = Vec::new(); - - for n in (0..data.len()).step_by(2) { - if n < data.len() - 1 { - let monomial_value: UnivariateMonomial = - UnivariateMonomial { coeff: data[n], pow: data[n + 1] }; - monomial.push(monomial_value); - } else if n == data.len() - 1 { - let monomial_value: UnivariateMonomial = - UnivariateMonomial { coeff: data[n], pow: F::zero() }; - monomial.push(monomial_value); - } - } - - UnivariatePolynomial { monomial } - } - - fn zero() -> Self { - Self { monomial: vec![] } - } - fn evaluate(&self, point: F) -> F { - let mut point_evaluation: F = F::from(0_u8); - for n in self.monomial.iter() { - let coefficient = n.coeff; - let n_pow: ::BigInt = n.pow.into(); - let power = point.pow(&n_pow); - - let evaluation = coefficient * power; - point_evaluation += evaluation; - } - - point_evaluation - } - - fn interpolate(points: &[(F, F)]) -> UnivariatePolynomial { - let mut result: Vec = vec![F::zero(); points.len()]; - - for (i, &(_, y_i)) in points.iter().enumerate() { - let l_i: Vec = lagrange_basis(points, i); - let l_i: Vec = l_i.into_iter().map(|coeff| coeff * y_i).collect(); - - for (k, &coeff) in l_i.iter().enumerate() { - result[k] += coeff; - } - } - - let monomial: Vec> = result - .into_iter() - .enumerate() - .filter(|&(_, coeff)| coeff != F::zero()) - .map(|(pow, coeff)| UnivariateMonomial { coeff, pow: F::from(pow as u64) }) - .collect(); - - UnivariatePolynomial { monomial } - } - - fn degree(&self) -> F { - let mut highest_degree: F = F::from(0_u8); - for m in self.monomial.iter() { - if m.pow > highest_degree { - highest_degree = m.pow; - } - } - - highest_degree.try_into().unwrap() - } - - fn to_bytes(&self) -> Vec { - let mut bytes = Vec::new(); - for p in self.monomial.iter() { - bytes.extend_from_slice(&p.coeff.into_bigint().to_bytes_be()); - bytes.extend_from_slice(&p.pow.into_bigint().to_bytes_be()); - } - bytes - } - -} - -impl Mul for UnivariatePolynomial { - type Output = Self; - fn mul(self, rhs: Self) -> Self { - let mut result_monomial: Vec> = Vec::new(); - - for lhs_mn in &self.monomial { - for rhs_mn in &rhs.monomial { - let new_coeff = lhs_mn.coeff * rhs_mn.coeff; - let new_pow = lhs_mn.pow + rhs_mn.pow; - - let mut found_like_terms = false; - for res_mn in &mut result_monomial { - if res_mn.pow == new_pow { - res_mn.coeff += new_coeff; - found_like_terms = true; - break; - } - } - - if !found_like_terms { - result_monomial.push(UnivariateMonomial { coeff: new_coeff, pow: new_pow }); - } - } - } - - UnivariatePolynomial { monomial: result_monomial } - } -} - -impl Add for UnivariatePolynomial { - type Output = Self; - - fn add(self, rhs: Self) -> Self::Output { - let mut result_monomials = Vec::new(); - let mut lhs_iter = self.monomial.into_iter(); - let mut rhs_iter = rhs.monomial.into_iter(); - let mut lhs_mn = lhs_iter.next(); - let mut rhs_mn = rhs_iter.next(); - - while lhs_mn.is_some() || rhs_mn.is_some() { - match (lhs_mn.clone(), rhs_mn.clone()) { - (Some(l), Some(r)) => { - if l.pow == r.pow { - result_monomials - .push(UnivariateMonomial { coeff: l.coeff + r.coeff, pow: l.pow }); - lhs_mn = lhs_iter.next(); - rhs_mn = rhs_iter.next(); - } else if l.pow < r.pow { - result_monomials.push(l); - lhs_mn = lhs_iter.next(); - } else { - result_monomials.push(r); - rhs_mn = rhs_iter.next(); - } - }, - (Some(l), None) => { - result_monomials.push(l); - lhs_mn = lhs_iter.next(); - }, - (None, Some(r)) => { - result_monomials.push(r); - rhs_mn = rhs_iter.next(); - }, - (None, None) => break, - } - } - - UnivariatePolynomial { monomial: result_monomials } - } -} - -impl Display for UnivariatePolynomial { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { - for (index, mn) in self.monomial.iter().enumerate() { - if index == 0 { - write!(f, "{}", mn.coeff)?; - } else { - if mn.pow == F::from(0_u8) || mn.coeff == F::from(0_u8) { - write!(f, " + {}", mn.coeff)?; - } else if mn.pow == F::from(1_u8) { - write!(f, " + {}x", mn.coeff)?; - } else { - write!(f, " + {}x^{}", mn.coeff, mn.pow)?; - } - } - } - Ok(()) - } -} - -mod tests { - use super::*; - use ark_ff::MontConfig; - use ark_ff::{Fp64, MontBackend}; - - #[derive(MontConfig)] - #[modulus = "17"] - #[generator = "3"] - struct FqConfig; - type Fq = Fp64>; - - #[test] - fn test_polynomial_evaluation() { - let data = vec![ - Fq::from(5_u8), - Fq::from(0_u8), - Fq::from(2_u8), - Fq::from(1_u8), - Fq::from(4_u8), - Fq::from(6_u8), - ]; - let polynomial = UnivariatePolynomial::new(data); - let evaluation = polynomial.evaluate(Fq::from(2_u8)); - - assert_eq!(evaluation, Fq::from(10_u8)); - } - - #[test] - fn test_polynomial_addition() { - let data = vec![Fq::from(5_u8), Fq::from(0_u8)]; - let data2 = vec![Fq::from(2_u8), Fq::from(1_u8)]; - - - let polynomial1 = UnivariatePolynomial::new(data); - let polynomial2 = UnivariatePolynomial::new(data2); - - assert_eq!( - polynomial1 + polynomial2, - UnivariatePolynomial::new(vec![ - Fq::from(5_u8), - Fq::from(0_u8), - Fq::from(2_u8), - Fq::from(1_u8), - ]) - ); - - let data3 = vec![Fq::from(5_u8), Fq::from(0_u8), Fq::from(5_u8), Fq::from(2_u8)]; - let data4 = vec![Fq::from(2_u8), Fq::from(1_u8), Fq::from(2_u8), Fq::from(2_u8)]; - let polynomial1 = UnivariatePolynomial::new(data3); - let polynomial2 = UnivariatePolynomial::new(data4); - - assert_eq!( - polynomial1 + polynomial2, - UnivariatePolynomial::new(vec![ - Fq::from(5_u8), - Fq::from(0_u8), - Fq::from(2_u8), - Fq::from(1_u8), - Fq::from(7_u8), - Fq::from(2_u8), - ]) - ); - } - - #[test] - fn test_polynomial_multiplication() { - let data = vec![Fq::from(5_u8), Fq::from(0_u8)]; - let data2 = vec![Fq::from(2_u8), Fq::from(1_u8)]; - - let polynomial1 = UnivariatePolynomial::new(data); - let polynomial2 = UnivariatePolynomial::new(data2); - - assert_eq!( - polynomial1 + polynomial2, - UnivariatePolynomial::new(vec![ - Fq::from(5_u8), - Fq::from(0_u8), - Fq::from(2_u8), - Fq::from(1_u8), - ]) - ); - - let data3 = vec![ - Fq::from(5_u8), - Fq::from(0_u8), - Fq::from(2_u8), - Fq::from(1_u8), - Fq::from(4_u8), - Fq::from(6_u8), - ]; - let data4 = - vec![Fq::from(4), Fq::from(0), Fq::from(3), Fq::from(2), Fq::from(4), Fq::from(5)]; - - let polynomial3 = UnivariatePolynomial::new(data3); - let polynomial4 = UnivariatePolynomial::new(data4); - - assert_eq!( - polynomial3 * polynomial4, - UnivariatePolynomial::new(vec![ - Fq::from(3_u8), - Fq::from(0_u8), - Fq::from(15_u8), - Fq::from(2_u8), - Fq::from(3_u8), - Fq::from(5_u8), - Fq::from(8_u8), - Fq::from(1_u8), - Fq::from(6_u8), - Fq::from(3_u8), - Fq::from(7_u8), - Fq::from(6_u8), - Fq::from(12_u8), - Fq::from(8_u8), - Fq::from(16_u8), - Fq::from(11_u8), - ]) - ); - } - - #[test] - fn test_polynomial_interpolate() { - let interpolation = UnivariatePolynomial::interpolate(&[ - (Fq::from(1), Fq::from(2)), - (Fq::from(2), Fq::from(3)), - (Fq::from(4), Fq::from(11)), - ]); - - let interpolation_check = UnivariatePolynomial::new(vec![ - Fq::from(3_u8), - Fq::from(0_u8), - Fq::from(15_u8), - Fq::from(1_u8), - Fq::from(1_u8), - Fq::from(2_u8), - ]); - assert_eq!(interpolation, interpolation_check); - - // to test the evaluation of the polynomial - let evaluation = interpolation.evaluate(Fq::from(2_u8)); - assert_eq!(evaluation, Fq::from(3_u8)); - } - -} +pub mod univariate; +pub mod univariant_coefficient; +pub mod interface; \ No newline at end of file diff --git a/polynomial/src/univariate_polynomial/univariant_coefficient.rs b/polynomial/src/univariate_polynomial/univariant_coefficient.rs new file mode 100644 index 0000000..859874c --- /dev/null +++ b/polynomial/src/univariate_polynomial/univariant_coefficient.rs @@ -0,0 +1,116 @@ +use std::ops::{Add, Mul}; + +use crate::{ + univariate_polynomial::interface::{PolynomialInterface, UnivariantPolynomialInterface}, + util::lbasis, +}; +use ark_ff::{BigInteger, PrimeField}; +#[derive(Clone, PartialEq, Eq, Hash, Default, Debug)] +pub struct UnivariantPolynomial { + pub coefficients: Vec, +} + +impl PolynomialInterface for UnivariantPolynomial { + type Point = F; + + fn degree(&self) -> usize { + if self.coefficients.is_empty() { + return 0; + } + self.coefficients.len() - 1 + } + + fn evaluate(&self, x: &F) -> F { + self.coefficients.iter().rev().fold(F::zero(), |acc, c| acc * x + c) + } + + fn is_zero(&self) -> bool { + self.coefficients.is_empty() + } +} + +impl UnivariantPolynomialInterface for UnivariantPolynomial { + fn from_coefficients_slice(coefficients: &[F]) -> Self { + UnivariantPolynomial { coefficients: coefficients.to_vec() } + } + fn from_coefficients_vec(coefficients: Vec) -> Self { + UnivariantPolynomial { coefficients } + } + fn coefficients(&self) -> &[F] { + &self.coefficients + } + fn interpolate(point_ys: Vec, domain: Vec) -> Self { + let langrange_poly_vec = lbasis(&domain, &point_ys); + let langrange_poly = langrange_poly_vec + .iter() + .fold(UnivariantPolynomial::new(vec![]), |acc, x| acc + x.clone()); + langrange_poly + } +} + +impl UnivariantPolynomial { + pub fn new(coefficients: Vec) -> Self { + UnivariantPolynomial { coefficients } + } + pub fn zero() -> Self { + UnivariantPolynomial::new(vec![]) + } + pub fn one() -> Self { + UnivariantPolynomial::new(vec![F::one()]) + } + + pub fn to_bytes(&self) -> Vec { + let mut bytes = vec![]; + for c in &self.coefficients { + let big_int = c.into_bigint().to_bytes_be(); + bytes.extend_from_slice(&big_int); + } + bytes + } +} + +impl Mul for UnivariantPolynomial { + type Output = Self; + fn mul(self, rhs: Self) -> Self { + if self.is_zero() || rhs.is_zero() { + return UnivariantPolynomial::new(vec![]); + } + let product_degree = self.degree() + rhs.degree(); + + let mut polynomial_product_coefficients = vec![F::zero(); product_degree + 1]; + for i in 0..=self.degree() { + for j in 0..=rhs.degree() { + polynomial_product_coefficients[i + j] += self.coefficients[i] * rhs.coefficients[j] + } + } + UnivariantPolynomial::new(polynomial_product_coefficients) + } +} + +impl Add for UnivariantPolynomial { + type Output = Self; + + fn add(self, other: Self) -> Self { + let result = if self.degree() >= other.degree() { + let mut result_coff = Vec::new(); + + for i in 0..self.coefficients.len() { + result_coff + .push(self.coefficients[i] + other.coefficients.get(i).unwrap_or(&F::zero())); + } + + UnivariantPolynomial::from_coefficients_vec(result_coff) + } else { + let mut result_coff = Vec::new(); + + for i in 0..other.coefficients.len() { + result_coff + .push(other.coefficients[i] + self.coefficients.get(i).unwrap_or(&F::zero())); + } + + UnivariantPolynomial::from_coefficients_vec(result_coff) + }; + + result + } +} diff --git a/polynomial/src/univariate_polynomial/univariate.rs b/polynomial/src/univariate_polynomial/univariate.rs new file mode 100644 index 0000000..98c4cea --- /dev/null +++ b/polynomial/src/univariate_polynomial/univariate.rs @@ -0,0 +1,331 @@ +use crate::interface::UnivariatePolynomialTrait; +use crate::util::lagrange_basis; +use ark_ff::{PrimeField, BigInteger}; +use std::{ + fmt::{Display, Formatter, Result}, + ops::{Add, Mul}, +}; + +#[derive(Clone, PartialEq, Eq, Hash, Default, Debug)] +pub struct UnivariateMonomial { + pub coeff: F, + pub pow: F, +} +#[derive(Clone, PartialEq, Eq, Hash, Default, Debug)] +pub struct UnivariatePolynomial { + pub monomial: Vec>, +} + +impl UnivariatePolynomialTrait for UnivariatePolynomial { + fn new(data: Vec) -> Self { + let mut monomial: Vec> = Vec::new(); + + for n in (0..data.len()).step_by(2) { + if n < data.len() - 1 { + let monomial_value: UnivariateMonomial = + UnivariateMonomial { coeff: data[n], pow: data[n + 1] }; + monomial.push(monomial_value); + } else if n == data.len() - 1 { + let monomial_value: UnivariateMonomial = + UnivariateMonomial { coeff: data[n], pow: F::zero() }; + monomial.push(monomial_value); + } + } + + UnivariatePolynomial { monomial } + } + + fn zero() -> Self { + Self { monomial: vec![] } + } + fn evaluate(&self, point: F) -> F { + let mut point_evaluation: F = F::from(0_u8); + for n in self.monomial.iter() { + let coefficient = n.coeff; + let n_pow: ::BigInt = n.pow.into(); + let power = point.pow(&n_pow); + + let evaluation = coefficient * power; + point_evaluation += evaluation; + } + + point_evaluation + } + + fn interpolate(points: &[(F, F)]) -> UnivariatePolynomial { + let mut result: Vec = vec![F::zero(); points.len()]; + + for (i, &(_, y_i)) in points.iter().enumerate() { + let l_i: Vec = lagrange_basis(points, i); + let l_i: Vec = l_i.into_iter().map(|coeff| coeff * y_i).collect(); + + for (k, &coeff) in l_i.iter().enumerate() { + result[k] += coeff; + } + } + + let monomial: Vec> = result + .into_iter() + .enumerate() + .filter(|&(_, coeff)| coeff != F::zero()) + .map(|(pow, coeff)| UnivariateMonomial { coeff, pow: F::from(pow as u64) }) + .collect(); + + UnivariatePolynomial { monomial } + } + + fn degree(&self) -> F { + let mut highest_degree: F = F::from(0_u8); + for m in self.monomial.iter() { + if m.pow > highest_degree { + highest_degree = m.pow; + } + } + + highest_degree.try_into().unwrap() + } + + fn to_bytes(&self) -> Vec { + let mut bytes = Vec::new(); + for p in self.monomial.iter() { + bytes.extend_from_slice(&p.coeff.into_bigint().to_bytes_be()); + bytes.extend_from_slice(&p.pow.into_bigint().to_bytes_be()); + } + bytes + } + +} + +impl Mul for UnivariatePolynomial { + type Output = Self; + fn mul(self, rhs: Self) -> Self { + let mut result_monomial: Vec> = Vec::new(); + + for lhs_mn in &self.monomial { + for rhs_mn in &rhs.monomial { + let new_coeff = lhs_mn.coeff * rhs_mn.coeff; + let new_pow = lhs_mn.pow + rhs_mn.pow; + + let mut found_like_terms = false; + for res_mn in &mut result_monomial { + if res_mn.pow == new_pow { + res_mn.coeff += new_coeff; + found_like_terms = true; + break; + } + } + + if !found_like_terms { + result_monomial.push(UnivariateMonomial { coeff: new_coeff, pow: new_pow }); + } + } + } + + UnivariatePolynomial { monomial: result_monomial } + } +} + +impl Add for UnivariatePolynomial { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + let mut result_monomials = Vec::new(); + let mut lhs_iter = self.monomial.into_iter(); + let mut rhs_iter = rhs.monomial.into_iter(); + let mut lhs_mn = lhs_iter.next(); + let mut rhs_mn = rhs_iter.next(); + + while lhs_mn.is_some() || rhs_mn.is_some() { + match (lhs_mn.clone(), rhs_mn.clone()) { + (Some(l), Some(r)) => { + if l.pow == r.pow { + result_monomials + .push(UnivariateMonomial { coeff: l.coeff + r.coeff, pow: l.pow }); + lhs_mn = lhs_iter.next(); + rhs_mn = rhs_iter.next(); + } else if l.pow < r.pow { + result_monomials.push(l); + lhs_mn = lhs_iter.next(); + } else { + result_monomials.push(r); + rhs_mn = rhs_iter.next(); + } + }, + (Some(l), None) => { + result_monomials.push(l); + lhs_mn = lhs_iter.next(); + }, + (None, Some(r)) => { + result_monomials.push(r); + rhs_mn = rhs_iter.next(); + }, + (None, None) => break, + } + } + + UnivariatePolynomial { monomial: result_monomials } + } +} + +impl Display for UnivariatePolynomial { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + for (index, mn) in self.monomial.iter().enumerate() { + if index == 0 { + write!(f, "{}", mn.coeff)?; + } else { + if mn.pow == F::from(0_u8) || mn.coeff == F::from(0_u8) { + write!(f, " + {}", mn.coeff)?; + } else if mn.pow == F::from(1_u8) { + write!(f, " + {}x", mn.coeff)?; + } else { + write!(f, " + {}x^{}", mn.coeff, mn.pow)?; + } + } + } + Ok(()) + } +} + +mod tests { + use super::*; + use ark_ff::MontConfig; + use ark_ff::{Fp64, MontBackend}; + + #[derive(MontConfig)] + #[modulus = "17"] + #[generator = "3"] + struct FqConfig; + type Fq = Fp64>; + + #[test] + fn test_polynomial_evaluation() { + let data = vec![ + Fq::from(5_u8), + Fq::from(0_u8), + Fq::from(2_u8), + Fq::from(1_u8), + Fq::from(4_u8), + Fq::from(6_u8), + ]; + let polynomial = UnivariatePolynomial::new(data); + let evaluation = polynomial.evaluate(Fq::from(2_u8)); + + assert_eq!(evaluation, Fq::from(10_u8)); + } + + #[test] + fn test_polynomial_addition() { + let data = vec![Fq::from(5_u8), Fq::from(0_u8)]; + let data2 = vec![Fq::from(2_u8), Fq::from(1_u8)]; + + + let polynomial1 = UnivariatePolynomial::new(data); + let polynomial2 = UnivariatePolynomial::new(data2); + + assert_eq!( + polynomial1 + polynomial2, + UnivariatePolynomial::new(vec![ + Fq::from(5_u8), + Fq::from(0_u8), + Fq::from(2_u8), + Fq::from(1_u8), + ]) + ); + + let data3 = vec![Fq::from(5_u8), Fq::from(0_u8), Fq::from(5_u8), Fq::from(2_u8)]; + let data4 = vec![Fq::from(2_u8), Fq::from(1_u8), Fq::from(2_u8), Fq::from(2_u8)]; + let polynomial1 = UnivariatePolynomial::new(data3); + let polynomial2 = UnivariatePolynomial::new(data4); + + assert_eq!( + polynomial1 + polynomial2, + UnivariatePolynomial::new(vec![ + Fq::from(5_u8), + Fq::from(0_u8), + Fq::from(2_u8), + Fq::from(1_u8), + Fq::from(7_u8), + Fq::from(2_u8), + ]) + ); + } + + #[test] + fn test_polynomial_multiplication() { + let data = vec![Fq::from(5_u8), Fq::from(0_u8)]; + let data2 = vec![Fq::from(2_u8), Fq::from(1_u8)]; + + let polynomial1 = UnivariatePolynomial::new(data); + let polynomial2 = UnivariatePolynomial::new(data2); + + assert_eq!( + polynomial1 + polynomial2, + UnivariatePolynomial::new(vec![ + Fq::from(5_u8), + Fq::from(0_u8), + Fq::from(2_u8), + Fq::from(1_u8), + ]) + ); + + let data3 = vec![ + Fq::from(5_u8), + Fq::from(0_u8), + Fq::from(2_u8), + Fq::from(1_u8), + Fq::from(4_u8), + Fq::from(6_u8), + ]; + let data4 = + vec![Fq::from(4), Fq::from(0), Fq::from(3), Fq::from(2), Fq::from(4), Fq::from(5)]; + + let polynomial3 = UnivariatePolynomial::new(data3); + let polynomial4 = UnivariatePolynomial::new(data4); + + assert_eq!( + polynomial3 * polynomial4, + UnivariatePolynomial::new(vec![ + Fq::from(3_u8), + Fq::from(0_u8), + Fq::from(15_u8), + Fq::from(2_u8), + Fq::from(3_u8), + Fq::from(5_u8), + Fq::from(8_u8), + Fq::from(1_u8), + Fq::from(6_u8), + Fq::from(3_u8), + Fq::from(7_u8), + Fq::from(6_u8), + Fq::from(12_u8), + Fq::from(8_u8), + Fq::from(16_u8), + Fq::from(11_u8), + ]) + ); + } + + #[test] + fn test_polynomial_interpolate() { + let interpolation = UnivariatePolynomial::interpolate(&[ + (Fq::from(1), Fq::from(2)), + (Fq::from(2), Fq::from(3)), + (Fq::from(4), Fq::from(11)), + ]); + + let interpolation_check = UnivariatePolynomial::new(vec![ + Fq::from(3_u8), + Fq::from(0_u8), + Fq::from(15_u8), + Fq::from(1_u8), + Fq::from(1_u8), + Fq::from(2_u8), + ]); + assert_eq!(interpolation, interpolation_check); + + // to test the evaluation of the polynomial + let evaluation = interpolation.evaluate(Fq::from(2_u8)); + assert_eq!(evaluation, Fq::from(3_u8)); + } + +} diff --git a/polynomial/src/util.rs b/polynomial/src/util.rs index 2f3a090..ad0d10f 100644 --- a/polynomial/src/util.rs +++ b/polynomial/src/util.rs @@ -1,5 +1,7 @@ use ark_ff::PrimeField; +use crate::univariate_polynomial::{interface::UnivariantPolynomialInterface, univariant_coefficient::UnivariantPolynomial, univariate::UnivariateMonomial}; + pub fn lagrange_basis(points: &[(F, F)], i: usize) -> Vec { let mut l_i = vec![F::one()]; @@ -22,4 +24,23 @@ pub fn lagrange_basis(points: &[(F, F)], i: usize) -> Vec { l_i.into_iter() .map(|coeff| coeff * denom.inverse().unwrap()) .collect() +} + + +pub fn lbasis(points: &Vec, y_s:&Vec) -> Vec>{ + let mut basis = Vec::new(); + assert!(points.len() == y_s.len(), "Length of points and y_s should be the same"); + for i in 0..points.len(){ + let mut basis_element = UnivariantPolynomial::new(vec![F::one()]); + for j in 0..points.len(){ + if i == j{ + continue; + } + let numerator = UnivariantPolynomial::from_coefficients_vec(vec![-points[j], F::one()]); + let denominator = points[i] - points[j]; + basis_element = basis_element * (numerator * UnivariantPolynomial::from_coefficients_vec(vec![denominator.inverse().unwrap()]) ) + } + basis.push(basis_element * UnivariantPolynomial::from_coefficients_vec(vec![y_s[i]])) + } + basis } \ No newline at end of file diff --git a/sum-check/src/composedsumcheck.rs b/sum-check/src/composedsumcheck.rs index ba8fa2c..673bb88 100644 --- a/sum-check/src/composedsumcheck.rs +++ b/sum-check/src/composedsumcheck.rs @@ -6,7 +6,7 @@ use polynomial::composed::multilinear::ComposedMultiLinearPolynomial; use polynomial::interface::UnivariatePolynomialTrait; use polynomial::multilinear::evaluation_form::MultiLinearPolynomialEvaluationForm; use polynomial::multilinear::interface::MultiLinearPolynomialEvaluationFormTrait; -use polynomial::UnivariatePolynomial; +use polynomial::univariate_polynomial::univariate::UnivariatePolynomial; use transcript::transcription::Transcript; use crate::interface::ComposedSumCheckInterface; diff --git a/sum-check/src/multi_composedsumcheck.rs b/sum-check/src/multi_composedsumcheck.rs index 46d278d..1a1e96f 100644 --- a/sum-check/src/multi_composedsumcheck.rs +++ b/sum-check/src/multi_composedsumcheck.rs @@ -5,7 +5,7 @@ use polynomial::composed::interface::ComposedMultilinearInterface; use polynomial::composed::multilinear::ComposedMultiLinearPolynomial; use polynomial::interface::UnivariatePolynomialTrait; use transcript::transcription::Transcript; -use polynomial::UnivariatePolynomial; +use polynomial::univariate_polynomial::univariate::UnivariatePolynomial; // use polynomial::multilinear::evaluation_form::MultiLinearPolynomialEvaluationForm; @@ -299,11 +299,11 @@ mod tests { let lhs_poly = ComposedMultiLinearPolynomial::new(vec![ add_i.partial_evaluation(&Fq::from(2), &0), - w_b.add_distinct(&w_c), + w_b.cartesian_add(&w_c), ]); let rhs_poly = ComposedMultiLinearPolynomial::new(vec![ mul_i.partial_evaluation(&Fq::from(2), &0), - w_b.mul_distinct(&w_c), + w_b.cartesian_mul(&w_c), ]); let multi_composed = vec![lhs_poly, rhs_poly];