ark_r1cs_std/uint/
not.rs

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}