Skip to content

Commit

Permalink
Kimchi/LagrangeBasisEvaluations: optimize evaluate_boolean
Browse files Browse the repository at this point in the history
  • Loading branch information
dannywillems committed Sep 4, 2024
1 parent bb51597 commit e54a4a2
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 8 deletions.
25 changes: 19 additions & 6 deletions kimchi/src/lagrange_basis_evaluations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,21 +102,34 @@ impl<F: FftField> LagrangeBasisEvaluations<F> {
/// polynomial at a point, assuming that the given evaluations are either `0`
/// or `1` at every point of the domain.
///
/// A slight optimisation is performed here, where we only use addition on
/// integers (usize) instead of the addition on field elements. We convert
/// only at the end into a field element.
///
/// This method can particularly be useful when the polynomials represent
/// (boolean) selectors in a circuit.
pub fn evaluate_boolean<D: EvaluationDomain<F>>(&self, p: &Evaluations<F, D>) -> Vec<F> {
///
/// # Safety
///
/// There is no check on the input, i.e. we do not verify the assumptions
/// that all evaluation points are `1` or `0`.
///
/// There is also an additional assumption that the number of evaluation
/// points is not greater than 2^64 - 1 (i.e. the machine word size on
/// 64bits machine).
pub unsafe fn evaluate_boolean<D: EvaluationDomain<F>>(&self, p: &Evaluations<F, D>) -> Vec<F> {
assert_eq!(p.evals.len() % self.domain_size(), 0);
let stride = p.evals.len() / self.domain_size();
self.evals
.iter()
.map(|evals| {
let mut result = F::zero();
for (i, e) in evals.iter().enumerate() {
let mut result: usize = 0;
for (i, _e) in evals.iter().enumerate() {
if !p.evals[stride * i].is_zero() {
result += e;
result += 1;
}
}
result
F::from(result as u64)
})
.collect()
}
Expand Down Expand Up @@ -341,7 +354,7 @@ mod tests {

let evaluator = LagrangeBasisEvaluations::new(domain.size(), domain, x);

let y = evaluator.evaluate_boolean(&evals);
let y = unsafe { evaluator.evaluate_boolean(&evals) };
let expected = vec![evals.interpolate().evaluate(&x)];
assert_eq!(y, expected)
}
Expand Down
4 changes: 2 additions & 2 deletions kimchi/src/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -962,8 +962,8 @@ where

let chunked_evals_for_selector =
|p: &Evaluations<G::ScalarField, D<G::ScalarField>>| PointEvaluations {
zeta: zeta_evals.evaluate_boolean(p),
zeta_omega: zeta_omega_evals.evaluate_boolean(p),
zeta: unsafe { zeta_evals.evaluate_boolean(p) },
zeta_omega: unsafe { zeta_omega_evals.evaluate_boolean(p) },
};

let chunked_evals_for_evaluations =
Expand Down

0 comments on commit e54a4a2

Please sign in to comment.