/ circuit / types / boolean / src / nand.rs
nand.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> Nand<Self> for Boolean<E> {
 19      type Output = Boolean<E>;
 20  
 21      /// Returns `NOT (a AND b)`.
 22      fn nand(&self, other: &Self) -> Self::Output {
 23          // Constant `self`
 24          if self.is_constant() {
 25              match self.eject_value() {
 26                  true => !other.clone(),
 27                  false => !self.clone(),
 28              }
 29          }
 30          // Constant `other`
 31          else if other.is_constant() {
 32              match other.eject_value() {
 33                  true => !self.clone(),
 34                  false => !other.clone(),
 35              }
 36          }
 37          // Variable NAND Variable
 38          else {
 39              // Declare a new variable with the expected output as witness.
 40              // Note: The constraint below will ensure `output` is either 0 or 1,
 41              // assuming `self` and `other` are well-formed (they are either 0 or 1).
 42              let output = Boolean(
 43                  E::new_variable(Mode::Private, match !(self.eject_value() & other.eject_value()) {
 44                      true => E::BaseField::one(),
 45                      false => E::BaseField::zero(),
 46                  })
 47                  .into(),
 48              );
 49  
 50              // Ensure `self` * `other` = (1 - `output`)
 51              // `output` is `1` iff `self` or `other` is `0`, otherwise `output` is `0`.
 52              E::enforce(|| (self, other, E::one() - &output.0));
 53  
 54              output
 55          }
 56      }
 57  }
 58  
 59  #[cfg(test)]
 60  mod tests {
 61      use super::*;
 62      use alphavm_circuit_environment::Circuit;
 63  
 64      fn check_nand(
 65          name: &str,
 66          expected: bool,
 67          a: Boolean<Circuit>,
 68          b: Boolean<Circuit>,
 69          num_constants: u64,
 70          num_public: u64,
 71          num_private: u64,
 72          num_constraints: u64,
 73      ) {
 74          Circuit::scope(name, || {
 75              let candidate = a.nand(&b);
 76              assert_eq!(expected, candidate.eject_value(), "({} NAND {})", a.eject_value(), b.eject_value());
 77              assert_scope!(num_constants, num_public, num_private, num_constraints);
 78          });
 79      }
 80  
 81      #[test]
 82      fn test_constant_nand_constant() {
 83          // false NAND false
 84          let expected = true;
 85          let a = Boolean::<Circuit>::new(Mode::Constant, false);
 86          let b = Boolean::<Circuit>::new(Mode::Constant, false);
 87          check_nand("false NAND false", expected, a, b, 0, 0, 0, 0);
 88  
 89          // false NAND true
 90          let expected = true;
 91          let a = Boolean::<Circuit>::new(Mode::Constant, false);
 92          let b = Boolean::<Circuit>::new(Mode::Constant, true);
 93          check_nand("false NAND true", expected, a, b, 0, 0, 0, 0);
 94  
 95          // true NAND false
 96          let expected = true;
 97          let a = Boolean::<Circuit>::new(Mode::Constant, true);
 98          let b = Boolean::<Circuit>::new(Mode::Constant, false);
 99          check_nand("true NAND false", expected, a, b, 0, 0, 0, 0);
100  
101          // true NAND true
102          let expected = false;
103          let a = Boolean::<Circuit>::new(Mode::Constant, true);
104          let b = Boolean::<Circuit>::new(Mode::Constant, true);
105          check_nand("true NAND true", expected, a, b, 0, 0, 0, 0);
106      }
107  
108      #[test]
109      fn test_constant_nand_public() {
110          // false NAND false
111          let expected = true;
112          let a = Boolean::<Circuit>::new(Mode::Constant, false);
113          let b = Boolean::<Circuit>::new(Mode::Public, false);
114          check_nand("false NAND false", expected, a, b, 0, 0, 0, 0);
115  
116          // false NAND true
117          let expected = true;
118          let a = Boolean::<Circuit>::new(Mode::Constant, false);
119          let b = Boolean::<Circuit>::new(Mode::Public, true);
120          check_nand("false NAND true", expected, a, b, 0, 0, 0, 0);
121  
122          // true NAND false
123          let expected = true;
124          let a = Boolean::<Circuit>::new(Mode::Constant, true);
125          let b = Boolean::<Circuit>::new(Mode::Public, false);
126          check_nand("true NAND false", expected, a, b, 0, 0, 0, 0);
127  
128          // true NAND true
129          let expected = false;
130          let a = Boolean::<Circuit>::new(Mode::Constant, true);
131          let b = Boolean::<Circuit>::new(Mode::Public, true);
132          check_nand("true NAND true", expected, a, b, 0, 0, 0, 0);
133      }
134  
135      #[test]
136      fn test_constant_nand_private() {
137          // false NAND false
138          let expected = true;
139          let a = Boolean::<Circuit>::new(Mode::Constant, false);
140          let b = Boolean::<Circuit>::new(Mode::Private, false);
141          check_nand("false NAND false", expected, a, b, 0, 0, 0, 0);
142  
143          // false NAND true
144          let expected = true;
145          let a = Boolean::<Circuit>::new(Mode::Constant, false);
146          let b = Boolean::<Circuit>::new(Mode::Private, true);
147          check_nand("false NAND true", expected, a, b, 0, 0, 0, 0);
148  
149          // true NAND false
150          let expected = true;
151          let a = Boolean::<Circuit>::new(Mode::Constant, true);
152          let b = Boolean::<Circuit>::new(Mode::Private, false);
153          check_nand("true NAND false", expected, a, b, 0, 0, 0, 0);
154  
155          // true NAND true
156          let expected = false;
157          let a = Boolean::<Circuit>::new(Mode::Constant, true);
158          let b = Boolean::<Circuit>::new(Mode::Private, true);
159          check_nand("true NAND true", expected, a, b, 0, 0, 0, 0);
160      }
161  
162      #[test]
163      fn test_public_nand_constant() {
164          // false NAND false
165          let expected = true;
166          let a = Boolean::<Circuit>::new(Mode::Public, false);
167          let b = Boolean::<Circuit>::new(Mode::Constant, false);
168          check_nand("false NAND false", expected, a, b, 0, 0, 0, 0);
169  
170          // false NAND true
171          let expected = true;
172          let a = Boolean::<Circuit>::new(Mode::Public, false);
173          let b = Boolean::<Circuit>::new(Mode::Constant, true);
174          check_nand("false NAND true", expected, a, b, 0, 0, 0, 0);
175  
176          // true NAND false
177          let expected = true;
178          let a = Boolean::<Circuit>::new(Mode::Public, true);
179          let b = Boolean::<Circuit>::new(Mode::Constant, false);
180          check_nand("true NAND false", expected, a, b, 0, 0, 0, 0);
181  
182          // true NAND true
183          let expected = false;
184          let a = Boolean::<Circuit>::new(Mode::Public, true);
185          let b = Boolean::<Circuit>::new(Mode::Constant, true);
186          check_nand("true NAND true", expected, a, b, 0, 0, 0, 0);
187      }
188  
189      #[test]
190      fn test_public_nand_public() {
191          // false NAND false
192          let expected = true;
193          let a = Boolean::<Circuit>::new(Mode::Public, false);
194          let b = Boolean::<Circuit>::new(Mode::Public, false);
195          check_nand("false NAND false", expected, a, b, 0, 0, 1, 1);
196  
197          // false NAND true
198          let expected = true;
199          let a = Boolean::<Circuit>::new(Mode::Public, false);
200          let b = Boolean::<Circuit>::new(Mode::Public, true);
201          check_nand("false NAND true", expected, a, b, 0, 0, 1, 1);
202  
203          // true NAND false
204          let expected = true;
205          let a = Boolean::<Circuit>::new(Mode::Public, true);
206          let b = Boolean::<Circuit>::new(Mode::Public, false);
207          check_nand("true NAND false", expected, a, b, 0, 0, 1, 1);
208  
209          // true NAND true
210          let expected = false;
211          let a = Boolean::<Circuit>::new(Mode::Public, true);
212          let b = Boolean::<Circuit>::new(Mode::Public, true);
213          check_nand("true NAND true", expected, a, b, 0, 0, 1, 1);
214      }
215  
216      #[test]
217      fn test_public_nand_private() {
218          // false NAND false
219          let expected = true;
220          let a = Boolean::<Circuit>::new(Mode::Public, false);
221          let b = Boolean::<Circuit>::new(Mode::Private, false);
222          check_nand("false NAND false", expected, a, b, 0, 0, 1, 1);
223  
224          // false NAND true
225          let expected = true;
226          let a = Boolean::<Circuit>::new(Mode::Public, false);
227          let b = Boolean::<Circuit>::new(Mode::Private, true);
228          check_nand("false NAND true", expected, a, b, 0, 0, 1, 1);
229  
230          // true NAND false
231          let expected = true;
232          let a = Boolean::<Circuit>::new(Mode::Public, true);
233          let b = Boolean::<Circuit>::new(Mode::Private, false);
234          check_nand("true NAND false", expected, a, b, 0, 0, 1, 1);
235  
236          // true NAND true
237          let expected = false;
238          let a = Boolean::<Circuit>::new(Mode::Public, true);
239          let b = Boolean::<Circuit>::new(Mode::Private, true);
240          check_nand("true NAND true", expected, a, b, 0, 0, 1, 1);
241      }
242  
243      #[test]
244      fn test_private_nand_constant() {
245          // false NAND false
246          let expected = true;
247          let a = Boolean::<Circuit>::new(Mode::Private, false);
248          let b = Boolean::<Circuit>::new(Mode::Constant, false);
249          check_nand("false NAND false", expected, a, b, 0, 0, 0, 0);
250  
251          // false NAND true
252          let expected = true;
253          let a = Boolean::<Circuit>::new(Mode::Private, false);
254          let b = Boolean::<Circuit>::new(Mode::Constant, true);
255          check_nand("false NAND true", expected, a, b, 0, 0, 0, 0);
256  
257          // true NAND false
258          let expected = true;
259          let a = Boolean::<Circuit>::new(Mode::Private, true);
260          let b = Boolean::<Circuit>::new(Mode::Constant, false);
261          check_nand("true NAND false", expected, a, b, 0, 0, 0, 0);
262  
263          // true NAND true
264          let expected = false;
265          let a = Boolean::<Circuit>::new(Mode::Private, true);
266          let b = Boolean::<Circuit>::new(Mode::Constant, true);
267          check_nand("true NAND true", expected, a, b, 0, 0, 0, 0);
268      }
269  
270      #[test]
271      fn test_private_nand_public() {
272          // false NAND false
273          let expected = true;
274          let a = Boolean::<Circuit>::new(Mode::Private, false);
275          let b = Boolean::<Circuit>::new(Mode::Public, false);
276          check_nand("false NAND false", expected, a, b, 0, 0, 1, 1);
277  
278          // false NAND true
279          let expected = true;
280          let a = Boolean::<Circuit>::new(Mode::Private, false);
281          let b = Boolean::<Circuit>::new(Mode::Public, true);
282          check_nand("false NAND true", expected, a, b, 0, 0, 1, 1);
283  
284          // true NAND false
285          let expected = true;
286          let a = Boolean::<Circuit>::new(Mode::Private, true);
287          let b = Boolean::<Circuit>::new(Mode::Public, false);
288          check_nand("true NAND false", expected, a, b, 0, 0, 1, 1);
289  
290          // true NAND true
291          let expected = false;
292          let a = Boolean::<Circuit>::new(Mode::Private, true);
293          let b = Boolean::<Circuit>::new(Mode::Public, true);
294          check_nand("true NAND true", expected, a, b, 0, 0, 1, 1);
295      }
296  
297      #[test]
298      fn test_private_nand_private() {
299          // false NAND false
300          let expected = true;
301          let a = Boolean::<Circuit>::new(Mode::Private, false);
302          let b = Boolean::<Circuit>::new(Mode::Private, false);
303          check_nand("false NAND false", expected, a, b, 0, 0, 1, 1);
304  
305          // false NAND true
306          let expected = true;
307          let a = Boolean::<Circuit>::new(Mode::Private, false);
308          let b = Boolean::<Circuit>::new(Mode::Private, true);
309          check_nand("false NAND true", expected, a, b, 0, 0, 1, 1);
310  
311          // true NAND false
312          let expected = true;
313          let a = Boolean::<Circuit>::new(Mode::Private, true);
314          let b = Boolean::<Circuit>::new(Mode::Private, false);
315          check_nand("true NAND false", expected, a, b, 0, 0, 1, 1);
316  
317          // true NAND true
318          let expected = false;
319          let a = Boolean::<Circuit>::new(Mode::Private, true);
320          let b = Boolean::<Circuit>::new(Mode::Private, true);
321          check_nand("true NAND true", expected, a, b, 0, 0, 1, 1);
322      }
323  }