Skip to main content

snarkvm_circuit_types_boolean/
or.rs

1// Copyright (c) 2019-2026 Provable Inc.
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use super::*;
17
18impl<E: Environment> BitOr<Boolean<E>> for Boolean<E> {
19    type Output = Boolean<E>;
20
21    /// Returns `(self OR other)`.
22    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    /// Returns `(self OR other)`.
31    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    /// Returns `(self OR other)`.
40    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    /// Returns `(self OR other)`.
49    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    /// Sets `self` as `(self OR other)`.
58    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    /// Sets `self` as `(self OR other)`.
66    fn bitor_assign(&mut self, other: &Boolean<E>) {
67        // Stores the bitwise OR of `self` and `other` in `self`.
68        *self =
69            // Constant `self`
70            if self.is_constant() {
71                match self.eject_value() {
72                    true => self.clone(),
73                    false => other.clone(),
74                }
75            }
76            // Constant `other`
77            else if other.is_constant() {
78                match other.eject_value() {
79                    true => other.clone(),
80                    false => self.clone(),
81                }
82            }
83            // Variable OR Variable
84            else {
85                // Declare a new variable with the expected output as witness.
86                // Note: The constraint below will ensure `output` is either 0 or 1,
87                // assuming `self` and `other` are well-formed (they are either 0 or 1).
88                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                // Ensure (1 - `self`) * (1 - `other`) = (1 - `output`)
97                // `output` is `1` iff `self` OR `other` is `1`.
98                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        // false OR false
130        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        // false OR true
136        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        // true OR false
142        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        // true OR true
148        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        // false OR false
157        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        // false OR true
163        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        // true OR false
169        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        // true OR true
175        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        // false OR false
184        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        // false OR true
190        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        // true OR false
196        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        // true OR true
202        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        // false OR false
211        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        // false OR true
217        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        // true OR false
223        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        // true OR true
229        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        // false OR false
238        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        // false OR true
244        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        // true OR false
250        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        // true OR true
256        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        // false OR false
265        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        // false OR true
271        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        // true OR false
277        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        // true OR true
283        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        // false OR false
292        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        // false OR true
298        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        // true OR false
304        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        // true OR true
310        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        // false OR false
319        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        // false OR true
325        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        // true OR false
331        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        // true OR true
337        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        // false OR false
346        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        // false OR true
352        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        // true OR false
358        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        // true OR true
364        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}