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}