1use super::*;
17
18impl<E: Environment> BitXor<Boolean<E>> for Boolean<E> {
19 type Output = Boolean<E>;
20
21 fn bitxor(self, other: Boolean<E>) -> Self::Output {
23 self ^ &other
24 }
25}
26
27impl<E: Environment> BitXor<Boolean<E>> for &Boolean<E> {
28 type Output = Boolean<E>;
29
30 fn bitxor(self, other: Boolean<E>) -> Self::Output {
32 self ^ &other
33 }
34}
35
36impl<E: Environment> BitXor<&Boolean<E>> for Boolean<E> {
37 type Output = Boolean<E>;
38
39 fn bitxor(self, other: &Boolean<E>) -> Self::Output {
41 &self ^ other
42 }
43}
44
45impl<E: Environment> BitXor<&Boolean<E>> for &Boolean<E> {
46 type Output = Boolean<E>;
47
48 fn bitxor(self, other: &Boolean<E>) -> Self::Output {
50 let mut output = self.clone();
51 output ^= other;
52 output
53 }
54}
55
56impl<E: Environment> BitXorAssign<Boolean<E>> for Boolean<E> {
57 fn bitxor_assign(&mut self, other: Boolean<E>) {
59 *self ^= &other;
60 }
61}
62
63impl<E: Environment> BitXorAssign<&Boolean<E>> for Boolean<E> {
64 fn bitxor_assign(&mut self, other: &Boolean<E>) {
66 *self =
68 if self.is_constant() {
70 match self.eject_value() {
71 true => !other.clone(),
72 false => other.clone(),
73 }
74 }
75 else if other.is_constant() {
77 match other.eject_value() {
78 true => !self.clone(),
79 false => self.clone(),
80 }
81 }
82 else {
84 let output = Boolean(
88 E::new_variable(Mode::Private, match self.eject_value() ^ other.eject_value() {
89 true => E::BaseField::one(),
90 false => E::BaseField::zero(),
91 })
92 .into(),
93 );
94
95 E::enforce(|| ((&self.0 + &self.0), other, (&self.0 + &other.0 - &output.0)));
116
117 output
118 }
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125 use snarkvm_circuit_environment::Circuit;
126
127 fn check_xor(
128 name: &str,
129 expected: bool,
130 a: Boolean<Circuit>,
131 b: Boolean<Circuit>,
132 num_constants: u64,
133 num_public: u64,
134 num_private: u64,
135 num_constraints: u64,
136 ) {
137 Circuit::scope(name, || {
138 let candidate = &a ^ &b;
139 assert_eq!(expected, candidate.eject_value(), "({} != {})", a.eject_value(), b.eject_value());
140 assert_scope!(num_constants, num_public, num_private, num_constraints);
141 });
142 }
143
144 #[test]
145 fn test_constant_xor_constant() {
146 let expected = false;
148 let a = Boolean::<Circuit>::new(Mode::Constant, false);
149 let b = Boolean::<Circuit>::new(Mode::Constant, false);
150 check_xor("false != false", expected, a, b, 0, 0, 0, 0);
151
152 let expected = true;
154 let a = Boolean::<Circuit>::new(Mode::Constant, false);
155 let b = Boolean::<Circuit>::new(Mode::Constant, true);
156 check_xor("false != true", expected, a, b, 0, 0, 0, 0);
157
158 let expected = true;
160 let a = Boolean::<Circuit>::new(Mode::Constant, true);
161 let b = Boolean::<Circuit>::new(Mode::Constant, false);
162 check_xor("true != false", expected, a, b, 0, 0, 0, 0);
163
164 let expected = false;
166 let a = Boolean::<Circuit>::new(Mode::Constant, true);
167 let b = Boolean::<Circuit>::new(Mode::Constant, true);
168 check_xor("true != true", expected, a, b, 0, 0, 0, 0);
169 }
170
171 #[test]
172 fn test_constant_xor_public() {
173 let expected = false;
175 let a = Boolean::<Circuit>::new(Mode::Constant, false);
176 let b = Boolean::<Circuit>::new(Mode::Public, false);
177 check_xor("false != false", expected, a, b, 0, 0, 0, 0);
178
179 let expected = true;
181 let a = Boolean::<Circuit>::new(Mode::Constant, false);
182 let b = Boolean::<Circuit>::new(Mode::Public, true);
183 check_xor("false != true", expected, a, b, 0, 0, 0, 0);
184
185 let expected = true;
187 let a = Boolean::<Circuit>::new(Mode::Constant, true);
188 let b = Boolean::<Circuit>::new(Mode::Public, false);
189 check_xor("true != false", expected, a, b, 0, 0, 0, 0);
190
191 let expected = false;
193 let a = Boolean::<Circuit>::new(Mode::Constant, true);
194 let b = Boolean::<Circuit>::new(Mode::Public, true);
195 check_xor("true != true", expected, a, b, 0, 0, 0, 0);
196 }
197
198 #[test]
199 fn test_constant_xor_private() {
200 let expected = false;
202 let a = Boolean::<Circuit>::new(Mode::Constant, false);
203 let b = Boolean::<Circuit>::new(Mode::Private, false);
204 check_xor("false != false", expected, a, b, 0, 0, 0, 0);
205
206 let expected = true;
208 let a = Boolean::<Circuit>::new(Mode::Constant, false);
209 let b = Boolean::<Circuit>::new(Mode::Private, true);
210 check_xor("false != true", expected, a, b, 0, 0, 0, 0);
211
212 let expected = true;
214 let a = Boolean::<Circuit>::new(Mode::Constant, true);
215 let b = Boolean::<Circuit>::new(Mode::Private, false);
216 check_xor("true != false", expected, a, b, 0, 0, 0, 0);
217
218 let expected = false;
220 let a = Boolean::<Circuit>::new(Mode::Constant, true);
221 let b = Boolean::<Circuit>::new(Mode::Private, true);
222 check_xor("true != true", expected, a, b, 0, 0, 0, 0);
223 }
224
225 #[test]
226 fn test_public_xor_constant() {
227 let expected = false;
229 let a = Boolean::<Circuit>::new(Mode::Public, false);
230 let b = Boolean::<Circuit>::new(Mode::Constant, false);
231 check_xor("false != false", expected, a, b, 0, 0, 0, 0);
232
233 let expected = true;
235 let a = Boolean::<Circuit>::new(Mode::Public, false);
236 let b = Boolean::<Circuit>::new(Mode::Constant, true);
237 check_xor("false != true", expected, a, b, 0, 0, 0, 0);
238
239 let expected = true;
241 let a = Boolean::<Circuit>::new(Mode::Public, true);
242 let b = Boolean::<Circuit>::new(Mode::Constant, false);
243 check_xor("true != false", expected, a, b, 0, 0, 0, 0);
244
245 let expected = false;
247 let a = Boolean::<Circuit>::new(Mode::Public, true);
248 let b = Boolean::<Circuit>::new(Mode::Constant, true);
249 check_xor("true != true", expected, a, b, 0, 0, 0, 0);
250 }
251
252 #[test]
253 fn test_public_xor_public() {
254 let expected = false;
256 let a = Boolean::<Circuit>::new(Mode::Public, false);
257 let b = Boolean::<Circuit>::new(Mode::Public, false);
258 check_xor("false != false", expected, a, b, 0, 0, 1, 1);
259
260 let expected = true;
262 let a = Boolean::<Circuit>::new(Mode::Public, false);
263 let b = Boolean::<Circuit>::new(Mode::Public, true);
264 check_xor("false != true", expected, a, b, 0, 0, 1, 1);
265
266 let expected = true;
268 let a = Boolean::<Circuit>::new(Mode::Public, true);
269 let b = Boolean::<Circuit>::new(Mode::Public, false);
270 check_xor("true != false", expected, a, b, 0, 0, 1, 1);
271
272 let expected = false;
274 let a = Boolean::<Circuit>::new(Mode::Public, true);
275 let b = Boolean::<Circuit>::new(Mode::Public, true);
276 check_xor("true != true", expected, a, b, 0, 0, 1, 1);
277 }
278
279 #[test]
280 fn test_public_xor_private() {
281 let expected = false;
283 let a = Boolean::<Circuit>::new(Mode::Public, false);
284 let b = Boolean::<Circuit>::new(Mode::Private, false);
285 check_xor("false != false", expected, a, b, 0, 0, 1, 1);
286
287 let expected = true;
289 let a = Boolean::<Circuit>::new(Mode::Public, false);
290 let b = Boolean::<Circuit>::new(Mode::Private, true);
291 check_xor("false != true", expected, a, b, 0, 0, 1, 1);
292
293 let expected = true;
295 let a = Boolean::<Circuit>::new(Mode::Public, true);
296 let b = Boolean::<Circuit>::new(Mode::Private, false);
297 check_xor("true != false", expected, a, b, 0, 0, 1, 1);
298
299 let expected = false;
301 let a = Boolean::<Circuit>::new(Mode::Public, true);
302 let b = Boolean::<Circuit>::new(Mode::Private, true);
303 check_xor("true != true", expected, a, b, 0, 0, 1, 1);
304 }
305
306 #[test]
307 fn test_private_xor_constant() {
308 let expected = false;
310 let a = Boolean::<Circuit>::new(Mode::Private, false);
311 let b = Boolean::<Circuit>::new(Mode::Constant, false);
312 check_xor("false != false", expected, a, b, 0, 0, 0, 0);
313
314 let expected = true;
316 let a = Boolean::<Circuit>::new(Mode::Private, false);
317 let b = Boolean::<Circuit>::new(Mode::Constant, true);
318 check_xor("false != true", expected, a, b, 0, 0, 0, 0);
319
320 let expected = true;
322 let a = Boolean::<Circuit>::new(Mode::Private, true);
323 let b = Boolean::<Circuit>::new(Mode::Constant, false);
324 check_xor("true != false", expected, a, b, 0, 0, 0, 0);
325
326 let expected = false;
328 let a = Boolean::<Circuit>::new(Mode::Private, true);
329 let b = Boolean::<Circuit>::new(Mode::Constant, true);
330 check_xor("true != true", expected, a, b, 0, 0, 0, 0);
331 }
332
333 #[test]
334 fn test_private_xor_public() {
335 let expected = false;
337 let a = Boolean::<Circuit>::new(Mode::Private, false);
338 let b = Boolean::<Circuit>::new(Mode::Public, false);
339 check_xor("false != false", expected, a, b, 0, 0, 1, 1);
340
341 let expected = true;
343 let a = Boolean::<Circuit>::new(Mode::Private, false);
344 let b = Boolean::<Circuit>::new(Mode::Public, true);
345 check_xor("false != true", expected, a, b, 0, 0, 1, 1);
346
347 let expected = true;
349 let a = Boolean::<Circuit>::new(Mode::Private, true);
350 let b = Boolean::<Circuit>::new(Mode::Public, false);
351 check_xor("true != false", expected, a, b, 0, 0, 1, 1);
352
353 let expected = false;
355 let a = Boolean::<Circuit>::new(Mode::Private, true);
356 let b = Boolean::<Circuit>::new(Mode::Public, true);
357 check_xor("true != true", expected, a, b, 0, 0, 1, 1);
358 }
359
360 #[test]
361 fn test_private_xor_private() {
362 let expected = false;
364 let a = Boolean::<Circuit>::new(Mode::Private, false);
365 let b = Boolean::<Circuit>::new(Mode::Private, false);
366 check_xor("false != false", expected, a, b, 0, 0, 1, 1);
367
368 let expected = true;
370 let a = Boolean::<Circuit>::new(Mode::Private, false);
371 let b = Boolean::<Circuit>::new(Mode::Private, true);
372 check_xor("false != true", expected, a, b, 0, 0, 1, 1);
373
374 let expected = true;
376 let a = Boolean::<Circuit>::new(Mode::Private, true);
377 let b = Boolean::<Circuit>::new(Mode::Private, false);
378 check_xor("true != false", expected, a, b, 0, 0, 1, 1);
379
380 let expected = false;
382 let a = Boolean::<Circuit>::new(Mode::Private, true);
383 let b = Boolean::<Circuit>::new(Mode::Private, true);
384 check_xor("true != true", expected, a, b, 0, 0, 1, 1);
385 }
386}