1use super::*;
17
18impl<E: Environment> BitOr<Boolean<E>> for Boolean<E> {
19 type Output = Boolean<E>;
20
21 fn bitor(self, other: Boolean<E>) -> Self::Output {
23 self | &other
24 }
25}
26
27impl<E: Environment> BitOr<Boolean<E>> for &Boolean<E> {
28 type Output = Boolean<E>;
29
30 fn bitor(self, other: Boolean<E>) -> Self::Output {
32 self | &other
33 }
34}
35
36impl<E: Environment> BitOr<&Boolean<E>> for Boolean<E> {
37 type Output = Boolean<E>;
38
39 fn bitor(self, other: &Boolean<E>) -> Self::Output {
41 &self | other
42 }
43}
44
45impl<E: Environment> BitOr<&Boolean<E>> for &Boolean<E> {
46 type Output = Boolean<E>;
47
48 fn bitor(self, other: &Boolean<E>) -> Self::Output {
50 let mut output = self.clone();
51 output |= other;
52 output
53 }
54}
55
56impl<E: Environment> BitOrAssign<Boolean<E>> for Boolean<E> {
57 fn bitor_assign(&mut self, other: Boolean<E>) {
59 *self |= &other;
60 }
61}
62
63#[allow(clippy::suspicious_op_assign_impl)]
64impl<E: Environment> BitOrAssign<&Boolean<E>> for Boolean<E> {
65 fn bitor_assign(&mut self, other: &Boolean<E>) {
67 *self =
69 if self.is_constant() {
71 match self.eject_value() {
72 true => self.clone(),
73 false => other.clone(),
74 }
75 }
76 else if other.is_constant() {
78 match other.eject_value() {
79 true => other.clone(),
80 false => self.clone(),
81 }
82 }
83 else {
85 let output = Boolean(
89 E::new_variable(Mode::Private, match self.eject_value() | other.eject_value() {
90 true => E::BaseField::one(),
91 false => E::BaseField::zero(),
92 })
93 .into(),
94 );
95
96 E::enforce(|| (E::one() - &self.0, E::one() - &other.0, E::one() - &output.0)).expect("Boolean OR constraint unsatisfied");
99
100 output
101 }
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108 use snarkvm_circuit_environment::Circuit;
109
110 fn check_or(
111 name: &str,
112 expected: bool,
113 a: Boolean<Circuit>,
114 b: Boolean<Circuit>,
115 num_constants: u64,
116 num_public: u64,
117 num_private: u64,
118 num_constraints: u64,
119 ) {
120 Circuit::scope(name, || {
121 let candidate = &a | &b;
122 assert_eq!(expected, candidate.eject_value(), "({} OR {})", a.eject_value(), b.eject_value());
123 assert_scope!(num_constants, num_public, num_private, num_constraints);
124 });
125 }
126
127 #[test]
128 fn test_constant_or_constant() {
129 let expected = false;
131 let a = Boolean::<Circuit>::new(Mode::Constant, false);
132 let b = Boolean::<Circuit>::new(Mode::Constant, false);
133 check_or("false OR false", expected, a, b, 0, 0, 0, 0);
134
135 let expected = true;
137 let a = Boolean::<Circuit>::new(Mode::Constant, false);
138 let b = Boolean::<Circuit>::new(Mode::Constant, true);
139 check_or("false OR true", expected, a, b, 0, 0, 0, 0);
140
141 let expected = true;
143 let a = Boolean::<Circuit>::new(Mode::Constant, true);
144 let b = Boolean::<Circuit>::new(Mode::Constant, false);
145 check_or("true OR false", expected, a, b, 0, 0, 0, 0);
146
147 let expected = true;
149 let a = Boolean::<Circuit>::new(Mode::Constant, true);
150 let b = Boolean::<Circuit>::new(Mode::Constant, true);
151 check_or("true OR true", expected, a, b, 0, 0, 0, 0);
152 }
153
154 #[test]
155 fn test_constant_or_public() {
156 let expected = false;
158 let a = Boolean::<Circuit>::new(Mode::Constant, false);
159 let b = Boolean::<Circuit>::new(Mode::Public, false);
160 check_or("false OR false", expected, a, b, 0, 0, 0, 0);
161
162 let expected = true;
164 let a = Boolean::<Circuit>::new(Mode::Constant, false);
165 let b = Boolean::<Circuit>::new(Mode::Public, true);
166 check_or("false OR true", expected, a, b, 0, 0, 0, 0);
167
168 let expected = true;
170 let a = Boolean::<Circuit>::new(Mode::Constant, true);
171 let b = Boolean::<Circuit>::new(Mode::Public, false);
172 check_or("true OR false", expected, a, b, 0, 0, 0, 0);
173
174 let expected = true;
176 let a = Boolean::<Circuit>::new(Mode::Constant, true);
177 let b = Boolean::<Circuit>::new(Mode::Public, true);
178 check_or("true OR true", expected, a, b, 0, 0, 0, 0);
179 }
180
181 #[test]
182 fn test_constant_or_private() {
183 let expected = false;
185 let a = Boolean::<Circuit>::new(Mode::Constant, false);
186 let b = Boolean::<Circuit>::new(Mode::Private, false);
187 check_or("false OR false", expected, a, b, 0, 0, 0, 0);
188
189 let expected = true;
191 let a = Boolean::<Circuit>::new(Mode::Constant, false);
192 let b = Boolean::<Circuit>::new(Mode::Private, true);
193 check_or("false OR true", expected, a, b, 0, 0, 0, 0);
194
195 let expected = true;
197 let a = Boolean::<Circuit>::new(Mode::Constant, true);
198 let b = Boolean::<Circuit>::new(Mode::Private, false);
199 check_or("true OR false", expected, a, b, 0, 0, 0, 0);
200
201 let expected = true;
203 let a = Boolean::<Circuit>::new(Mode::Constant, true);
204 let b = Boolean::<Circuit>::new(Mode::Private, true);
205 check_or("true OR true", expected, a, b, 0, 0, 0, 0);
206 }
207
208 #[test]
209 fn test_public_or_constant() {
210 let expected = false;
212 let a = Boolean::<Circuit>::new(Mode::Public, false);
213 let b = Boolean::<Circuit>::new(Mode::Constant, false);
214 check_or("false OR false", expected, a, b, 0, 0, 0, 0);
215
216 let expected = true;
218 let a = Boolean::<Circuit>::new(Mode::Public, false);
219 let b = Boolean::<Circuit>::new(Mode::Constant, true);
220 check_or("false OR true", expected, a, b, 0, 0, 0, 0);
221
222 let expected = true;
224 let a = Boolean::<Circuit>::new(Mode::Public, true);
225 let b = Boolean::<Circuit>::new(Mode::Constant, false);
226 check_or("true OR false", expected, a, b, 0, 0, 0, 0);
227
228 let expected = true;
230 let a = Boolean::<Circuit>::new(Mode::Public, true);
231 let b = Boolean::<Circuit>::new(Mode::Constant, true);
232 check_or("true OR true", expected, a, b, 0, 0, 0, 0);
233 }
234
235 #[test]
236 fn test_public_or_public() {
237 let expected = false;
239 let a = Boolean::<Circuit>::new(Mode::Public, false);
240 let b = Boolean::<Circuit>::new(Mode::Public, false);
241 check_or("false OR false", expected, a, b, 0, 0, 1, 1);
242
243 let expected = true;
245 let a = Boolean::<Circuit>::new(Mode::Public, false);
246 let b = Boolean::<Circuit>::new(Mode::Public, true);
247 check_or("false OR true", expected, a, b, 0, 0, 1, 1);
248
249 let expected = true;
251 let a = Boolean::<Circuit>::new(Mode::Public, true);
252 let b = Boolean::<Circuit>::new(Mode::Public, false);
253 check_or("true OR false", expected, a, b, 0, 0, 1, 1);
254
255 let expected = true;
257 let a = Boolean::<Circuit>::new(Mode::Public, true);
258 let b = Boolean::<Circuit>::new(Mode::Public, true);
259 check_or("true OR true", expected, a, b, 0, 0, 1, 1);
260 }
261
262 #[test]
263 fn test_public_or_private() {
264 let expected = false;
266 let a = Boolean::<Circuit>::new(Mode::Public, false);
267 let b = Boolean::<Circuit>::new(Mode::Private, false);
268 check_or("false OR false", expected, a, b, 0, 0, 1, 1);
269
270 let expected = true;
272 let a = Boolean::<Circuit>::new(Mode::Public, false);
273 let b = Boolean::<Circuit>::new(Mode::Private, true);
274 check_or("false OR true", expected, a, b, 0, 0, 1, 1);
275
276 let expected = true;
278 let a = Boolean::<Circuit>::new(Mode::Public, true);
279 let b = Boolean::<Circuit>::new(Mode::Private, false);
280 check_or("true OR false", expected, a, b, 0, 0, 1, 1);
281
282 let expected = true;
284 let a = Boolean::<Circuit>::new(Mode::Public, true);
285 let b = Boolean::<Circuit>::new(Mode::Private, true);
286 check_or("true OR true", expected, a, b, 0, 0, 1, 1);
287 }
288
289 #[test]
290 fn test_private_or_constant() {
291 let expected = false;
293 let a = Boolean::<Circuit>::new(Mode::Private, false);
294 let b = Boolean::<Circuit>::new(Mode::Constant, false);
295 check_or("false OR false", expected, a, b, 0, 0, 0, 0);
296
297 let expected = true;
299 let a = Boolean::<Circuit>::new(Mode::Private, false);
300 let b = Boolean::<Circuit>::new(Mode::Constant, true);
301 check_or("false OR true", expected, a, b, 0, 0, 0, 0);
302
303 let expected = true;
305 let a = Boolean::<Circuit>::new(Mode::Private, true);
306 let b = Boolean::<Circuit>::new(Mode::Constant, false);
307 check_or("true OR false", expected, a, b, 0, 0, 0, 0);
308
309 let expected = true;
311 let a = Boolean::<Circuit>::new(Mode::Private, true);
312 let b = Boolean::<Circuit>::new(Mode::Constant, true);
313 check_or("true OR true", expected, a, b, 0, 0, 0, 0);
314 }
315
316 #[test]
317 fn test_private_or_public() {
318 let expected = false;
320 let a = Boolean::<Circuit>::new(Mode::Private, false);
321 let b = Boolean::<Circuit>::new(Mode::Public, false);
322 check_or("false OR false", expected, a, b, 0, 0, 1, 1);
323
324 let expected = true;
326 let a = Boolean::<Circuit>::new(Mode::Private, false);
327 let b = Boolean::<Circuit>::new(Mode::Public, true);
328 check_or("false OR true", expected, a, b, 0, 0, 1, 1);
329
330 let expected = true;
332 let a = Boolean::<Circuit>::new(Mode::Private, true);
333 let b = Boolean::<Circuit>::new(Mode::Public, false);
334 check_or("true OR false", expected, a, b, 0, 0, 1, 1);
335
336 let expected = true;
338 let a = Boolean::<Circuit>::new(Mode::Private, true);
339 let b = Boolean::<Circuit>::new(Mode::Public, true);
340 check_or("true OR true", expected, a, b, 0, 0, 1, 1);
341 }
342
343 #[test]
344 fn test_private_or_private() {
345 let expected = false;
347 let a = Boolean::<Circuit>::new(Mode::Private, false);
348 let b = Boolean::<Circuit>::new(Mode::Private, false);
349 check_or("false OR false", expected, a, b, 0, 0, 1, 1);
350
351 let expected = true;
353 let a = Boolean::<Circuit>::new(Mode::Private, false);
354 let b = Boolean::<Circuit>::new(Mode::Private, true);
355 check_or("false OR true", expected, a, b, 0, 0, 1, 1);
356
357 let expected = true;
359 let a = Boolean::<Circuit>::new(Mode::Private, true);
360 let b = Boolean::<Circuit>::new(Mode::Private, false);
361 check_or("true OR false", expected, a, b, 0, 0, 1, 1);
362
363 let expected = true;
365 let a = Boolean::<Circuit>::new(Mode::Private, true);
366 let b = Boolean::<Circuit>::new(Mode::Private, true);
367 check_or("true OR true", expected, a, b, 0, 0, 1, 1);
368 }
369}