Skip to content

Commit

Permalink
Merge pull request #2182 from ljedrz/perf/vec_in_lc
Browse files Browse the repository at this point in the history
Use a Vec for terms in LinearCombination (circuit)
  • Loading branch information
howardwu authored Nov 24, 2023
2 parents c620cc4 + a15fb28 commit 9cf0c07
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 27 deletions.
2 changes: 1 addition & 1 deletion circuit/algorithms/src/elligator2/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl<E: Environment> Elligator2<E> {
debug_assert!(console::Group::<E::Network>::EDWARDS_D.legendre().is_qnr());

// Ensure the input is nonzero.
E::assert_neq(input, &Field::<E>::zero());
E::assert_neq(input, Field::<E>::zero());

// Define `1` as a constant.
let one = Field::one();
Expand Down
44 changes: 20 additions & 24 deletions circuit/environment/src/helpers/linear_combination.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use core::{
fmt,
ops::{Add, AddAssign, Mul, Neg, Sub},
};
use indexmap::{map::Entry, IndexMap};

// Before high level program operations are converted into constraints, they are first tracked as linear combinations.
// Each linear combination corresponds to a portion or all of a single row of an R1CS matrix, and consists of:
Expand All @@ -34,7 +33,8 @@ use indexmap::{map::Entry, IndexMap};
#[derive(Clone)]
pub struct LinearCombination<F: PrimeField> {
constant: F,
terms: IndexMap<Variable<F>, F>,
/// The list of terms is kept sorted in order to speed up lookups.
terms: Vec<(Variable<F>, F)>,
/// The value of this linear combination, defined as the sum of the `terms` and `constant`.
value: F,
}
Expand All @@ -60,7 +60,7 @@ impl<F: PrimeField> LinearCombination<F> {
pub fn is_public(&self) -> bool {
self.constant.is_zero()
&& self.terms.len() == 1
&& match self.terms.iter().next() {
&& match self.terms.first() {
Some((Variable::Public(..), coefficient)) => *coefficient == F::one(),
_ => false,
}
Expand Down Expand Up @@ -130,7 +130,7 @@ impl<F: PrimeField> LinearCombination<F> {
}

/// Returns the terms (excluding the constant value) in the linear combination.
pub(super) fn to_terms(&self) -> &IndexMap<Variable<F>, F> {
pub(super) fn to_terms(&self) -> &[(Variable<F>, F)] {
&self.terms
}

Expand Down Expand Up @@ -197,18 +197,18 @@ impl<F: PrimeField> From<&[Variable<F>]> for LinearCombination<F> {
match variable.is_constant() {
true => output.constant += variable.value(),
false => {
match output.terms.entry(variable.clone()) {
Entry::Occupied(mut entry) => {
match output.terms.binary_search_by(|(v, _)| v.cmp(variable)) {
Ok(idx) => {
// Increment the existing coefficient by 1.
*entry.get_mut() += F::one();
output.terms[idx].1 += F::one();
// If the coefficient of the term is now zero, remove the entry.
if entry.get().is_zero() {
entry.remove_entry();
if output.terms[idx].1.is_zero() {
output.terms.remove(idx);
}
}
Entry::Vacant(entry) => {
Err(idx) => {
// Insert the variable and a coefficient of 1 as a new term.
entry.insert(F::one());
output.terms.insert(idx, (variable.clone(), F::one()));
}
}
}
Expand Down Expand Up @@ -336,18 +336,18 @@ impl<F: PrimeField> AddAssign<&LinearCombination<F>> for LinearCombination<F> {
match variable.is_constant() {
true => panic!("Malformed linear combination found"),
false => {
match self.terms.entry(variable.clone()) {
Entry::Occupied(mut entry) => {
match self.terms.binary_search_by(|(v, _)| v.cmp(variable)) {
Ok(idx) => {
// Add the coefficient to the existing coefficient for this term.
*entry.get_mut() += *coefficient;
self.terms[idx].1 += *coefficient;
// If the coefficient of the term is now zero, remove the entry.
if entry.get().is_zero() {
entry.remove_entry();
if self.terms[idx].1.is_zero() {
self.terms.remove(idx);
}
}
Entry::Vacant(entry) => {
Err(idx) => {
// Insert the variable and coefficient as a new term.
entry.insert(*coefficient);
self.terms.insert(idx, (variable.clone(), *coefficient));
}
}
}
Expand Down Expand Up @@ -467,11 +467,7 @@ impl<F: PrimeField> fmt::Debug for LinearCombination<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let mut output = format!("Constant({})", self.constant);

// Sort the terms.
let mut terms = self.terms.clone();
terms.sort_keys();

for (variable, coefficient) in &terms {
for (variable, coefficient) in &self.terms {
output += &match (variable.mode(), coefficient.is_one()) {
(Mode::Constant, _) => panic!("Malformed linear combination at: ({coefficient} * {variable:?})"),
(_, true) => format!(" + {variable:?}"),
Expand Down Expand Up @@ -559,7 +555,7 @@ mod tests {
assert_eq!(zero, candidate.constant);
assert_eq!(1, candidate.terms.len());

let (candidate_variable, candidate_coefficient) = candidate.terms.iter().next().unwrap();
let (candidate_variable, candidate_coefficient) = candidate.terms.first().unwrap();
assert!(candidate_variable.is_public());
assert_eq!(one, candidate_variable.value());
assert_eq!(four, *candidate_coefficient);
Expand Down
2 changes: 1 addition & 1 deletion circuit/types/integers/src/mul_checked.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ impl<E: Environment, I: IntegerType> Integer<E, I> {
Boolean::assert_bits_are_zero(&z_1_upper_bits);

// Check that `z2` is zero.
E::assert_eq(&z2, E::zero());
E::assert_eq(z2, E::zero());

// Return the product of `self` and `other`.
product
Expand Down
2 changes: 1 addition & 1 deletion synthesizer/process/src/trace/inclusion/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ impl<N: Network> InclusionAssignment<N> {
let candidate_serial_number =
circuit::Record::<A, circuit::Plaintext<A>>::serial_number_from_gamma(&gamma, commitment.clone());
// Enforce that the candidate serial number is equal to the serial number.
A::assert_eq(&candidate_serial_number, &serial_number);
A::assert_eq(candidate_serial_number, serial_number);

// Enforce the starting leaf is the claimed commitment.
A::assert_eq(state_path.transition_leaf().id(), commitment);
Expand Down

0 comments on commit 9cf0c07

Please sign in to comment.