1use super::*;
17
18impl<E: Environment> Nand<Self> for Boolean<E> {
19 type Output = Boolean<E>;
20
21 fn nand(&self, other: &Self) -> Self::Output {
23 if self.is_constant() {
25 match self.eject_value() {
26 true => !other.clone(),
27 false => !self.clone(),
28 }
29 }
30 else if other.is_constant() {
32 match other.eject_value() {
33 true => !self.clone(),
34 false => !other.clone(),
35 }
36 }
37 else {
39 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 E::enforce(|| (self, other, E::one() - &output.0));
53
54 output
55 }
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62 use snarkvm_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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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}