bellpepper_core/util_cs/
mod.rs1use crate::LinearCombination;
2use ff::PrimeField;
3
4pub mod test_cs;
5
6pub type Constraint<Scalar> = (
7 LinearCombination<Scalar>,
8 LinearCombination<Scalar>,
9 LinearCombination<Scalar>,
10 String,
11);
12
13pub trait Comparable<Scalar: PrimeField> {
14 fn num_inputs(&self) -> usize;
34 fn num_constraints(&self) -> usize;
35 fn inputs(&self) -> Vec<String>;
36 fn aux(&self) -> Vec<String>;
37 fn constraints(&self) -> &[Constraint<Scalar>];
38
39 fn delta<C: Comparable<Scalar>>(&self, other: &C, ignore_counts: bool) -> Delta<Scalar>
40 where
41 Scalar: PrimeField,
42 {
43 let input_count_matches = self.num_inputs() == other.num_inputs();
44 let constraint_count_matches = self.num_constraints() == other.num_constraints();
45
46 let inputs_match = self.inputs() == other.inputs();
47 let constraints_match = self.constraints() == other.constraints();
48
49 let equal =
50 input_count_matches && constraint_count_matches && inputs_match && constraints_match;
51
52 if !ignore_counts && !input_count_matches {
53 Delta::InputCountMismatch(self.num_inputs(), other.num_inputs())
54 } else if !ignore_counts && !constraint_count_matches {
55 Delta::ConstraintCountMismatch(self.num_constraints(), other.num_constraints())
56 } else if !constraints_match {
57 let c = self.constraints();
58 let o = other.constraints();
59
60 let mismatch = c
61 .iter()
62 .zip(o)
63 .enumerate()
64 .filter(|(_, (a, b))| a != b)
65 .map(|(i, (a, b))| (i, a, b))
66 .next();
67
68 let m = mismatch.unwrap();
69
70 Delta::ConstraintMismatch(m.0, m.1.clone(), m.2.clone())
71 } else if equal {
72 Delta::Equal
73 } else {
74 Delta::Different
75 }
76 }
77}
78
79#[allow(clippy::large_enum_variant)]
80#[derive(Clone, Debug, PartialEq)]
81pub enum Delta<Scalar: PrimeField> {
82 Equal,
83 Different,
84 InputCountMismatch(usize, usize),
85 ConstraintCountMismatch(usize, usize),
86 ConstraintMismatch(usize, Constraint<Scalar>, Constraint<Scalar>),
87}