From 3d324bb8d7642c9017d0cc8c00cd44f8a0336fbe Mon Sep 17 00:00:00 2001 From: Andreas Fackler Date: Mon, 8 Oct 2018 16:58:54 +0200 Subject: [PATCH] Optimize polynomial interpolation in the curve. Slightly reduce the number of multiplication and division operations in the scalar field. --- src/lib.rs | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7e24d0c..c2269fb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -596,27 +596,40 @@ where { let samples: Vec<_> = items .into_iter() + .take(t) .map(|(i, sample)| (into_fr_plus_1(i), sample)) .collect(); if samples.len() < t { return Err(Error::NotEnoughShares); } + + // Compute the products `x_prod[i]` of all but the `i`-th entry. + let mut x_prod: Vec = Vec::with_capacity(t); + let mut tmp = C::Scalar::one(); + x_prod.push(tmp); + for (x, _) in samples.iter().take(t - 1) { + tmp.mul_assign(x); + x_prod.push(tmp); + } + tmp = C::Scalar::one(); + let mut i = t - 2; + for (x, _) in samples[1..].iter().rev() { + tmp.mul_assign(x); + x_prod[i].mul_assign(&tmp); + i -= 1; + } + let mut result = C::zero(); - let mut indexes = Vec::new(); - for (x, sample) in samples.iter().take(t) { - if indexes.contains(x) { - return Err(Error::DuplicateEntry); - } - indexes.push(x.clone()); + for (mut l0, (x, sample)) in x_prod.into_iter().zip(&samples) { // Compute the value at 0 of the Lagrange polynomial that is `0` at the other data // points but `1` at `x`. - let mut l0 = C::Scalar::one(); - for (x0, _) in samples.iter().take(t).filter(|(x0, _)| x0 != x) { - let mut denom = *x0; - denom.sub_assign(x); - l0.mul_assign(x0); - l0.mul_assign(&denom.inverse().expect("indices are different")); + let mut denom = C::Scalar::one(); + for (x0, _) in samples.iter().filter(|(x0, _)| x0 != x) { + let mut diff = *x0; + diff.sub_assign(x); + denom.mul_assign(&diff); } + l0.mul_assign(&denom.inverse().ok_or(Error::DuplicateEntry)?); result.add_assign(&sample.into_affine().mul(l0)); } Ok(result)