mirror of
https://github.com/arnaucube/ark-r1cs-std.git
synced 2026-01-08 15:01:29 +01:00
Avoid deeply nested lc in EvaluationsVar::interpolate_and_evaluate
This commit is contained in:
@@ -158,11 +158,13 @@ impl<F: PrimeField> EvaluationsVar<F> {
|
||||
.as_ref()
|
||||
.expect("lagrange interpolator has not been initialized. ");
|
||||
let lagrange_coeffs = self.compute_lagrange_coefficients(interpolation_point)?;
|
||||
let mut interpolation: FpVar<F> = FpVar::zero();
|
||||
for i in 0..lagrange_interpolator.domain_order {
|
||||
let intermediate = &lagrange_coeffs[i] * &self.evals[i];
|
||||
interpolation += &intermediate
|
||||
}
|
||||
|
||||
let interpolation = lagrange_coeffs
|
||||
.iter()
|
||||
.zip(&self.evals)
|
||||
.take(lagrange_interpolator.domain_order)
|
||||
.map(|(coeff, eval)| coeff * eval)
|
||||
.sum::<FpVar<F>>();
|
||||
|
||||
Ok(interpolation)
|
||||
}
|
||||
@@ -208,11 +210,11 @@ impl<F: PrimeField> EvaluationsVar<F> {
|
||||
let alpha_coset_offset_inv =
|
||||
interpolation_point.mul_by_inverse_unchecked(&self.domain.offset())?;
|
||||
|
||||
// `res` stores the sum of all lagrange polynomials evaluated at alpha
|
||||
let mut res = FpVar::<F>::zero();
|
||||
|
||||
let domain_size = self.domain.size() as usize;
|
||||
for i in 0..domain_size {
|
||||
|
||||
// `evals` stores all lagrange polynomials evaluated at alpha
|
||||
let evals = (0..domain_size)
|
||||
.map(|i| {
|
||||
// a'^{-1} where a is the base coset element
|
||||
let subgroup_point_inv = subgroup_points[(domain_size - i) % domain_size];
|
||||
debug_assert_eq!(subgroup_points[i] * subgroup_point_inv, F::one());
|
||||
@@ -230,9 +232,11 @@ impl<F: PrimeField> EvaluationsVar<F> {
|
||||
// in the coset.
|
||||
let lag_coeff = lhs.mul_by_inverse_unchecked(&lag_denom)?;
|
||||
|
||||
let lag_interpoland = &self.evals[i] * lag_coeff;
|
||||
res += lag_interpoland
|
||||
}
|
||||
Ok(&self.evals[i] * lag_coeff)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let res = evals.iter().sum();
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
@@ -378,19 +382,16 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_interpolate_constant_offset() {
|
||||
for n in [11, 12, 13, 14] {
|
||||
let mut rng = test_rng();
|
||||
let poly = DensePolynomial::rand(15, &mut rng);
|
||||
let gen = Fr::get_root_of_unity(1 << 4).unwrap();
|
||||
assert_eq!(gen.pow(&[1 << 4]), Fr::one());
|
||||
let domain = Radix2DomainVar::new(
|
||||
gen,
|
||||
4, // 2^4 = 16
|
||||
FpVar::constant(Fr::rand(&mut rng)),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let poly = DensePolynomial::rand((1 << n) - 1, &mut rng);
|
||||
let gen = Fr::get_root_of_unity(1 << n).unwrap();
|
||||
assert_eq!(gen.pow(&[1 << n]), Fr::one());
|
||||
let domain = Radix2DomainVar::new(gen, n, FpVar::constant(Fr::rand(&mut rng))).unwrap();
|
||||
let mut coset_point = domain.offset().value().unwrap();
|
||||
let mut oracle_evals = Vec::new();
|
||||
for _ in 0..(1 << 4) {
|
||||
for _ in 0..(1 << n) {
|
||||
oracle_evals.push(poly.evaluate(&coset_point));
|
||||
coset_point *= gen;
|
||||
}
|
||||
@@ -415,25 +416,27 @@ mod tests {
|
||||
|
||||
assert_eq!(actual, expected);
|
||||
assert!(cs.is_satisfied().unwrap());
|
||||
println!("number of constraints: {}", cs.num_constraints())
|
||||
println!("number of constraints: {}", cs.num_constraints());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_interpolate_non_constant_offset() {
|
||||
for n in [11, 12, 13, 14] {
|
||||
let mut rng = test_rng();
|
||||
let poly = DensePolynomial::rand(15, &mut rng);
|
||||
let gen = Fr::get_root_of_unity(1 << 4).unwrap();
|
||||
assert_eq!(gen.pow(&[1 << 4]), Fr::one());
|
||||
let poly = DensePolynomial::rand((1 << n) - 1, &mut rng);
|
||||
let gen = Fr::get_root_of_unity(1 << n).unwrap();
|
||||
assert_eq!(gen.pow(&[1 << n]), Fr::one());
|
||||
let cs = ConstraintSystem::new_ref();
|
||||
let domain = Radix2DomainVar::new(
|
||||
gen,
|
||||
4, // 2^4 = 16
|
||||
n,
|
||||
FpVar::new_witness(ns!(cs, "offset"), || Ok(Fr::rand(&mut rng))).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let mut coset_point = domain.offset().value().unwrap();
|
||||
let mut oracle_evals = Vec::new();
|
||||
for _ in 0..(1 << 4) {
|
||||
for _ in 0..(1 << n) {
|
||||
oracle_evals.push(poly.evaluate(&coset_point));
|
||||
coset_point *= gen;
|
||||
}
|
||||
@@ -458,7 +461,8 @@ mod tests {
|
||||
|
||||
assert_eq!(actual, expected);
|
||||
assert!(cs.is_satisfied().unwrap());
|
||||
println!("number of constraints: {}", cs.num_constraints())
|
||||
println!("number of constraints: {}", cs.num_constraints());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user