@@ -69,6 +69,53 @@ pub fn add<E: Engine, CS: ConstraintSystem<E>>(
69
69
Ok ( res)
70
70
}
71
71
72
+ pub fn sub < E : Engine , CS : ConstraintSystem < E > > (
73
+ mut cs : CS ,
74
+ a : & num:: AllocatedNum < E > ,
75
+ b : & num:: AllocatedNum < E > ,
76
+ ) -> Result < num:: AllocatedNum < E > , SynthesisError > {
77
+ let res = num:: AllocatedNum :: alloc ( cs. namespace ( || "sub_num" ) , || {
78
+ let mut tmp = a
79
+ . get_value ( )
80
+ . ok_or_else ( || SynthesisError :: AssignmentMissing ) ?;
81
+ tmp. sub_assign (
82
+ & b. get_value ( )
83
+ . ok_or_else ( || SynthesisError :: AssignmentMissing ) ?,
84
+ ) ;
85
+
86
+ Ok ( tmp)
87
+ } ) ?;
88
+
89
+ // a - b = res
90
+ difference ( & mut cs, || "subtraction constraint" , & a, & b, & res) ;
91
+
92
+ Ok ( res)
93
+ }
94
+
95
+ /// Adds a constraint to CS, enforcing a difference relationship between the allocated numbers a, b, and difference.
96
+ ///
97
+ /// a - b = difference
98
+ pub fn difference < E : Engine , A , AR , CS : ConstraintSystem < E > > (
99
+ cs : & mut CS ,
100
+ annotation : A ,
101
+ a : & num:: AllocatedNum < E > ,
102
+ b : & num:: AllocatedNum < E > ,
103
+ difference : & num:: AllocatedNum < E > ,
104
+ ) where
105
+ A : FnOnce ( ) -> AR ,
106
+ AR : Into < String > ,
107
+ {
108
+ // difference = a-b
109
+ // => difference + b = a
110
+ // => (difference + b) * 1 = a
111
+ cs. enforce (
112
+ annotation,
113
+ |lc| lc + difference. get_variable ( ) + b. get_variable ( ) ,
114
+ |lc| lc + CS :: one ( ) ,
115
+ |lc| lc + a. get_variable ( ) ,
116
+ ) ;
117
+ }
118
+
72
119
#[ cfg( test) ]
73
120
mod tests {
74
121
use super :: * ;
@@ -95,4 +142,24 @@ mod tests {
95
142
assert ! ( cs. is_satisfied( ) ) ;
96
143
}
97
144
}
145
+
146
+ #[ test]
147
+ fn sub_constraint ( ) {
148
+ let rng = & mut XorShiftRng :: from_seed ( [ 0x3dbe6259 , 0x8d313d76 , 0x3237db17 , 0xe5bc0654 ] ) ;
149
+
150
+ for _ in 0 ..100 {
151
+ let mut cs = TestConstraintSystem :: < Bls12 > :: new ( ) ;
152
+
153
+ let a = num:: AllocatedNum :: alloc ( cs. namespace ( || "a" ) , || Ok ( rng. gen ( ) ) ) . unwrap ( ) ;
154
+ let b = num:: AllocatedNum :: alloc ( cs. namespace ( || "b" ) , || Ok ( rng. gen ( ) ) ) . unwrap ( ) ;
155
+
156
+ let res = sub ( cs. namespace ( || "a-b" ) , & a, & b) . expect ( "subtraction failed" ) ;
157
+
158
+ let mut tmp = a. get_value ( ) . unwrap ( ) . clone ( ) ;
159
+ tmp. sub_assign ( & b. get_value ( ) . unwrap ( ) ) ;
160
+
161
+ assert_eq ! ( res. get_value( ) . unwrap( ) , tmp) ;
162
+ assert ! ( cs. is_satisfied( ) ) ;
163
+ }
164
+ }
98
165
}
0 commit comments