1use super::*;
17
18impl<E: Environment> Ternary for Field<E> {
19 type Boolean = Boolean<E>;
20 type Output = Self;
21
22 fn ternary(condition: &Self::Boolean, first: &Self, second: &Self) -> Self::Output {
24 if condition.is_constant() {
26 match condition.eject_value() {
27 true => first.clone(),
28 false => second.clone(),
29 }
30 }
31 else if first.is_constant() && second.is_constant() {
33 let not_condition = Field::from_boolean(&!condition);
34 let condition = Field::from_boolean(condition);
35 (condition * first) + (not_condition * second)
36 }
37 else {
39 let witness = witness!(|condition, first, second| match condition {
41 true => first,
42 false => second,
43 });
44
45 E::enforce(|| ((first - second), condition, (&witness - second)));
88
89 witness
90 }
91 }
92}
93
94impl<E: Environment> Metrics<dyn Ternary<Boolean = Boolean<E>, Output = Field<E>>> for Field<E> {
95 type Case = (Mode, Mode, Mode);
96
97 fn count(case: &Self::Case) -> Count {
98 match case {
99 (Mode::Constant, _, _)
100 | (Mode::Public, Mode::Constant, Mode::Constant)
101 | (Mode::Private, Mode::Constant, Mode::Constant) => Count::is(0, 0, 0, 0),
102 _ => Count::is(0, 0, 1, 1),
103 }
104 }
105}
106
107impl<E: Environment> OutputMode<dyn Ternary<Boolean = Boolean<E>, Output = Field<E>>> for Field<E> {
108 type Case = (CircuitType<Boolean<E>>, Mode, Mode);
109
110 fn output_mode(parameter: &Self::Case) -> Mode {
111 match parameter.0.mode().is_constant() {
112 true => match ¶meter.0 {
113 CircuitType::Constant(circuit) => match circuit.eject_value() {
114 true => parameter.1,
115 false => parameter.2,
116 },
117 _ => E::halt("Circuit is required to determine output mode."),
118 },
119 false => Mode::Private,
120 }
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127 use snarkvm_circuit_environment::Circuit;
128
129 fn check_ternary(
130 name: &str,
131 expected: console::Field<<Circuit as Environment>::Network>,
132 condition: Boolean<Circuit>,
133 a: Field<Circuit>,
134 b: Field<Circuit>,
135 ) {
136 Circuit::scope(name, || {
137 let case = format!("({} ? {} : {})", condition.eject_value(), a.eject_value(), b.eject_value());
138 let candidate = Field::ternary(&condition, &a, &b);
139 assert_eq!(expected, candidate.eject_value(), "{case}");
140 assert_count!(Ternary(Boolean, Field, Field) => Field, &(condition.eject_mode(), a.eject_mode(), b.eject_mode()));
141 assert_output_mode!(Ternary(Boolean, Field, Field) => Field, &(CircuitType::from(&condition), a.eject_mode(), b.eject_mode()), candidate);
142 });
143 }
144
145 #[test]
146 fn test_constant_condition() {
147 let mut rng = TestRng::default();
148
149 let first = Uniform::rand(&mut rng);
150 let second = Uniform::rand(&mut rng);
151
152 let expected = second;
154 let condition = Boolean::<Circuit>::new(Mode::Constant, false);
155 let a = Field::<Circuit>::new(Mode::Constant, first);
156 let b = Field::<Circuit>::new(Mode::Constant, second);
157 check_ternary("false ? Constant : Constant", expected, condition, a, b);
158
159 let expected = second;
161 let condition = Boolean::<Circuit>::new(Mode::Constant, false);
162 let a = Field::<Circuit>::new(Mode::Constant, first);
163 let b = Field::<Circuit>::new(Mode::Public, second);
164 check_ternary("false ? Constant : Public", expected, condition, a, b);
165
166 let expected = second;
168 let condition = Boolean::<Circuit>::new(Mode::Constant, false);
169 let a = Field::<Circuit>::new(Mode::Public, first);
170 let b = Field::<Circuit>::new(Mode::Constant, second);
171 check_ternary("false ? Public : Constant", expected, condition, a, b);
172
173 let expected = second;
175 let condition = Boolean::<Circuit>::new(Mode::Constant, false);
176 let a = Field::<Circuit>::new(Mode::Public, first);
177 let b = Field::<Circuit>::new(Mode::Public, second);
178 check_ternary("false ? Public : Public", expected, condition, a, b);
179
180 let expected = second;
182 let condition = Boolean::<Circuit>::new(Mode::Constant, false);
183 let a = Field::<Circuit>::new(Mode::Public, first);
184 let b = Field::<Circuit>::new(Mode::Private, second);
185 check_ternary("false ? Public : Private", expected, condition, a, b);
186
187 let expected = second;
189 let condition = Boolean::<Circuit>::new(Mode::Constant, false);
190 let a = Field::<Circuit>::new(Mode::Private, first);
191 let b = Field::<Circuit>::new(Mode::Private, second);
192 check_ternary("false ? Private : Private", expected, condition, a, b);
193
194 let expected = first;
196 let condition = Boolean::<Circuit>::new(Mode::Constant, true);
197 let a = Field::<Circuit>::new(Mode::Constant, first);
198 let b = Field::<Circuit>::new(Mode::Constant, second);
199 check_ternary("true ? Constant : Constant", expected, condition, a, b);
200
201 let expected = first;
203 let condition = Boolean::<Circuit>::new(Mode::Constant, true);
204 let a = Field::<Circuit>::new(Mode::Constant, first);
205 let b = Field::<Circuit>::new(Mode::Public, second);
206 check_ternary("true ? Constant : Public", expected, condition, a, b);
207
208 let expected = first;
210 let condition = Boolean::<Circuit>::new(Mode::Constant, true);
211 let a = Field::<Circuit>::new(Mode::Public, first);
212 let b = Field::<Circuit>::new(Mode::Constant, second);
213 check_ternary("true ? Public : Constant", expected, condition, a, b);
214
215 let expected = first;
217 let condition = Boolean::<Circuit>::new(Mode::Constant, true);
218 let a = Field::<Circuit>::new(Mode::Public, first);
219 let b = Field::<Circuit>::new(Mode::Public, second);
220 check_ternary("true ? Public : Public", expected, condition, a, b);
221
222 let expected = first;
224 let condition = Boolean::<Circuit>::new(Mode::Constant, true);
225 let a = Field::<Circuit>::new(Mode::Public, first);
226 let b = Field::<Circuit>::new(Mode::Private, second);
227 check_ternary("true ? Public : Private", expected, condition, a, b);
228
229 let expected = first;
231 let condition = Boolean::<Circuit>::new(Mode::Constant, true);
232 let a = Field::<Circuit>::new(Mode::Private, first);
233 let b = Field::<Circuit>::new(Mode::Private, second);
234 check_ternary("true ? Private : Private", expected, condition, a, b);
235 }
236
237 #[test]
238 fn test_public_condition_and_constant_inputs() {
239 let mut rng = TestRng::default();
240
241 let first = Uniform::rand(&mut rng);
242 let second = Uniform::rand(&mut rng);
243
244 let expected = second;
246 let condition = Boolean::<Circuit>::new(Mode::Public, false);
247 let a = Field::<Circuit>::new(Mode::Constant, first);
248 let b = Field::<Circuit>::new(Mode::Constant, second);
249 check_ternary("false ? Constant : Constant", expected, condition, a, b);
250
251 let expected = first;
253 let condition = Boolean::<Circuit>::new(Mode::Public, true);
254 let a = Field::<Circuit>::new(Mode::Constant, first);
255 let b = Field::<Circuit>::new(Mode::Constant, second);
256 check_ternary("true ? Constant : Constant", expected, condition, a, b);
257 }
258
259 #[test]
260 fn test_public_condition_and_mixed_inputs() {
261 let mut rng = TestRng::default();
262
263 let first = Uniform::rand(&mut rng);
264 let second = Uniform::rand(&mut rng);
265
266 let expected = second;
268 let condition = Boolean::<Circuit>::new(Mode::Public, false);
269 let a = Field::<Circuit>::new(Mode::Constant, first);
270 let b = Field::<Circuit>::new(Mode::Public, second);
271 check_ternary("false ? Constant : Public", expected, condition, a, b);
272
273 let expected = second;
275 let condition = Boolean::<Circuit>::new(Mode::Public, false);
276 let a = Field::<Circuit>::new(Mode::Public, first);
277 let b = Field::<Circuit>::new(Mode::Constant, second);
278 check_ternary("false ? Public : Constant", expected, condition, a, b);
279
280 let expected = first;
282 let condition = Boolean::<Circuit>::new(Mode::Public, true);
283 let a = Field::<Circuit>::new(Mode::Constant, first);
284 let b = Field::<Circuit>::new(Mode::Public, second);
285 check_ternary("true ? Constant : Public", expected, condition, a, b);
286
287 let expected = first;
289 let condition = Boolean::<Circuit>::new(Mode::Public, true);
290 let a = Field::<Circuit>::new(Mode::Public, first);
291 let b = Field::<Circuit>::new(Mode::Constant, second);
292 check_ternary("true ? Public : Constant", expected, condition, a, b);
293 }
294
295 #[test]
296 fn test_private_condition_and_constant_inputs() {
297 let mut rng = TestRng::default();
298
299 let first = Uniform::rand(&mut rng);
300 let second = Uniform::rand(&mut rng);
301
302 let expected = second;
304 let condition = Boolean::<Circuit>::new(Mode::Private, false);
305 let a = Field::<Circuit>::new(Mode::Constant, first);
306 let b = Field::<Circuit>::new(Mode::Constant, second);
307 check_ternary("false ? Constant : Constant", expected, condition, a, b);
308
309 let expected = first;
311 let condition = Boolean::<Circuit>::new(Mode::Private, true);
312 let a = Field::<Circuit>::new(Mode::Constant, first);
313 let b = Field::<Circuit>::new(Mode::Constant, second);
314 check_ternary("true ? Constant : Constant", expected, condition, a, b);
315 }
316
317 #[test]
318 fn test_private_condition_and_mixed_inputs() {
319 let mut rng = TestRng::default();
320
321 let first = Uniform::rand(&mut rng);
322 let second = Uniform::rand(&mut rng);
323
324 let expected = second;
326 let condition = Boolean::<Circuit>::new(Mode::Private, false);
327 let a = Field::<Circuit>::new(Mode::Constant, first);
328 let b = Field::<Circuit>::new(Mode::Public, second);
329 check_ternary("false ? Constant : Public", expected, condition, a, b);
330
331 let expected = second;
333 let condition = Boolean::<Circuit>::new(Mode::Private, false);
334 let a = Field::<Circuit>::new(Mode::Public, first);
335 let b = Field::<Circuit>::new(Mode::Constant, second);
336 check_ternary("false ? Public : Constant", expected, condition, a, b);
337
338 let expected = first;
340 let condition = Boolean::<Circuit>::new(Mode::Private, true);
341 let a = Field::<Circuit>::new(Mode::Constant, first);
342 let b = Field::<Circuit>::new(Mode::Public, second);
343 check_ternary("true ? Constant : Public", expected, condition, a, b);
344
345 let expected = first;
347 let condition = Boolean::<Circuit>::new(Mode::Private, true);
348 let a = Field::<Circuit>::new(Mode::Public, first);
349 let b = Field::<Circuit>::new(Mode::Constant, second);
350 check_ternary("true ? Public : Constant", expected, condition, a, b);
351 }
352
353 #[test]
354 fn test_public_condition_and_variable_inputs() {
355 let mut rng = TestRng::default();
356
357 let first = Uniform::rand(&mut rng);
358 let second = Uniform::rand(&mut rng);
359
360 let expected = second;
362 let condition = Boolean::<Circuit>::new(Mode::Public, false);
363 let a = Field::<Circuit>::new(Mode::Public, first);
364 let b = Field::<Circuit>::new(Mode::Public, second);
365 check_ternary("false ? Public : Public", expected, condition, a, b);
366
367 let expected = second;
369 let condition = Boolean::<Circuit>::new(Mode::Public, false);
370 let a = Field::<Circuit>::new(Mode::Public, first);
371 let b = Field::<Circuit>::new(Mode::Private, second);
372 check_ternary("false ? Public : Private", expected, condition, a, b);
373
374 let expected = second;
376 let condition = Boolean::<Circuit>::new(Mode::Public, false);
377 let a = Field::<Circuit>::new(Mode::Private, first);
378 let b = Field::<Circuit>::new(Mode::Public, second);
379 check_ternary("false ? Private : Public", expected, condition, a, b);
380
381 let expected = second;
383 let condition = Boolean::<Circuit>::new(Mode::Public, false);
384 let a = Field::<Circuit>::new(Mode::Private, first);
385 let b = Field::<Circuit>::new(Mode::Private, second);
386 check_ternary("false ? Private : Private", expected, condition, a, b);
387
388 let expected = first;
390 let condition = Boolean::<Circuit>::new(Mode::Public, true);
391 let a = Field::<Circuit>::new(Mode::Public, first);
392 let b = Field::<Circuit>::new(Mode::Public, second);
393 check_ternary("true ? Public : Public", expected, condition, a, b);
394
395 let expected = first;
397 let condition = Boolean::<Circuit>::new(Mode::Public, true);
398 let a = Field::<Circuit>::new(Mode::Public, first);
399 let b = Field::<Circuit>::new(Mode::Private, second);
400 check_ternary("true ? Public : Private", expected, condition, a, b);
401
402 let expected = first;
404 let condition = Boolean::<Circuit>::new(Mode::Public, true);
405 let a = Field::<Circuit>::new(Mode::Private, first);
406 let b = Field::<Circuit>::new(Mode::Public, second);
407 check_ternary("true ? Private : Public", expected, condition, a, b);
408
409 let expected = first;
411 let condition = Boolean::<Circuit>::new(Mode::Public, true);
412 let a = Field::<Circuit>::new(Mode::Private, first);
413 let b = Field::<Circuit>::new(Mode::Private, second);
414 check_ternary("true ? Private : Private", expected, condition, a, b);
415 }
416
417 #[test]
418 fn test_private_condition_and_variable_inputs() {
419 let mut rng = TestRng::default();
420
421 let first = Uniform::rand(&mut rng);
422 let second = Uniform::rand(&mut rng);
423
424 let expected = second;
426 let condition = Boolean::<Circuit>::new(Mode::Private, false);
427 let a = Field::<Circuit>::new(Mode::Public, first);
428 let b = Field::<Circuit>::new(Mode::Public, second);
429 check_ternary("false ? Public : Public", expected, condition, a, b);
430
431 let expected = second;
433 let condition = Boolean::<Circuit>::new(Mode::Private, false);
434 let a = Field::<Circuit>::new(Mode::Public, first);
435 let b = Field::<Circuit>::new(Mode::Private, second);
436 check_ternary("false ? Public : Private", expected, condition, a, b);
437
438 let expected = second;
440 let condition = Boolean::<Circuit>::new(Mode::Private, false);
441 let a = Field::<Circuit>::new(Mode::Private, first);
442 let b = Field::<Circuit>::new(Mode::Public, second);
443 check_ternary("false ? Private : Public", expected, condition, a, b);
444
445 let expected = second;
447 let condition = Boolean::<Circuit>::new(Mode::Private, false);
448 let a = Field::<Circuit>::new(Mode::Private, first);
449 let b = Field::<Circuit>::new(Mode::Private, second);
450 check_ternary("false ? Private : Private", expected, condition, a, b);
451
452 let expected = first;
454 let condition = Boolean::<Circuit>::new(Mode::Private, true);
455 let a = Field::<Circuit>::new(Mode::Public, first);
456 let b = Field::<Circuit>::new(Mode::Public, second);
457 check_ternary("true ? Public : Public", expected, condition, a, b);
458
459 let expected = first;
461 let condition = Boolean::<Circuit>::new(Mode::Private, true);
462 let a = Field::<Circuit>::new(Mode::Public, first);
463 let b = Field::<Circuit>::new(Mode::Private, second);
464 check_ternary("true ? Public : Private", expected, condition, a, b);
465
466 let expected = first;
468 let condition = Boolean::<Circuit>::new(Mode::Private, true);
469 let a = Field::<Circuit>::new(Mode::Private, first);
470 let b = Field::<Circuit>::new(Mode::Public, second);
471 check_ternary("true ? Private : Public", expected, condition, a, b);
472
473 let expected = first;
475 let condition = Boolean::<Circuit>::new(Mode::Private, true);
476 let a = Field::<Circuit>::new(Mode::Private, first);
477 let b = Field::<Circuit>::new(Mode::Private, second);
478 check_ternary("true ? Private : Private", expected, condition, a, b);
479 }
480}