diff --git a/src/gadgets/insert.rs b/src/gadgets/insert.rs index ca7149bf..64260209 100644 --- a/src/gadgets/insert.rs +++ b/src/gadgets/insert.rs @@ -1,33 +1,39 @@ use crate::circuit_builder::CircuitBuilder; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::generator::EqualsZeroGenerator; +use crate::generator::NonzeroTestGenerator; use crate::target::Target; impl, const D: usize> CircuitBuilder { - /// Evaluates to 1 if `x` equals zero, 0 otherwise. - pub fn is_zero(&mut self, x: Target) -> Target { + /// Evaluates to 0 if `x` equals zero, 1 otherwise. + pub fn is_nonzero(&mut self, x: Target) -> Target { + // Dummy variable. let m = self.add_virtual_target(); + + // The prover sets the dummy variable to 0 if x == 0 and to 1/x otherwise. + self.add_generator(NonzeroTestGenerator { + to_test: x, + dummy: m, + }); + + // Evaluates to (0) * (0) = 0 if x == 0 and (x) * (1/x) = 1 otherwise. let y = self.mul(x, m); + // Enforce that (1 - y) * x == 0. let one = self.one(); let diff = self.sub(one, y); let prod = self.mul(diff, x); self.assert_zero(prod); - self.add_generator(EqualsZeroGenerator { - to_test: x, - dummy: m, - is_zero: y, - }); - y } /// Evaluates to 1 if `x` and `y` are equal, 0 otherwise. pub fn is_equal(&mut self, x: Target, y: Target) -> Target { let difference = self.sub(x, y); - self.is_zero(difference) + let not_equal = self.is_nonzero(difference); + let one = self.one(); + self.sub(one, not_equal) } /// Inserts a `Target` in a vector at a non-deterministic index. This is done by rotating to the diff --git a/src/generator.rs b/src/generator.rs index 6bc12011..3795fdfa 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -132,13 +132,12 @@ impl SimpleGenerator for RandomValueGenerator { } /// A generator for testing if a value equals zero -pub(crate) struct EqualsZeroGenerator { +pub(crate) struct NonzeroTestGenerator { pub(crate) to_test: Target, pub(crate) dummy: Target, - pub(crate) is_zero: Target, } -impl SimpleGenerator for EqualsZeroGenerator { +impl SimpleGenerator for NonzeroTestGenerator { fn dependencies(&self) -> Vec { vec![self.to_test] } @@ -146,12 +145,6 @@ impl SimpleGenerator for EqualsZeroGenerator { fn run_once(&self, witness: &PartialWitness) -> PartialWitness { let to_test_value = witness.get_target(self.to_test); - let is_zero_value = if to_test_value == F::ZERO { - F::ZERO - } else { - F::ONE - }; - let dummy_value = if to_test_value == F::ZERO { F::ONE } else { @@ -160,7 +153,6 @@ impl SimpleGenerator for EqualsZeroGenerator { let mut witness = PartialWitness::new(); witness.set_target(self.dummy, dummy_value); - witness.set_target(self.is_zero, is_zero_value); witness } }