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}