// Copyright (c) 2023 Espresso Systems (espressosys.com) // This file is part of the HyperPlonk library. // You should have received a copy of the MIT License // along with the HyperPlonk library. If not, see . //! Useful utilities for KZG PCS use ark_ff::PrimeField; use ark_poly::DenseMultilinearExtension; use ark_std::{end_timer, start_timer, vec::Vec}; use crate::PCSError; /// Generate eq(t,x), a product of multilinear polynomials with fixed t. /// eq(a,b) is takes extensions of a,b in {0,1}^num_vars such that if a and b in /// {0,1}^num_vars are equal then this polynomial evaluates to 1. pub(crate) fn eq_extension(t: &[F]) -> Vec> { let start = start_timer!(|| "eq extension"); let dim = t.len(); let mut result = Vec::new(); for (i, &ti) in t.iter().enumerate().take(dim) { let mut poly = Vec::with_capacity(1 << dim); for x in 0..(1 << dim) { let xi = if x >> i & 1 == 1 { F::one() } else { F::zero() }; let ti_xi = ti * xi; poly.push(ti_xi + ti_xi - xi - ti + F::one()); } result.push(DenseMultilinearExtension::from_evaluations_vec(dim, poly)); } end_timer!(start); result } /// Evaluate eq polynomial. use the public one later pub(crate) fn eq_eval(x: &[F], y: &[F]) -> Result { if x.len() != y.len() { return Err(PCSError::InvalidParameters( "x and y have different length".to_string(), )); } let start = start_timer!(|| "eq_eval"); let mut res = F::one(); for (&xi, &yi) in x.iter().zip(y.iter()) { let xi_yi = xi * yi; res *= xi_yi + xi_yi - xi - yi + F::one(); } end_timer!(start); Ok(res) }