snarkvm_circuit_types_field/
equal.rs1use super::*;
17
18impl<E: Environment> Equal<Self> for Field<E> {
19 type Output = Boolean<E>;
20
21 fn is_equal(&self, other: &Self) -> Self::Output {
27 !self.is_not_equal(other)
28 }
29
30 fn is_not_equal(&self, other: &Self) -> Self::Output {
39 let is_neq_ejected = self.eject_value() != other.eject_value();
41
42 match (self.is_constant(), other.is_constant()) {
43 (true, true) => Boolean::new(Mode::Constant, is_neq_ejected),
45 _ => {
46 let is_neq = Boolean::from_variable(E::new_variable(Mode::Private, match is_neq_ejected {
102 true => E::BaseField::one(),
103 false => E::BaseField::zero(),
104 }));
105
106 let delta = self - other;
108
109 let multiplier: Field<E> = witness!(|delta| {
114 match delta.inverse() {
115 Ok(inverse) => inverse,
116 _ => console::Field::one(),
117 }
118 });
119
120 let is_eq = !is_neq.clone();
122
123 E::enforce(|| (&delta, &multiplier, &is_neq));
125
126 E::enforce(|| (delta, is_eq, E::zero()));
128
129 is_neq
131 }
132 }
133 }
134}
135
136impl<E: Environment> Metrics<dyn Equal<Field<E>, Output = Boolean<E>>> for Field<E> {
137 type Case = (Mode, Mode);
138
139 fn count(case: &Self::Case) -> Count {
141 match case {
142 (Mode::Constant, Mode::Constant) => Count::is(1, 0, 0, 0),
143 _ => Count::is(0, 0, 2, 2),
144 }
145 }
146}
147
148impl<E: Environment> OutputMode<dyn Equal<Field<E>, Output = Boolean<E>>> for Field<E> {
149 type Case = (Mode, Mode);
150
151 fn output_mode(case: &Self::Case) -> Mode {
152 match case {
153 (Mode::Constant, Mode::Constant) => Mode::Constant,
154 _ => Mode::Private,
155 }
156 }
157}
158
159#[cfg(test)]
160mod tests {
161 use super::*;
162 use snarkvm_circuit_environment::Circuit;
163
164 const ITERATIONS: u64 = 200;
165
166 fn check_is_equal(name: &str, expected: bool, a: &Field<Circuit>, b: &Field<Circuit>) {
167 Circuit::scope(name, || {
168 let candidate = a.is_equal(b);
169 assert_eq!(expected, candidate.eject_value(), "({} == {})", a.eject_value(), b.eject_value());
170 assert_count!(Equal(Field, Field) => Boolean, &(a.eject_mode(), b.eject_mode()));
171 assert_output_mode!(Equal(Field, Field) => Boolean, &(a.eject_mode(), b.eject_mode()), candidate);
172 });
173 }
174
175 fn check_is_not_equal(name: &str, expected: bool, a: &Field<Circuit>, b: &Field<Circuit>) {
176 Circuit::scope(name, || {
177 let candidate = a.is_not_equal(b);
178 assert_eq!(expected, candidate.eject_value(), "({} != {})", a.eject_value(), b.eject_value());
179 assert_count!(Equal(Field, Field) => Boolean, &(a.eject_mode(), b.eject_mode()));
180 assert_output_mode!(Equal(Field, Field) => Boolean, &(a.eject_mode(), b.eject_mode()), candidate);
181 });
182 }
183
184 fn run_test(mode_a: Mode, mode_b: Mode) {
185 let mut rng = TestRng::default();
186
187 for i in 0..ITERATIONS {
188 let first = Uniform::rand(&mut rng);
189 let second = Uniform::rand(&mut rng);
190
191 let a = Field::<Circuit>::new(mode_a, first);
192 let b = Field::<Circuit>::new(mode_b, second);
193
194 let name = format!("Equal: a == b {i}");
195 check_is_equal(&name, first == second, &a, &b);
196
197 let name = format!("Not Equal: a != b {i}");
198 check_is_not_equal(&name, first != second, &a, &b);
199
200 let a = Field::<Circuit>::new(mode_a, first);
202 let b = Field::<Circuit>::new(mode_b, first);
203 let name = format!("{first} == {first}");
204 check_is_equal(&name, true, &a, &b);
205
206 let a = Field::<Circuit>::new(mode_a, second);
208 let b = Field::<Circuit>::new(mode_b, second);
209 let name = format!("{second} == {second}");
210 check_is_equal(&name, true, &a, &b);
211 }
212 }
213
214 #[test]
215 fn test_constant_is_equal_to_constant() {
216 run_test(Mode::Constant, Mode::Constant);
217 }
218
219 #[test]
220 fn test_constant_is_not_equal_to_public() {
221 run_test(Mode::Constant, Mode::Public);
222 }
223
224 #[test]
225 fn test_constant_is_not_equal_to_private() {
226 run_test(Mode::Constant, Mode::Private);
227 }
228
229 #[test]
230 fn test_public_is_equal_to_constant() {
231 run_test(Mode::Public, Mode::Constant);
232 }
233
234 #[test]
235 fn test_private_is_equal_to_constant() {
236 run_test(Mode::Private, Mode::Constant);
237 }
238
239 #[test]
240 fn test_public_is_equal_to_public() {
241 run_test(Mode::Public, Mode::Public);
242 }
243
244 #[test]
245 fn test_public_is_not_equal_to_private() {
246 run_test(Mode::Public, Mode::Private);
247 }
248
249 #[test]
250 fn test_private_is_equal_to_public() {
251 run_test(Mode::Private, Mode::Public);
252 }
253
254 #[test]
255 fn test_private_is_equal_to_private() {
256 run_test(Mode::Private, Mode::Private);
257 }
258
259 #[test]
260 fn test_is_eq_cases() {
261 let one = console::Field::<<Circuit as Environment>::Network>::one();
262
263 {
265 let mut accumulator = one + one;
266
267 for _ in 0..ITERATIONS {
268 let a = Field::<Circuit>::new(Mode::Private, accumulator);
269 let b = Field::<Circuit>::new(Mode::Private, accumulator);
270 let is_eq = a.is_equal(&b);
271 assert!(is_eq.eject_value()); let a = Field::<Circuit>::new(Mode::Private, one);
274 let b = Field::<Circuit>::new(Mode::Private, accumulator);
275 let is_eq = a.is_equal(&b);
276 assert!(!is_eq.eject_value()); let a = Field::<Circuit>::new(Mode::Private, accumulator);
279 let b = Field::<Circuit>::new(Mode::Private, accumulator - one);
280 let is_eq = a.is_equal(&b);
281 assert!(!is_eq.eject_value()); accumulator += one;
284 }
285 }
286 }
287
288 #[test]
289 fn test_is_neq_cases() {
290 let zero = console::Field::<<Circuit as Environment>::Network>::zero();
291 let one = console::Field::<<Circuit as Environment>::Network>::one();
292 let two = one + one;
293 let five = two + two + one;
294
295 let enforce = |a: Field<Circuit>, b: Field<Circuit>, multiplier: Field<Circuit>, is_neq: Boolean<Circuit>| {
301 let delta = &a - &b;
303
304 let is_eq = !is_neq.clone();
306
307 Circuit::enforce(|| (delta.clone(), multiplier, is_neq.clone()));
309
310 Circuit::enforce(|| (delta, is_eq, Circuit::zero()));
312 };
313
314 let a = Field::<Circuit>::new(Mode::Private, five);
319 let b = Field::<Circuit>::new(Mode::Private, five);
320 let multiplier = Field::<Circuit>::new(Mode::Private, one);
321 let is_neq = Boolean::new(Mode::Private, false);
322
323 assert!(Circuit::is_satisfied());
324 enforce(a, b, multiplier, is_neq);
325 assert!(Circuit::is_satisfied());
326 Circuit::reset();
327
328 let a = Field::<Circuit>::new(Mode::Private, five);
333 let b = Field::<Circuit>::new(Mode::Private, five);
334 let multiplier = Field::<Circuit>::new(Mode::Private, one);
335 let is_neq = Boolean::new(Mode::Private, true);
336
337 assert!(Circuit::is_satisfied());
338 enforce(a, b, multiplier, is_neq);
339 assert!(!Circuit::is_satisfied());
340 Circuit::reset();
341
342 let a = Field::<Circuit>::new(Mode::Private, five);
346 let b = Field::<Circuit>::new(Mode::Private, two);
347 let multiplier = Field::<Circuit>::new(Mode::Private, zero);
348 let is_neq = Boolean::new(Mode::Private, false);
349
350 assert!(Circuit::is_satisfied());
351 enforce(a, b, multiplier, is_neq);
352 assert!(!Circuit::is_satisfied());
353 Circuit::reset();
354
355 let a = Field::<Circuit>::new(Mode::Private, five);
360 let b = Field::<Circuit>::new(Mode::Private, two);
361 let multiplier = Field::<Circuit>::new(Mode::Private, one);
362 let is_neq = Boolean::new(Mode::Private, false);
363
364 assert!(Circuit::is_satisfied());
365 enforce(a, b, multiplier, is_neq);
366 assert!(!Circuit::is_satisfied());
367 Circuit::reset();
368
369 let a = Field::<Circuit>::new(Mode::Private, five);
374 let b = Field::<Circuit>::new(Mode::Private, two);
375 let multiplier = Field::<Circuit>::new(Mode::Private, two);
376 let is_neq = Boolean::new(Mode::Private, true);
377
378 assert!(Circuit::is_satisfied());
379 enforce(a, b, multiplier, is_neq);
380 assert!(!Circuit::is_satisfied());
381 Circuit::reset();
382
383 let a = Field::<Circuit>::new(Mode::Private, five);
388 let b = Field::<Circuit>::new(Mode::Private, two);
389 let multiplier =
390 Field::<Circuit>::new(Mode::Private, (five - two).inverse().expect("Failed to compute a native inverse"));
391 let is_neq = Boolean::new(Mode::Private, true);
392
393 assert!(Circuit::is_satisfied());
394 enforce(a, b, multiplier, is_neq);
395 assert!(Circuit::is_satisfied());
396 Circuit::reset();
397 }
398}