diff --git a/constraint-solver/src/grouped_expression.rs b/constraint-solver/src/grouped_expression.rs index e7c290777c..7d70eec1f3 100644 --- a/constraint-solver/src/grouped_expression.rs +++ b/constraint-solver/src/grouped_expression.rs @@ -57,7 +57,12 @@ impl, V> GroupedExpression Zero for GroupedExpression { +impl Zero for GroupedExpression +where + // The bounds are so strict because Zero requires Add + T: Zero + PartialEq + Neg + AddAssign + Clone, + V: Clone + Ord + Eq, +{ fn zero() -> Self { Self { quadratic: Default::default(), @@ -67,11 +72,16 @@ impl Zero for GroupedExpression { } fn is_zero(&self) -> bool { - self.try_to_known().is_some_and(|k| k.is_known_zero()) + self.try_to_known().is_some_and(|k| k.is_zero()) } } -impl One for GroupedExpression { +impl One for GroupedExpression +where + // The bounds are so strict because One requise Mul + T: Zero + One + PartialEq + Neg + AddAssign + MulAssign + Clone, + V: Clone + Ord + Eq, +{ fn one() -> Self { Self { quadratic: Default::default(), @@ -81,7 +91,7 @@ impl One for GroupedExpression { } fn is_one(&self) -> bool { - self.try_to_known().is_some_and(|k| k.is_known_one()) + self.try_to_known().is_some_and(|k| k.is_one()) } } @@ -91,7 +101,7 @@ impl GroupedExpression GroupedExpression { +impl GroupedExpression { pub fn from_runtime_constant(constant: T) -> Self { Self { quadratic: Default::default(), @@ -99,15 +109,19 @@ impl GroupedExpression { constant, } } +} +impl GroupedExpression { pub fn from_unknown_variable(var: V) -> Self { Self { quadratic: Default::default(), - linear: [(var.clone(), T::one())].into_iter().collect(), + linear: [(var, T::one())].into_iter().collect(), constant: T::zero(), } } +} +impl GroupedExpression { /// If this expression does not contain unknown variables, returns the symbolic expression. pub fn try_to_known(&self) -> Option<&T> { if self.quadratic.is_empty() && self.linear.is_empty() { @@ -122,33 +136,37 @@ impl GroupedExpression { !self.is_quadratic() } + /// Returns true if this expression contains at least one quadratic term. + pub fn is_quadratic(&self) -> bool { + !self.quadratic.is_empty() + } +} + +impl GroupedExpression { /// If the expression is a known number, returns it. pub fn try_to_number(&self) -> Option { self.try_to_known()?.try_to_number() } +} +impl GroupedExpression { /// If the expression is equal to `GroupedExpression::from_unknown_variable(v)`, returns `v`. pub fn try_to_simple_unknown(&self) -> Option { - if self.is_quadratic() || !self.constant.is_known_zero() { + if self.is_quadratic() || !self.constant.is_zero() { return None; } let Ok((var, coeff)) = self.linear.iter().exactly_one() else { return None; }; - if !coeff.is_known_one() { + if !coeff.is_one() { return None; } Some(var.clone()) } - /// Returns true if this expression contains at least one quadratic term. - pub fn is_quadratic(&self) -> bool { - !self.quadratic.is_empty() - } - /// Returns `(l, r)` if `self == l * r`. pub fn try_as_single_product(&self) -> Option<(&Self, &Self)> { - if self.linear.is_empty() && self.constant.is_known_zero() { + if self.linear.is_empty() && self.constant.is_zero() { match self.quadratic.as_slice() { [(l, r)] => Some((l, r)), _ => None, @@ -157,7 +175,9 @@ impl GroupedExpression { None } } +} +impl GroupedExpression { /// Returns `vec![f1, f2, ..., fn]` such that `self` is equivalent to /// `c * f1 * f2 * ... * fn` for some constant `c`. /// Tries to find as many factors as possible and also tries to normalize @@ -195,7 +215,9 @@ impl GroupedExpression { vec![self.clone() * T::one().field_div(÷_by)] } } +} +impl GroupedExpression { /// Returns the quadratic, linear and constant components of this expression. pub fn components( &self, @@ -242,7 +264,9 @@ impl GroupedExpression { assert!(!self.is_quadratic()); self.linear.get(var) } +} +impl GroupedExpression { /// Returns the range constraint of the full expression. pub fn range_constraint( &self, @@ -440,7 +464,11 @@ impl RangeConstraintProvider for NoRangeConstraints { } } -impl Add for GroupedExpression { +impl Add for GroupedExpression +where + T: Zero + PartialEq + Neg + AddAssign + Clone, + V: Clone + Ord + Eq, +{ type Output = GroupedExpression; fn add(mut self, rhs: Self) -> Self { @@ -449,7 +477,11 @@ impl Add for GroupedExpression { } } -impl Add for &GroupedExpression { +impl Add for &GroupedExpression +where + T: Zero + PartialEq + Neg + AddAssign + Clone, + V: Clone + Ord + Eq, +{ type Output = GroupedExpression; fn add(self, rhs: Self) -> Self::Output { @@ -457,8 +489,10 @@ impl Add for &GroupedExpression { } } -impl AddAssign> - for GroupedExpression +impl AddAssign> for GroupedExpression +where + T: Zero + PartialEq + Neg + AddAssign + Clone, + V: Clone + Ord + Eq, { fn add_assign(&mut self, rhs: Self) { self.quadratic = combine_removing_zeros(std::mem::take(&mut self.quadratic), rhs.quadratic); @@ -469,7 +503,7 @@ impl AddAssign> .or_insert_with(|| coeff); } self.constant += rhs.constant.clone(); - self.linear.retain(|_, f| !f.is_known_zero()); + self.linear.retain(|_, f| !f.is_zero()); } } @@ -550,7 +584,11 @@ where [n1, n2].contains(&(&first.0, &first.1)) || [n1, n2].contains(&(&first.1, &first.0)) } -impl Sub for &GroupedExpression { +impl Sub for &GroupedExpression +where + T: Zero + PartialEq + Neg + AddAssign + Clone, + V: Clone + Ord + Eq, +{ type Output = GroupedExpression; fn sub(self, rhs: Self) -> Self::Output { @@ -558,7 +596,11 @@ impl Sub for &GroupedExpression { } } -impl Sub for GroupedExpression { +impl Sub for GroupedExpression +where + T: Zero + PartialEq + Neg + AddAssign + Clone, + V: Clone + Ord + Eq, +{ type Output = GroupedExpression; fn sub(self, rhs: Self) -> Self::Output { @@ -566,7 +608,7 @@ impl Sub for GroupedExpression { } } -impl GroupedExpression { +impl + Clone, V: Clone + Ord> GroupedExpression { fn negate(&mut self) { for (first, _) in &mut self.quadratic { first.negate() @@ -578,7 +620,7 @@ impl GroupedExpression { } } -impl Neg for GroupedExpression { +impl + Clone, V: Clone + Ord> Neg for GroupedExpression { type Output = GroupedExpression; fn neg(mut self) -> Self { @@ -587,7 +629,7 @@ impl Neg for GroupedExpression { } } -impl Neg for &GroupedExpression { +impl + Clone, V: Clone + Ord> Neg for &GroupedExpression { type Output = GroupedExpression; fn neg(self) -> Self::Output { @@ -596,7 +638,11 @@ impl Neg for &GroupedExpression { } /// Multiply by known symbolic expression. -impl Mul<&T> for GroupedExpression { +impl Mul<&T> for GroupedExpression +where + T: Zero + PartialEq + Neg + AddAssign + MulAssign + Clone, + V: Clone + Ord + Eq, +{ type Output = GroupedExpression; fn mul(mut self, rhs: &T) -> Self { @@ -605,7 +651,11 @@ impl Mul<&T> for GroupedExpression Mul for GroupedExpression { +impl Mul for GroupedExpression +where + T: Zero + PartialEq + Neg + AddAssign + MulAssign + Clone, + V: Clone + Ord + Eq, +{ type Output = GroupedExpression; fn mul(self, rhs: T) -> Self { @@ -613,9 +663,13 @@ impl Mul for GroupedExpression } } -impl MulAssign<&T> for GroupedExpression { +impl MulAssign<&T> for GroupedExpression +where + T: Zero + PartialEq + Neg + AddAssign + MulAssign + Clone, + V: Clone + Ord + Eq, +{ fn mul_assign(&mut self, rhs: &T) { - if rhs.is_known_zero() { + if rhs.is_zero() { *self = Self::zero(); } else { for (first, _) in &mut self.quadratic { @@ -629,7 +683,11 @@ impl MulAssign<&T> for GroupedExpressio } } -impl Sum for GroupedExpression { +impl Sum for GroupedExpression +where + T: Zero + PartialEq + Neg + AddAssign + Clone, + V: Clone + Ord + Eq, +{ fn sum>(iter: I) -> Self { iter.fold(Self::zero(), |mut acc, item| { acc += item; @@ -638,7 +696,11 @@ impl Sum for GroupedExpression { } } -impl Mul for GroupedExpression { +impl Mul for GroupedExpression +where + T: Zero + PartialEq + Neg + AddAssign + MulAssign + Clone, + V: Clone + Ord + Eq, +{ type Output = GroupedExpression; fn mul(self, rhs: GroupedExpression) -> Self {