ark-r1cs-std/src/boolean/not.rs
src/boolean/not.rsRaw
1use ark_ff::Field;
2use ark_relations::r1cs::SynthesisError;
3use ark_std::ops::Not;
4
5use super::Boolean;
6
7impl<F: Field> Boolean<F> {
8 fn _not(&self) -> Result<Self, SynthesisError> {
9 match *self {
10 Boolean::Constant(c) => Ok(Boolean::Constant(!c)),
11 Boolean::Var(ref v) => Ok(Boolean::Var(v.not().unwrap())),
12 }
13 }
14}
15
16impl<'a, F: Field> Not for &'a Boolean<F> {
17 type Output = Boolean<F>;
18 /// Negates `self`.
19 ///
20 /// This *does not* create any new variables or constraints.
21 /// ```
22 /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> {
23 /// // We'll use the BLS12-381 scalar field for our constraints.
24 /// use ark_test_curves::bls12_381::Fr;
25 /// use ark_relations::r1cs::*;
26 /// use ark_r1cs_std::prelude::*;
27 ///
28 /// let cs = ConstraintSystem::<Fr>::new_ref();
29 ///
30 /// let a = Boolean::new_witness(cs.clone(), || Ok(true))?;
31 /// let b = Boolean::new_witness(cs.clone(), || Ok(false))?;
32 ///
33 /// (!&a).enforce_equal(&b)?;
34 /// (!&b).enforce_equal(&a)?;
35 ///
36 /// (!&a).enforce_equal(&Boolean::FALSE)?;
37 /// (!&b).enforce_equal(&Boolean::TRUE)?;
38 ///
39 /// assert!(cs.is_satisfied().unwrap());
40 /// # Ok(())
41 /// # }
42 /// ```
43 #[tracing::instrument(target = "r1cs", skip(self))]
44 fn not(self) -> Self::Output {
45 self._not().unwrap()
46 }
47}
48
49impl<'a, F: Field> Not for &'a mut Boolean<F> {
50 type Output = Boolean<F>;
51
52 #[tracing::instrument(target = "r1cs", skip(self))]
53 fn not(self) -> Self::Output {
54 self._not().unwrap()
55 }
56}
57
58impl<F: Field> Not for Boolean<F> {
59 type Output = Boolean<F>;
60
61 #[tracing::instrument(target = "r1cs", skip(self))]
62 fn not(self) -> Self::Output {
63 self._not().unwrap()
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70 use crate::{
71 alloc::{AllocVar, AllocationMode},
72 boolean::test_utils::run_unary_exhaustive,
73 prelude::EqGadget,
74 R1CSVar,
75 };
76 use ark_test_curves::bls12_381::Fr;
77
78 #[test]
79 fn not() {
80 run_unary_exhaustive::<Fr>(|a| {
81 let cs = a.cs();
82 let computed = !&a;
83 let expected_mode = if a.is_constant() {
84 AllocationMode::Constant
85 } else {
86 AllocationMode::Witness
87 };
88 let expected = Boolean::new_variable(cs.clone(), || Ok(!a.value()?), expected_mode)?;
89 assert_eq!(expected.value(), computed.value());
90 expected.enforce_equal(&computed)?;
91 if !a.is_constant() {
92 assert!(cs.is_satisfied().unwrap());
93 }
94 Ok(())
95 })
96 .unwrap()
97 }
98}