arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/src/uint/not.rs
src/uint/not.rsRaw
  1use ark_ff::Field;
  2use ark_relations::r1cs::SynthesisError;
  3use ark_std::ops::Not;
  4
  5use super::*;
  6
  7impl<const N: usize, T: PrimUInt, F: Field> UInt<N, T, F> {
  8    fn _not(&self) -> Result<Self, SynthesisError> {
  9        let mut result = self.clone();
 10        for a in &mut result.bits {
 11            *a = !&*a
 12        }
 13        result.value = self.value.map(Not::not);
 14        Ok(result)
 15    }
 16}
 17
 18impl<'a, const N: usize, T: PrimUInt, F: Field> Not for &'a UInt<N, T, F> {
 19    type Output = UInt<N, T, F>;
 20    /// Outputs `!self`.
 21    ///
 22    /// If `self` is a constant, then this method *does not* create any constraints or variables.
 23    ///
 24    /// ```
 25    /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> {
 26    /// // We'll use the BLS12-381 scalar field for our constraints.
 27    /// use ark_test_curves::bls12_381::Fr;
 28    /// use ark_relations::r1cs::*;
 29    /// use ark_r1cs_std::prelude::*;
 30    ///
 31    /// let cs = ConstraintSystem::<Fr>::new_ref();
 32    /// let a = UInt8::new_witness(cs.clone(), || Ok(2))?;
 33    /// let b = UInt8::new_witness(cs.clone(), || Ok(!2))?;
 34    ///
 35    /// (!a).enforce_equal(&b)?;
 36    /// assert!(cs.is_satisfied().unwrap());
 37    /// # Ok(())
 38    /// # }
 39    /// ```
 40    #[tracing::instrument(target = "r1cs", skip(self))]
 41    fn not(self) -> Self::Output {
 42        self._not().unwrap()
 43    }
 44}
 45
 46impl<'a, const N: usize, T: PrimUInt, F: Field> Not for UInt<N, T, F> {
 47    type Output = UInt<N, T, F>;
 48
 49    /// Outputs `!self`.
 50    ///
 51    /// If `self` is a constant, then this method *does not* create any constraints or variables.
 52    ///
 53    /// ```
 54    /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> {
 55    /// // We'll use the BLS12-381 scalar field for our constraints.
 56    /// use ark_test_curves::bls12_381::Fr;
 57    /// use ark_relations::r1cs::*;
 58    /// use ark_r1cs_std::prelude::*;
 59    ///
 60    /// let cs = ConstraintSystem::<Fr>::new_ref();
 61    /// let a = UInt8::new_witness(cs.clone(), || Ok(2))?;
 62    /// let b = UInt8::new_witness(cs.clone(), || Ok(!2))?;
 63    ///
 64    /// (!a).enforce_equal(&b)?;
 65    /// assert!(cs.is_satisfied().unwrap());
 66    /// # Ok(())
 67    /// # }
 68    /// ```
 69    #[tracing::instrument(target = "r1cs", 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        prelude::EqGadget,
 81        uint::test_utils::{run_unary_exhaustive, run_unary_random},
 82        R1CSVar,
 83    };
 84    use ark_ff::PrimeField;
 85    use ark_test_curves::bls12_381::Fr;
 86
 87    fn uint_not<T: PrimUInt, const N: usize, F: PrimeField>(
 88        a: UInt<N, T, F>,
 89    ) -> Result<(), SynthesisError> {
 90        let cs = a.cs();
 91        let computed = !&a;
 92        let expected_mode = if a.is_constant() {
 93            AllocationMode::Constant
 94        } else {
 95            AllocationMode::Witness
 96        };
 97        let expected =
 98            UInt::<N, T, F>::new_variable(cs.clone(), || Ok(!a.value()?), expected_mode)?;
 99        assert_eq!(expected.value(), computed.value());
100        expected.enforce_equal(&computed)?;
101        if !a.is_constant() {
102            assert!(cs.is_satisfied().unwrap());
103        }
104        Ok(())
105    }
106
107    #[test]
108    fn u8_not() {
109        run_unary_exhaustive(uint_not::<u8, 8, Fr>).unwrap()
110    }
111
112    #[test]
113    fn u16_not() {
114        run_unary_random::<1000, 16, _, _>(uint_not::<u16, 16, Fr>).unwrap()
115    }
116
117    #[test]
118    fn u32_not() {
119        run_unary_random::<1000, 32, _, _>(uint_not::<u32, 32, Fr>).unwrap()
120    }
121
122    #[test]
123    fn u64_not() {
124        run_unary_random::<1000, 64, _, _>(uint_not::<u64, 64, Fr>).unwrap()
125    }
126
127    #[test]
128    fn u128() {
129        run_unary_random::<1000, 128, _, _>(uint_not::<u128, 128, Fr>).unwrap()
130    }
131}