From c979e5fcb50a4bf60377a701bc01335ec9dba39e Mon Sep 17 00:00:00 2001 From: radik878 Date: Sun, 21 Sep 2025 21:57:38 +0300 Subject: [PATCH 1/2] fix: LinearCombination::get_var_loc linear-search to return Ok on equality --- relations/src/utils/linear_combination.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/relations/src/utils/linear_combination.rs b/relations/src/utils/linear_combination.rs index 793bad7bc..24812faa7 100644 --- a/relations/src/utils/linear_combination.rs +++ b/relations/src/utils/linear_combination.rs @@ -48,7 +48,8 @@ impl LinearCombination { Self::new() } - /// Deduplicate entries in `self` by combining coefficients of identical variables. + /// Deduplicate entries in `self` by combining coefficients of identical + /// variables. #[inline] pub fn compactify(&mut self) { // For 0 or 1 element, there is nothing to do. @@ -93,7 +94,8 @@ impl LinearCombination { lc } - /// Create a new linear combination from the sum of many (coefficient, variable) pairs. + /// Create a new linear combination from the sum of many (coefficient, + /// variable) pairs. #[inline] pub fn from_sum_coeff_vars(terms: &[(F, Variable)]) -> Self { let mut lc = LinearCombination(terms.to_vec()); @@ -169,20 +171,19 @@ impl LinearCombination { /// Get the location of a variable in `self`. /// /// # Errors - /// If the variable is not found, returns the index where it would be inserted. + /// If the variable is not found, returns the index where it would be + /// inserted. #[inline] pub fn get_var_loc(&self, search_var: &Variable) -> Result { if self.0.len() < 6 { - let mut found_index = 0; - for (i, (_, var)) in self.iter().enumerate() { - if var >= search_var { - found_index = i; - break; - } else { - found_index += 1; + for (i, &(_, var)) in self.iter().enumerate() { + if var == *search_var { + return Ok(i); + } else if var > *search_var { + return Err(i); } } - Err(found_index) + return Err(self.0.len()); } else { self.0 .binary_search_by_key(search_var, |&(_, cur_var)| cur_var) From 908d78f58fd06a6f3ea948d98ab0ed142a0a152c Mon Sep 17 00:00:00 2001 From: radik878 Date: Tue, 23 Sep 2025 23:46:17 +0300 Subject: [PATCH 2/2] add a test case --- relations/src/utils/linear_combination.rs | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/relations/src/utils/linear_combination.rs b/relations/src/utils/linear_combination.rs index 24812faa7..850c17080 100644 --- a/relations/src/utils/linear_combination.rs +++ b/relations/src/utils/linear_combination.rs @@ -599,3 +599,31 @@ impl Sub<(F, LinearCombination)> for LinearCombination { self + (-coeff, other) } } + +#[cfg(test)] +mod tests { + use super::LinearCombination; + use crate::utils::variable::Variable; + use ark_test_curves::bls12_381::Fr; + + #[test] + fn add_assign_merges_on_equality_small_vec_singleton() { + // Start with a length-1 LC so the small-vector linear search branch is used. + let v = Variable::witness(5); + let mut lc: LinearCombination = LinearCombination::from((Fr::from(3u64), v)); + // Adding the same variable should merge coefficients, not insert a duplicate. + lc += (Fr::from(2u64), v); + + assert_eq!( + lc.len(), + 1, + "should not create a duplicate entry for the same variable" + ); + assert_eq!(lc[0].1, v, "variable should remain the same entry"); + assert_eq!( + lc[0].0, + Fr::from(5u64), + "coefficients should sum when variables are equal" + ); + } +}