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