arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/src/boolean/not.rs
src/boolean/not.rsRaw
  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}