/ circuit / types / boolean / src / or.rs
or.rs
  1  // Copyright (c) 2019-2025 Alpha-Delta Network Inc.
  2  // This file is part of the alphavm 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  
 16  use super::*;
 17  
 18  impl<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  
 27  impl<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  
 36  impl<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  
 45  impl<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  
 56  impl<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)]
 64  impl<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));
 99  
100                  output
101              }
102      }
103  }
104  
105  #[cfg(test)]
106  mod tests {
107      use super::*;
108      use alphavm_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  }