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