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