Skip to main content

ark_r1cs_std/boolean/
not.rs

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