ark_r1cs_std/boolean/
not.rs

1use ark_ff::Field;
2use ark_relations::r1cs::SynthesisError;
3use ark_std::ops::Not;
4
5use super::Boolean;
6
7impl<F: Field> Boolean<F> {
8    fn _not(&self) -> Result<Self, SynthesisError> {
9        let mut result = self.clone();
10        result.not_in_place()?;
11        Ok(result)
12    }
13
14    pub fn not_in_place(&mut self) -> Result<(), SynthesisError> {
15        match *self {
16            Boolean::Constant(ref mut c) => *c = !*c,
17            Boolean::Var(ref mut v) => *v = v.not()?,
18        }
19        Ok(())
20    }
21}
22
23impl<'a, F: Field> Not for &'a Boolean<F> {
24    type Output = Boolean<F>;
25    /// Negates `self`.
26    ///
27    /// This *does not* create any new variables or constraints.
28    /// ```
29    /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> {
30    /// // We'll use the BLS12-381 scalar field for our constraints.
31    /// use ark_test_curves::bls12_381::Fr;
32    /// use ark_relations::r1cs::*;
33    /// use ark_r1cs_std::prelude::*;
34    ///
35    /// let cs = ConstraintSystem::<Fr>::new_ref();
36    ///
37    /// let a = Boolean::new_witness(cs.clone(), || Ok(true))?;
38    /// let b = Boolean::new_witness(cs.clone(), || Ok(false))?;
39    ///
40    /// (!&a).enforce_equal(&b)?;
41    /// (!&b).enforce_equal(&a)?;
42    ///
43    /// (!&a).enforce_equal(&Boolean::FALSE)?;
44    /// (!&b).enforce_equal(&Boolean::TRUE)?;
45    ///
46    /// assert!(cs.is_satisfied().unwrap());
47    /// # Ok(())
48    /// # }
49    /// ```
50    #[tracing::instrument(target = "r1cs", skip(self))]
51    fn not(self) -> Self::Output {
52        self._not().unwrap()
53    }
54}
55
56impl<'a, F: Field> Not for &'a mut Boolean<F> {
57    type Output = Boolean<F>;
58
59    #[tracing::instrument(target = "r1cs", skip(self))]
60    fn not(self) -> Self::Output {
61        self._not().unwrap()
62    }
63}
64
65impl<F: Field> Not for Boolean<F> {
66    type Output = Boolean<F>;
67
68    #[tracing::instrument(target = "r1cs", skip(self))]
69    fn not(self) -> Self::Output {
70        self._not().unwrap()
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77    use crate::{
78        alloc::{AllocVar, AllocationMode},
79        boolean::test_utils::run_unary_exhaustive,
80        prelude::EqGadget,
81        R1CSVar,
82    };
83    use ark_test_curves::bls12_381::Fr;
84
85    #[test]
86    fn not() {
87        run_unary_exhaustive::<Fr>(|a| {
88            let cs = a.cs();
89            let computed = !&a;
90            let expected_mode = if a.is_constant() {
91                AllocationMode::Constant
92            } else {
93                AllocationMode::Witness
94            };
95            let expected = Boolean::new_variable(cs.clone(), || Ok(!a.value()?), expected_mode)?;
96            assert_eq!(expected.value(), computed.value());
97            expected.enforce_equal(&computed)?;
98            if !a.is_constant() {
99                assert!(cs.is_satisfied().unwrap());
100            }
101            Ok(())
102        })
103        .unwrap()
104    }
105}