snarkvm_circuit_types_boolean/
and.rs

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