1use crate::{
5 dummy::{Dummy, DummyVal},
6 fancy::Fancy,
7 informer::Informer,
8};
9use swanky_channel::Channel;
10use swanky_error::Result;
11
12mod binary;
13pub use binary::{BinaryCircuit, BinaryGate};
14
15pub trait CircuitExecutor<F: Fancy> {
49 fn execute(
51 &self,
52 backend: &mut F,
53 inputs: &[F::Item],
54 channel: &mut Channel,
55 ) -> Result<Vec<F::Item>>;
56 fn ninputs(&self) -> usize;
58 fn modulus(&self, i: usize) -> u16;
60}
61
62pub trait CircuitInfo {
67 fn print_info(&self) -> swanky_error::Result<()>;
69}
70
71impl<C: CircuitExecutor<Informer<Dummy>>> CircuitInfo for C {
72 fn print_info(&self) -> swanky_error::Result<()> {
73 let mut informer = crate::informer::Informer::new(Dummy::new());
74
75 let inputs = Channel::with(std::io::empty(), |channel| {
77 (0..self.ninputs())
78 .map(|i| informer.encode(0, self.modulus(i), channel))
79 .collect::<swanky_error::Result<Vec<DummyVal>>>()
80 })?;
81
82 Channel::with(std::io::empty(), |c| {
83 self.execute(&mut informer, &inputs, c)
84 })?;
85 println!("{}", informer.stats());
86 Ok(())
87 }
88}
89
90pub mod circuits {
91 pub mod fancy {
94 use crate::{Fancy, circuit::CircuitExecutor};
97 use swanky_channel::Channel;
98 use swanky_error::Result;
99
100 pub struct TestBinaryOutputs(pub usize);
102 impl<F: Fancy> CircuitExecutor<F> for TestBinaryOutputs {
103 fn execute(
104 &self,
105 backend: &mut F,
106 inputs: &[<F as Fancy>::Item],
107 channel: &mut Channel,
108 ) -> Result<Vec<<F as Fancy>::Item>> {
109 backend.outputs(inputs, channel)?;
110 Ok(inputs.to_vec())
111 }
112
113 fn ninputs(&self) -> usize {
114 self.0
115 }
116
117 fn modulus(&self, _: usize) -> u16 {
118 2
119 }
120 }
121
122 pub struct TestBinaryConstant;
124 impl<F: Fancy> CircuitExecutor<F> for TestBinaryConstant {
125 fn execute(
126 &self,
127 backend: &mut F,
128 _inputs: &[F::Item],
129 channel: &mut Channel,
130 ) -> Result<Vec<F::Item>> {
131 let outputs = vec![
132 backend.constant(0, 2, channel)?,
133 backend.constant(1, 2, channel)?,
134 ];
135 backend.outputs(&outputs, channel)?;
136 Ok(outputs)
137 }
138
139 fn ninputs(&self) -> usize {
140 0
141 }
142
143 fn modulus(&self, _: usize) -> u16 {
144 2
145 }
146 }
147 }
148
149 pub mod binary {
150 use crate::{BinaryBundle, BundleGadgets, FancyBinary, circuit::CircuitExecutor};
153 use swanky_channel::Channel;
154 use swanky_error::Result;
155
156 pub struct TestNegateGate;
158 impl<F: FancyBinary> CircuitExecutor<F> for TestNegateGate {
159 fn execute(
160 &self,
161 backend: &mut F,
162 inputs: &[<F as crate::Fancy>::Item],
163 channel: &mut Channel,
164 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
165 let output = backend.negate(&inputs[0]);
166 backend.output(&output, channel)?;
167 Ok(vec![output])
168 }
169
170 fn ninputs(&self) -> usize {
171 1
172 }
173
174 fn modulus(&self, _: usize) -> u16 {
175 2
176 }
177 }
178
179 pub struct TestAndGate;
181 impl<F: FancyBinary> CircuitExecutor<F> for TestAndGate {
182 fn execute(
183 &self,
184 backend: &mut F,
185 inputs: &[F::Item],
186 channel: &mut Channel,
187 ) -> Result<Vec<F::Item>> {
188 let output = backend.and(&inputs[0], &inputs[1], channel)?;
189 backend.output(&output, channel)?;
190 Ok(vec![output])
191 }
192
193 fn ninputs(&self) -> usize {
194 2
195 }
196
197 fn modulus(&self, _: usize) -> u16 {
198 2
199 }
200 }
201
202 pub struct TestAndGateFanN(pub usize);
204 impl<F: FancyBinary> CircuitExecutor<F> for TestAndGateFanN {
205 fn execute(
206 &self,
207 backend: &mut F,
208 inputs: &[F::Item],
209 channel: &mut Channel,
210 ) -> Result<Vec<F::Item>> {
211 let output = backend.and_many(inputs, channel)?;
212 backend.output(&output, channel)?;
213 Ok(vec![output])
214 }
215
216 fn ninputs(&self) -> usize {
217 self.0
218 }
219
220 fn modulus(&self, _: usize) -> u16 {
221 2
222 }
223 }
224
225 pub struct TestOrGateFanN(pub usize);
227 impl<F: FancyBinary> CircuitExecutor<F> for TestOrGateFanN {
228 fn execute(
229 &self,
230 backend: &mut F,
231 inputs: &[F::Item],
232 channel: &mut Channel,
233 ) -> Result<Vec<F::Item>> {
234 let output = backend.or_many(inputs, channel)?;
235 backend.output(&output, channel)?;
236 Ok(vec![output])
237 }
238
239 fn ninputs(&self) -> usize {
240 self.0
241 }
242
243 fn modulus(&self, _: usize) -> u16 {
244 2
245 }
246 }
247
248 pub struct TestXorGateFanN(pub usize);
250 impl<F: FancyBinary> CircuitExecutor<F> for TestXorGateFanN {
251 fn execute(
252 &self,
253 backend: &mut F,
254 inputs: &[F::Item],
255 channel: &mut Channel,
256 ) -> Result<Vec<F::Item>> {
257 let output = backend.xor_many(inputs);
258 backend.output(&output, channel)?;
259 Ok(vec![output])
260 }
261
262 fn ninputs(&self) -> usize {
263 self.0
264 }
265
266 fn modulus(&self, _: usize) -> u16 {
267 2
268 }
269 }
270
271 pub struct TestBinaryNegate(pub usize);
273 impl<F: FancyBinary> CircuitExecutor<F> for TestBinaryNegate {
274 fn execute(
275 &self,
276 backend: &mut F,
277 inputs: &[<F as crate::Fancy>::Item],
278 channel: &mut Channel,
279 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
280 let not =
281 BinaryBundle::new(inputs.iter().map(|x| backend.negate(x)).collect::<Vec<_>>());
282 backend.output_bundle(¬, channel)?;
283 Ok(not.wires().to_vec())
284 }
285
286 fn ninputs(&self) -> usize {
287 self.0
288 }
289
290 fn modulus(&self, _: usize) -> u16 {
291 2
292 }
293 }
294 }
295
296 pub mod arithmetic {
297 use crate::{FancyArithmetic, circuit::CircuitExecutor};
300 use swanky_channel::Channel;
301 use swanky_error::Result;
302
303 pub struct TestAddition(pub u16);
305 impl<F: FancyArithmetic> CircuitExecutor<F> for TestAddition {
306 fn execute(
307 &self,
308 backend: &mut F,
309 inputs: &[F::Item],
310 _: &mut Channel,
311 ) -> swanky_error::Result<Vec<F::Item>> {
312 let output = backend.add(&inputs[0], &inputs[1]);
313 Ok(vec![output])
314 }
315
316 fn ninputs(&self) -> usize {
317 2
318 }
319
320 fn modulus(&self, _: usize) -> u16 {
321 self.0
322 }
323 }
324
325 pub struct TestAddMany(pub u16, pub usize);
327 impl<F: FancyArithmetic> CircuitExecutor<F> for TestAddMany {
328 fn execute(
329 &self,
330 backend: &mut F,
331 inputs: &[F::Item],
332 channel: &mut Channel,
333 ) -> Result<Vec<F::Item>> {
334 let output = backend.add_many(inputs);
335 backend.output(&output, channel)?;
336 Ok(vec![output])
337 }
338
339 fn ninputs(&self) -> usize {
340 self.1
341 }
342
343 fn modulus(&self, _: usize) -> u16 {
344 self.0
345 }
346 }
347
348 pub struct TestSubtraction(pub u16);
350 impl<F: FancyArithmetic> CircuitExecutor<F> for TestSubtraction {
351 fn execute(
352 &self,
353 backend: &mut F,
354 inputs: &[F::Item],
355 _: &mut Channel,
356 ) -> swanky_error::Result<Vec<F::Item>> {
357 let z = backend.sub(&inputs[0], &inputs[1]);
358 Ok(vec![z])
359 }
360
361 fn ninputs(&self) -> usize {
362 2
363 }
364
365 fn modulus(&self, _: usize) -> u16 {
366 self.0
367 }
368 }
369
370 pub struct TestMulGate(pub u16);
372 impl<F: FancyArithmetic> CircuitExecutor<F> for TestMulGate {
373 fn execute(
374 &self,
375 backend: &mut F,
376 inputs: &[F::Item],
377 channel: &mut Channel,
378 ) -> Result<Vec<F::Item>> {
379 let output = backend.mul(&inputs[0], &inputs[1], channel)?;
380 backend.output(&output, channel)?;
381 Ok(vec![output])
382 }
383
384 fn ninputs(&self) -> usize {
385 2
386 }
387
388 fn modulus(&self, _: usize) -> u16 {
389 self.0
390 }
391 }
392
393 pub struct TestMulGateUnequalMods(pub [u16; 2]);
396 impl<F: FancyArithmetic> CircuitExecutor<F> for TestMulGateUnequalMods {
397 fn execute(
398 &self,
399 backend: &mut F,
400 inputs: &[F::Item],
401 channel: &mut Channel,
402 ) -> Result<Vec<F::Item>> {
403 let output = backend.mul(&inputs[0], &inputs[1], channel)?;
404 backend.output(&output, channel)?;
405 Ok(vec![output])
406 }
407
408 fn ninputs(&self) -> usize {
409 2
410 }
411
412 fn modulus(&self, i: usize) -> u16 {
413 self.0[i]
414 }
415 }
416
417 pub struct TestCmul(pub u16, pub u16);
419 impl<F: FancyArithmetic> CircuitExecutor<F> for TestCmul {
420 fn execute(
421 &self,
422 backend: &mut F,
423 inputs: &[<F as crate::Fancy>::Item],
424 channel: &mut Channel,
425 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
426 let output = backend.cmul(&inputs[0], self.1);
427 backend.output(&output, channel)?;
428 Ok(vec![output])
429 }
430
431 fn ninputs(&self) -> usize {
432 1
433 }
434
435 fn modulus(&self, _: usize) -> u16 {
436 self.0
437 }
438 }
439
440 pub struct TestConstants(pub u16, pub u16);
442 impl<F: FancyArithmetic> CircuitExecutor<F> for TestConstants {
443 fn execute(
444 &self,
445 backend: &mut F,
446 inputs: &[F::Item],
447 channel: &mut Channel,
448 ) -> Result<Vec<F::Item>> {
449 let constant = backend.constant(self.1, self.0, channel)?;
450 let output = backend.add(&inputs[0], &constant);
451 backend.output(&output, channel)?;
452 Ok(vec![output])
453 }
454
455 fn ninputs(&self) -> usize {
456 1
457 }
458
459 fn modulus(&self, _: usize) -> u16 {
460 self.0
461 }
462 }
463 }
464
465 pub mod proj {
466 use crate::{FancyArithmetic, FancyProj, circuit::CircuitExecutor};
469 use swanky_channel::Channel;
470 use swanky_error::Result;
471
472 pub struct TestProj(pub u16);
474 impl<F: FancyProj> CircuitExecutor<F> for TestProj {
475 fn execute(
476 &self,
477 backend: &mut F,
478 inputs: &[<F as crate::Fancy>::Item],
479 channel: &mut Channel,
480 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
481 let tab = (0..self.0).map(|i| (i + 1) % self.0).collect();
482 let output = backend.proj(&inputs[0], self.0, Some(tab), channel)?;
483 backend.output(&output, channel)?;
484 Ok(vec![output])
485 }
486
487 fn ninputs(&self) -> usize {
488 1
489 }
490
491 fn modulus(&self, _: usize) -> u16 {
492 self.0
493 }
494 }
495
496 pub struct TestProjRand(pub u16, pub Vec<u16>);
498 impl<F: FancyProj> CircuitExecutor<F> for TestProjRand {
499 fn execute(
500 &self,
501 backend: &mut F,
502 inputs: &[<F as crate::Fancy>::Item],
503 channel: &mut Channel,
504 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
505 let output = backend.proj(&inputs[0], self.0, Some(self.1.clone()), channel)?;
506 backend.output(&output, channel)?;
507 Ok(vec![output])
508 }
509
510 fn ninputs(&self) -> usize {
511 1
512 }
513
514 fn modulus(&self, _: usize) -> u16 {
515 self.0
516 }
517 }
518
519 pub struct TestModChange(pub u16, pub u16);
521 impl<F: FancyProj> CircuitExecutor<F> for TestModChange {
522 fn execute(
523 &self,
524 backend: &mut F,
525 inputs: &[F::Item],
526 channel: &mut Channel,
527 ) -> Result<Vec<F::Item>> {
528 let y = backend.mod_change(&inputs[0], self.1, channel)?;
529 let z = backend.mod_change(&y, self.0, channel)?;
530 backend.output(&z, channel)?;
531 Ok(vec![z])
532 }
533
534 fn ninputs(&self) -> usize {
535 1
536 }
537
538 fn modulus(&self, _: usize) -> u16 {
539 self.0
540 }
541 }
542
543 pub struct TestAddManyModChange(pub usize);
546 impl<F: FancyProj + FancyArithmetic> CircuitExecutor<F> for TestAddManyModChange {
547 fn execute(
548 &self,
549 backend: &mut F,
550 inputs: &[F::Item],
551 channel: &mut Channel,
552 ) -> Result<Vec<F::Item>> {
553 let wires = inputs
554 .iter()
555 .map(|x| backend.mod_change(x, self.0 as u16 + 1, channel))
556 .collect::<Result<Vec<_>>>()?;
557 let output = backend.add_many(&wires);
558 backend.output(&output, channel)?;
559 Ok(vec![output])
560 }
561
562 fn ninputs(&self) -> usize {
563 self.0
564 }
565
566 fn modulus(&self, _: usize) -> u16 {
567 2
568 }
569 }
570 }
571
572 pub mod bundle_gadgets {
573 use crate::{BinaryBundle, BundleGadgets, CrtBundle, circuit::CircuitExecutor};
576 use swanky_channel::Channel;
577 use swanky_error::Result;
578
579 pub struct TestBundleInputOutput(pub Vec<u16>);
581 impl<F: BundleGadgets> CircuitExecutor<F> for TestBundleInputOutput {
582 fn execute(
583 &self,
584 backend: &mut F,
585 inputs: &[F::Item],
586 channel: &mut Channel,
587 ) -> Result<Vec<F::Item>> {
588 let output = CrtBundle::new(inputs.to_vec());
589 backend.output_bundle(&output, channel)?;
590 Ok(output.wires().to_vec())
591 }
592
593 fn ninputs(&self) -> usize {
594 self.0.len()
595 }
596
597 fn modulus(&self, i: usize) -> u16 {
598 self.0[i]
599 }
600 }
601
602 pub struct TestShiftExtend(pub usize, pub usize);
604 impl<F: BundleGadgets> CircuitExecutor<F> for TestShiftExtend {
605 fn execute(
606 &self,
607 backend: &mut F,
608 inputs: &[<F as crate::Fancy>::Item],
609 channel: &mut Channel,
610 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
611 let x = BinaryBundle::new(inputs.to_vec());
612 let z = backend.shift_extend(&x, self.1, channel)?;
613 backend.output_bundle(&z, channel)?;
614 Ok(z.wires().to_vec())
615 }
616
617 fn ninputs(&self) -> usize {
618 self.0
619 }
620
621 fn modulus(&self, _: usize) -> u16 {
622 2
623 }
624 }
625 }
626
627 pub mod crt_gadgets {
628 use crate::{CrtBundle, CrtGadgets, circuit::CircuitExecutor};
631 use swanky_channel::Channel;
632 use swanky_error::Result;
633
634 pub struct TestCrtAddition(pub Vec<u16>);
636 impl<F: CrtGadgets> CircuitExecutor<F> for TestCrtAddition {
637 fn execute(
638 &self,
639 backend: &mut F,
640 inputs: &[F::Item],
641 channel: &mut Channel,
642 ) -> Result<Vec<F::Item>> {
643 let x = CrtBundle::new(inputs[..self.0.len()].to_vec());
644 let y = CrtBundle::new(inputs[self.0.len()..].to_vec());
645 let z = backend.crt_add(&x, &y);
646 backend.output_bundle(&z, channel)?;
647 Ok(z.wires().to_vec())
648 }
649
650 fn ninputs(&self) -> usize {
651 self.0.len() * 2
652 }
653
654 fn modulus(&self, i: usize) -> u16 {
655 self.0[i % self.0.len()]
656 }
657 }
658
659 pub struct TestCrtSubtraction(pub Vec<u16>);
661 impl<F: CrtGadgets> CircuitExecutor<F> for TestCrtSubtraction {
662 fn execute(
663 &self,
664 backend: &mut F,
665 inputs: &[F::Item],
666 channel: &mut Channel,
667 ) -> Result<Vec<F::Item>> {
668 let x = CrtBundle::new(inputs[..self.0.len()].to_vec());
669 let y = CrtBundle::new(inputs[self.0.len()..].to_vec());
670 let z = backend.crt_sub(&x, &y);
671 backend.output_bundle(&z, channel)?;
672 Ok(z.wires().to_vec())
673 }
674
675 fn ninputs(&self) -> usize {
676 self.0.len() * 2
677 }
678
679 fn modulus(&self, i: usize) -> u16 {
680 self.0[i % self.0.len()]
681 }
682 }
683
684 pub struct TestCrtCmul(pub Vec<u16>, pub u128);
686 impl<F: CrtGadgets> CircuitExecutor<F> for TestCrtCmul {
687 fn execute(
688 &self,
689 backend: &mut F,
690 inputs: &[F::Item],
691 channel: &mut Channel,
692 ) -> Result<Vec<F::Item>> {
693 let x = CrtBundle::new(inputs.to_vec());
694 let z = backend.crt_cmul(&x, self.1);
695 backend.output_bundle(&z, channel)?;
696 Ok(z.wires().to_vec())
697 }
698
699 fn ninputs(&self) -> usize {
700 self.0.len()
701 }
702
703 fn modulus(&self, i: usize) -> u16 {
704 self.0[i]
705 }
706 }
707 }
708
709 pub mod arithmetic_bundle_gadgets {
710 use crate::{ArithmeticBundleGadgets, BundleGadgets, CrtBundle, circuit::CircuitExecutor};
713 use swanky_channel::Channel;
714 use swanky_error::Result;
715
716 pub struct TestCrtMultiplication(pub Vec<u16>);
718 impl<F: ArithmeticBundleGadgets> CircuitExecutor<F> for TestCrtMultiplication {
719 fn execute(
720 &self,
721 backend: &mut F,
722 inputs: &[F::Item],
723 channel: &mut Channel,
724 ) -> Result<Vec<F::Item>> {
725 let x = CrtBundle::new(inputs[..self.0.len()].to_vec());
726 let y = CrtBundle::new(inputs[self.0.len()..].to_vec());
727 let z = backend.mul_bundles(&x, &y, channel)?;
728 backend.output_bundle(&z, channel)?;
729 Ok(z.wires().to_vec())
730 }
731
732 fn ninputs(&self) -> usize {
733 self.0.len() * 2
734 }
735
736 fn modulus(&self, i: usize) -> u16 {
737 self.0[i % self.0.len()]
738 }
739 }
740
741 pub struct TestMask(pub Vec<u16>);
743 impl<F: ArithmeticBundleGadgets> CircuitExecutor<F> for TestMask {
744 fn execute(
745 &self,
746 backend: &mut F,
747 inputs: &[F::Item],
748 channel: &mut Channel,
749 ) -> Result<Vec<F::Item>> {
750 let b = &inputs[0];
751 let x = CrtBundle::new(inputs[1..self.0.len() + 1].to_vec());
752 let z = backend.mask(b, &x, channel)?;
753 backend.output_bundle(&z, channel)?;
754 Ok(z.wires().to_vec())
755 }
756
757 fn ninputs(&self) -> usize {
758 self.0.len() + 1
759 }
760
761 fn modulus(&self, i: usize) -> u16 {
762 if i == 0 { 2 } else { self.0[i - 1] }
763 }
764 }
765 }
766
767 pub mod crt_proj_gadgets {
768 use crate::{CrtBundle, CrtProjGadgets, circuit::CircuitExecutor};
771 use swanky_channel::Channel;
772 use swanky_error::Result;
773
774 pub struct TestCrtCexp(pub Vec<u16>, pub u16);
776 impl<F: CrtProjGadgets> CircuitExecutor<F> for TestCrtCexp {
777 fn execute(
778 &self,
779 backend: &mut F,
780 inputs: &[F::Item],
781 channel: &mut Channel,
782 ) -> Result<Vec<F::Item>> {
783 let x = CrtBundle::new(inputs.to_vec());
784 let z = backend.crt_cexp(&x, self.1, channel)?;
785 backend.output_bundle(&z, channel)?;
786 Ok(z.wires().to_vec())
787 }
788
789 fn ninputs(&self) -> usize {
790 self.0.len()
791 }
792
793 fn modulus(&self, i: usize) -> u16 {
794 self.0[i]
795 }
796 }
797
798 pub struct TestCrtDivision(pub Vec<u16>);
800 impl<F: CrtProjGadgets> CircuitExecutor<F> for TestCrtDivision {
801 fn execute(
802 &self,
803 backend: &mut F,
804 inputs: &[F::Item],
805 channel: &mut Channel,
806 ) -> Result<Vec<F::Item>> {
807 let x = CrtBundle::new(inputs[..self.0.len()].to_vec());
808 let y = CrtBundle::new(inputs[self.0.len()..].to_vec());
809 let z = backend.crt_div(&x, &y, channel)?;
810 backend.output_bundle(&z, channel)?;
811 Ok(z.wires().to_vec())
812 }
813
814 fn ninputs(&self) -> usize {
815 self.0.len() * 2
816 }
817
818 fn modulus(&self, i: usize) -> u16 {
819 self.0[i % self.0.len()]
820 }
821 }
822
823 pub struct TestCrtRemainder(pub Vec<u16>, pub u16);
825 impl<F: CrtProjGadgets> CircuitExecutor<F> for TestCrtRemainder {
826 fn execute(
827 &self,
828 backend: &mut F,
829 inputs: &[F::Item],
830 channel: &mut Channel,
831 ) -> Result<Vec<F::Item>> {
832 let x = CrtBundle::new(inputs.to_vec());
833 let z = backend.crt_rem(&x, self.1, channel)?;
834 backend.output_bundle(&z, channel)?;
835 Ok(z.wires().to_vec())
836 }
837
838 fn ninputs(&self) -> usize {
839 self.0.len()
840 }
841
842 fn modulus(&self, i: usize) -> u16 {
843 self.0[i]
844 }
845 }
846
847 pub struct TestComplexGadget(pub Vec<u16>, pub usize);
849 impl<F: CrtProjGadgets> CircuitExecutor<F> for TestComplexGadget {
850 fn execute(
851 &self,
852 backend: &mut F,
853 inputs: &[<F as crate::Fancy>::Item],
854 channel: &mut Channel,
855 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
856 let inputs = inputs
857 .chunks_exact(self.0.len())
858 .map(|x| CrtBundle::new(x.to_vec()))
859 .collect::<Vec<_>>();
860 let mut outputs = Vec::with_capacity(inputs.len());
861 for x in inputs.iter() {
862 let c = backend.crt_constant_bundle(1, x.composite_modulus(), channel)?;
863 let y = backend.crt_mul(x, &c, channel)?;
864 let z = backend.crt_relu(&y, "100%", None, channel)?;
865 outputs.push(z);
866 }
867 backend.crt_outputs(&outputs, channel)?;
868 Ok(outputs
869 .iter()
870 .map(|out| out.wires().to_vec())
871 .collect::<Vec<_>>()
872 .concat())
873 }
874
875 fn ninputs(&self) -> usize {
876 self.1
877 }
878
879 fn modulus(&self, i: usize) -> u16 {
880 self.0[i % self.0.len()]
881 }
882 }
883
884 pub struct TestRelu(pub Vec<u16>);
886 impl<F: CrtProjGadgets> CircuitExecutor<F> for TestRelu {
887 fn execute(
888 &self,
889 backend: &mut F,
890 inputs: &[<F as crate::Fancy>::Item],
891 channel: &mut Channel,
892 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
893 let x = CrtBundle::new(inputs.to_vec());
894 let z = backend.crt_relu(&x, "100%", None, channel)?;
895 backend.output_bundle(&z, channel)?;
896 Ok(z.wires().to_vec())
897 }
898
899 fn ninputs(&self) -> usize {
900 self.0.len()
901 }
902
903 fn modulus(&self, i: usize) -> u16 {
904 self.0[i]
905 }
906 }
907
908 pub struct TestSgn(pub Vec<u16>);
910 impl<F: CrtProjGadgets> CircuitExecutor<F> for TestSgn {
911 fn execute(
912 &self,
913 backend: &mut F,
914 inputs: &[<F as crate::Fancy>::Item],
915 channel: &mut Channel,
916 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
917 let x = CrtBundle::new(inputs.to_vec());
918 let z = backend.crt_sgn(&x, "100%", None, channel)?;
919 backend.output_bundle(&z, channel)?;
920 Ok(z.wires().to_vec())
921 }
922
923 fn ninputs(&self) -> usize {
924 self.0.len()
925 }
926
927 fn modulus(&self, i: usize) -> u16 {
928 self.0[i]
929 }
930 }
931
932 pub struct TestLeq(pub Vec<u16>);
934 impl<F: CrtProjGadgets> CircuitExecutor<F> for TestLeq {
935 fn execute(
936 &self,
937 backend: &mut F,
938 inputs: &[<F as crate::Fancy>::Item],
939 channel: &mut Channel,
940 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
941 let x = CrtBundle::new(inputs[..self.0.len()].to_vec());
942 let y = CrtBundle::new(inputs[self.0.len()..].to_vec());
943 let z = backend.crt_lt(&x, &y, "100%", channel)?;
944 backend.output(&z, channel)?;
945 Ok(vec![z])
946 }
947
948 fn ninputs(&self) -> usize {
949 self.0.len() * 2
950 }
951
952 fn modulus(&self, i: usize) -> u16 {
953 self.0[i % self.0.len()]
954 }
955 }
956
957 pub struct TestMax(pub Vec<u16>, pub usize);
959 impl<F: CrtProjGadgets> CircuitExecutor<F> for TestMax {
960 fn execute(
961 &self,
962 backend: &mut F,
963 inputs: &[<F as crate::Fancy>::Item],
964 channel: &mut Channel,
965 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
966 let xs = inputs
967 .chunks_exact(self.0.len())
968 .map(|v| CrtBundle::new(v.to_vec()))
969 .collect::<Vec<_>>();
970 let z = backend.crt_max(&xs, "100%", channel)?;
971 backend.output_bundle(&z, channel)?;
972 Ok(z.wires().to_vec())
973 }
974
975 fn ninputs(&self) -> usize {
976 self.0.len() * self.1
977 }
978
979 fn modulus(&self, i: usize) -> u16 {
980 self.0[i % self.0.len()]
981 }
982 }
983
984 pub struct TestCrtToPmr(pub Vec<u16>);
986 impl<F: CrtProjGadgets> CircuitExecutor<F> for TestCrtToPmr {
987 fn execute(
988 &self,
989 backend: &mut F,
990 inputs: &[<F as crate::Fancy>::Item],
991 channel: &mut Channel,
992 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
993 let x = CrtBundle::new(inputs.to_vec());
994 let z = backend.crt_to_pmr(&x, channel)?;
995 backend.output_bundle(&z, channel)?;
996 Ok(z.wires().to_vec())
997 }
998
999 fn ninputs(&self) -> usize {
1000 self.0.len()
1001 }
1002
1003 fn modulus(&self, i: usize) -> u16 {
1004 self.0[i]
1005 }
1006 }
1007
1008 pub struct TestPmrLessThan(pub Vec<u16>);
1010 impl<F: CrtProjGadgets> CircuitExecutor<F> for TestPmrLessThan {
1011 fn execute(
1012 &self,
1013 backend: &mut F,
1014 inputs: &[<F as crate::Fancy>::Item],
1015 channel: &mut Channel,
1016 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1017 let x = CrtBundle::new(inputs[..self.0.len()].to_vec());
1018 let y = CrtBundle::new(inputs[self.0.len()..].to_vec());
1019 let z = backend.pmr_lt(&x, &y, channel)?;
1020 backend.output(&z, channel)?;
1021 Ok(vec![z])
1022 }
1023
1024 fn ninputs(&self) -> usize {
1025 self.0.len() * 2
1026 }
1027
1028 fn modulus(&self, i: usize) -> u16 {
1029 self.0[i % self.0.len()]
1030 }
1031 }
1032
1033 pub struct TestPmrGreaterThanOrEqual(pub Vec<u16>);
1035 impl<F: CrtProjGadgets> CircuitExecutor<F> for TestPmrGreaterThanOrEqual {
1036 fn execute(
1037 &self,
1038 backend: &mut F,
1039 inputs: &[<F as crate::Fancy>::Item],
1040 channel: &mut Channel,
1041 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1042 let x = CrtBundle::new(inputs[..self.0.len()].to_vec());
1043 let y = CrtBundle::new(inputs[self.0.len()..].to_vec());
1044 let z = backend.pmr_geq(&x, &y, channel)?;
1045 backend.output(&z, channel)?;
1046 Ok(vec![z])
1047 }
1048
1049 fn ninputs(&self) -> usize {
1050 self.0.len() * 2
1051 }
1052
1053 fn modulus(&self, i: usize) -> u16 {
1054 self.0[i % self.0.len()]
1055 }
1056 }
1057 }
1058
1059 pub mod arithmetic_proj_bundle_gadgets {
1060 use crate::{
1063 ArithmeticProjBundleGadgets, Bundle, BundleGadgets, CrtBundle, circuit::CircuitExecutor,
1064 };
1065 use swanky_channel::Channel;
1066 use swanky_error::Result;
1067
1068 pub struct TestEqBundles(pub Vec<u16>);
1070 impl<F: ArithmeticProjBundleGadgets> CircuitExecutor<F> for TestEqBundles {
1071 fn execute(
1072 &self,
1073 backend: &mut F,
1074 inputs: &[F::Item],
1075 channel: &mut Channel,
1076 ) -> Result<Vec<F::Item>> {
1077 let x = CrtBundle::new(inputs[..self.0.len()].to_vec());
1078 let y = CrtBundle::new(inputs[self.0.len()..].to_vec());
1079 let z = backend.eq_bundles(&x, &y, channel)?;
1080 backend.output(&z, channel)?;
1081 Ok(vec![z])
1082 }
1083
1084 fn ninputs(&self) -> usize {
1085 self.0.len() * 2
1086 }
1087
1088 fn modulus(&self, i: usize) -> u16 {
1089 self.0[i % self.0.len()]
1090 }
1091 }
1092
1093 pub struct TestMixedRadixAddition(pub Vec<u16>, pub usize);
1095 impl<F: ArithmeticProjBundleGadgets> CircuitExecutor<F> for TestMixedRadixAddition {
1096 fn execute(
1097 &self,
1098 backend: &mut F,
1099 inputs: &[<F as crate::Fancy>::Item],
1100 channel: &mut Channel,
1101 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1102 let xs = inputs
1103 .chunks_exact(self.0.len())
1104 .map(|v| Bundle::new(v.to_vec()))
1105 .collect::<Vec<_>>();
1106 let z = backend.mixed_radix_addition(&xs, channel)?;
1107 backend.output_bundle(&z, channel)?;
1108 Ok(z.wires().to_vec())
1109 }
1110
1111 fn ninputs(&self) -> usize {
1112 self.1 * self.0.len()
1113 }
1114
1115 fn modulus(&self, i: usize) -> u16 {
1116 self.0[i % self.0.len()]
1117 }
1118 }
1119
1120 pub struct TestMixedRadixAdditionMSBOnly(pub Vec<u16>, pub usize);
1122 impl<F: ArithmeticProjBundleGadgets> CircuitExecutor<F> for TestMixedRadixAdditionMSBOnly {
1123 fn execute(
1124 &self,
1125 backend: &mut F,
1126 inputs: &[<F as crate::Fancy>::Item],
1127 channel: &mut Channel,
1128 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1129 let xs = inputs
1130 .chunks_exact(self.0.len())
1131 .map(|v| Bundle::new(v.to_vec()))
1132 .collect::<Vec<_>>();
1133 let z = backend.mixed_radix_addition_msb_only(&xs, channel)?;
1134 backend.output(&z, channel)?;
1135 Ok(vec![z])
1136 }
1137
1138 fn ninputs(&self) -> usize {
1139 self.0.len() * self.1
1140 }
1141
1142 fn modulus(&self, i: usize) -> u16 {
1143 self.0[i % self.0.len()]
1144 }
1145 }
1146 }
1147
1148 pub mod binary_gadgets {
1149 use crate::{BinaryBundle, BinaryGadgets, circuit::CircuitExecutor};
1152 use swanky_channel::Channel;
1153 use swanky_error::Result;
1154
1155 pub struct TestConstantBundle(pub u128, pub usize);
1157 impl<F: BinaryGadgets> CircuitExecutor<F> for TestConstantBundle {
1158 fn execute(
1159 &self,
1160 backend: &mut F,
1161 _inputs: &[<F as crate::Fancy>::Item],
1162 channel: &mut Channel,
1163 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1164 let value = backend.bin_constant_bundle(self.0, self.1, channel)?;
1165 backend.output_bundle(&value, channel)?;
1166 Ok(value.wires().to_vec())
1167 }
1168
1169 fn ninputs(&self) -> usize {
1170 0
1171 }
1172
1173 fn modulus(&self, _: usize) -> u16 {
1174 2
1175 }
1176 }
1177
1178 pub struct TestBinaryAnd(pub usize);
1180 impl<F: BinaryGadgets> CircuitExecutor<F> for TestBinaryAnd {
1181 fn execute(
1182 &self,
1183 backend: &mut F,
1184 inputs: &[<F as crate::Fancy>::Item],
1185 channel: &mut Channel,
1186 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1187 let x = BinaryBundle::new(inputs[..self.0].to_vec());
1188 let y = BinaryBundle::new(inputs[self.0..].to_vec());
1189 let z = backend.bin_and(&x, &y, channel)?;
1190 backend.output_bundle(&z, channel)?;
1191 Ok(z.wires().to_vec())
1192 }
1193
1194 fn ninputs(&self) -> usize {
1195 self.0 * 2
1196 }
1197
1198 fn modulus(&self, _: usize) -> u16 {
1199 2
1200 }
1201 }
1202
1203 pub struct TestBinaryAddition(pub usize);
1205 impl<F: BinaryGadgets> CircuitExecutor<F> for TestBinaryAddition {
1206 fn execute(
1207 &self,
1208 backend: &mut F,
1209 inputs: &[<F as crate::Fancy>::Item],
1210 channel: &mut Channel,
1211 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1212 let x = BinaryBundle::new(inputs[..self.0].to_vec());
1213 let y = BinaryBundle::new(inputs[self.0..].to_vec());
1214 let (z, carry) = backend.bin_addition(&x, &y, channel)?;
1215 backend.output(&carry, channel)?;
1216 backend.output_bundle(&z, channel)?;
1217 Ok([vec![carry], z.wires().to_vec()].concat())
1218 }
1219
1220 fn ninputs(&self) -> usize {
1221 self.0 * 2
1222 }
1223
1224 fn modulus(&self, _: usize) -> u16 {
1225 2
1226 }
1227 }
1228
1229 pub struct TestBinaryAdditionNoCarry(pub usize);
1231 impl<F: BinaryGadgets> CircuitExecutor<F> for TestBinaryAdditionNoCarry {
1232 fn execute(
1233 &self,
1234 backend: &mut F,
1235 inputs: &[<F as crate::Fancy>::Item],
1236 channel: &mut Channel,
1237 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1238 let x = BinaryBundle::new(inputs[..self.0].to_vec());
1239 let y = BinaryBundle::new(inputs[self.0..].to_vec());
1240 let z = backend.bin_addition_no_carry(&x, &y, channel)?;
1241 backend.output_bundle(&z, channel)?;
1242 Ok(z.wires().to_vec())
1243 }
1244
1245 fn ninputs(&self) -> usize {
1246 self.0 * 2
1247 }
1248
1249 fn modulus(&self, _: usize) -> u16 {
1250 2
1251 }
1252 }
1253
1254 pub struct TestBinarySubtraction(pub usize);
1256 impl<F: BinaryGadgets> CircuitExecutor<F> for TestBinarySubtraction {
1257 fn execute(
1258 &self,
1259 backend: &mut F,
1260 inputs: &[<F as crate::Fancy>::Item],
1261 channel: &mut Channel,
1262 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1263 assert_eq!(inputs.len(), <Self as CircuitExecutor<F>>::ninputs(self));
1264
1265 let x = BinaryBundle::new(inputs[..self.0].to_vec());
1266 let y = BinaryBundle::new(inputs[self.0..].to_vec());
1267 let (z, underflow) = backend.bin_subtraction(&x, &y, channel)?;
1268 backend.output(&underflow, channel)?;
1269 backend.output_bundle(&z, channel)?;
1270 Ok([vec![underflow], z.wires().to_vec()].concat())
1271 }
1272
1273 fn ninputs(&self) -> usize {
1274 self.0 * 2
1275 }
1276
1277 fn modulus(&self, _: usize) -> u16 {
1278 2
1279 }
1280 }
1281
1282 pub struct TestBinaryMultiplication(pub usize);
1284 impl<F: BinaryGadgets> CircuitExecutor<F> for TestBinaryMultiplication {
1285 fn execute(
1286 &self,
1287 backend: &mut F,
1288 inputs: &[<F as crate::Fancy>::Item],
1289 channel: &mut Channel,
1290 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1291 let x = BinaryBundle::new(inputs[..self.0].to_vec());
1292 let y = BinaryBundle::new(inputs[self.0..].to_vec());
1293 let z = backend.bin_mul(&x, &y, channel)?;
1294 backend.output_bundle(&z, channel)?;
1295 Ok(z.wires().to_vec())
1296 }
1297
1298 fn ninputs(&self) -> usize {
1299 self.0 * 2
1300 }
1301
1302 fn modulus(&self, _: usize) -> u16 {
1303 2
1304 }
1305 }
1306
1307 pub struct TestBinaryMultiplicationLowerHalf(pub usize);
1309 impl<F: BinaryGadgets> CircuitExecutor<F> for TestBinaryMultiplicationLowerHalf {
1310 fn execute(
1311 &self,
1312 backend: &mut F,
1313 inputs: &[<F as crate::Fancy>::Item],
1314 channel: &mut Channel,
1315 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1316 let x = BinaryBundle::new(inputs[..self.0].to_vec());
1317 let y = BinaryBundle::new(inputs[self.0..].to_vec());
1318 let z = backend.bin_multiplication_lower_half(&x, &y, channel)?;
1319 backend.output_bundle(&z, channel)?;
1320 Ok(z.wires().to_vec())
1321 }
1322
1323 fn ninputs(&self) -> usize {
1324 self.0 * 2
1325 }
1326
1327 fn modulus(&self, _: usize) -> u16 {
1328 2
1329 }
1330 }
1331
1332 pub struct TestBinaryDivision(pub usize);
1334 impl<F: BinaryGadgets> CircuitExecutor<F> for TestBinaryDivision {
1335 fn execute(
1336 &self,
1337 backend: &mut F,
1338 inputs: &[<F as crate::Fancy>::Item],
1339 channel: &mut Channel,
1340 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1341 let x = BinaryBundle::new(inputs[..self.0].to_vec());
1342 let y = BinaryBundle::new(inputs[self.0..].to_vec());
1343 let z = backend.bin_div(&x, &y, channel)?;
1344 backend.output_bundle(&z, channel)?;
1345 Ok(z.wires().to_vec())
1346 }
1347
1348 fn ninputs(&self) -> usize {
1349 self.0 * 2
1350 }
1351
1352 fn modulus(&self, _: usize) -> u16 {
1353 2
1354 }
1355 }
1356
1357 pub struct TestBinaryLessThan(pub usize);
1359 impl<F: BinaryGadgets> CircuitExecutor<F> for TestBinaryLessThan {
1360 fn execute(
1361 &self,
1362 backend: &mut F,
1363 inputs: &[<F as crate::Fancy>::Item],
1364 channel: &mut Channel,
1365 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1366 let x = BinaryBundle::new(inputs[..self.0].to_vec());
1367 let y = BinaryBundle::new(inputs[self.0..].to_vec());
1368 let z = backend.bin_lt(&x, &y, channel)?;
1369 backend.output(&z, channel)?;
1370 Ok(vec![z])
1371 }
1372
1373 fn ninputs(&self) -> usize {
1374 self.0 * 2
1375 }
1376
1377 fn modulus(&self, _: usize) -> u16 {
1378 2
1379 }
1380 }
1381
1382 pub struct TestBinaryLessThanSigned(pub usize);
1384 impl<F: BinaryGadgets> CircuitExecutor<F> for TestBinaryLessThanSigned {
1385 fn execute(
1386 &self,
1387 backend: &mut F,
1388 inputs: &[<F as crate::Fancy>::Item],
1389 channel: &mut Channel,
1390 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1391 let x = BinaryBundle::new(inputs[..self.0].to_vec());
1392 let y = BinaryBundle::new(inputs[self.0..].to_vec());
1393 let z = backend.bin_lt_signed(&x, &y, channel)?;
1394 backend.output(&z, channel)?;
1395 Ok(vec![z])
1396 }
1397
1398 fn ninputs(&self) -> usize {
1399 self.0 * 2
1400 }
1401
1402 fn modulus(&self, _: usize) -> u16 {
1403 2
1404 }
1405 }
1406
1407 pub struct TestBinaryArithmeticRightShift(pub usize, pub usize);
1409 impl<F: BinaryGadgets> CircuitExecutor<F> for TestBinaryArithmeticRightShift {
1410 fn execute(
1411 &self,
1412 backend: &mut F,
1413 inputs: &[<F as crate::Fancy>::Item],
1414 channel: &mut Channel,
1415 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1416 let x = BinaryBundle::new(inputs.to_vec());
1417 let z = backend.bin_rsa(&x, self.1);
1418 backend.output_bundle(&z, channel)?;
1419 Ok(z.wires().to_vec())
1420 }
1421
1422 fn ninputs(&self) -> usize {
1423 self.0
1424 }
1425
1426 fn modulus(&self, _: usize) -> u16 {
1427 2
1428 }
1429 }
1430
1431 pub struct TestBinaryLogicalRightShift(pub usize, pub usize);
1433 impl<F: BinaryGadgets> CircuitExecutor<F> for TestBinaryLogicalRightShift {
1434 fn execute(
1435 &self,
1436 backend: &mut F,
1437 inputs: &[<F as crate::Fancy>::Item],
1438 channel: &mut Channel,
1439 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1440 let x = BinaryBundle::new(inputs.to_vec());
1441 let z = backend.bin_rsl(&x, self.1, channel)?;
1442 backend.output_bundle(&z, channel)?;
1443 Ok(z.wires().to_vec())
1444 }
1445
1446 fn ninputs(&self) -> usize {
1447 self.0
1448 }
1449
1450 fn modulus(&self, _: usize) -> u16 {
1451 2
1452 }
1453 }
1454
1455 pub struct TestBinaryEqBundles(pub usize);
1457 impl<F: BinaryGadgets> CircuitExecutor<F> for TestBinaryEqBundles {
1458 fn execute(
1459 &self,
1460 backend: &mut F,
1461 inputs: &[<F as crate::Fancy>::Item],
1462 channel: &mut Channel,
1463 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1464 let x = BinaryBundle::new(inputs[..self.0].to_vec());
1465 let y = BinaryBundle::new(inputs[self.0..].to_vec());
1466 let z = backend.bin_eq_bundles(&x, &y, channel)?;
1467 backend.output(&z, channel)?;
1468 Ok(vec![z])
1469 }
1470
1471 fn ninputs(&self) -> usize {
1472 self.0 * 2
1473 }
1474
1475 fn modulus(&self, _: usize) -> u16 {
1476 2
1477 }
1478 }
1479
1480 pub struct TestBinaryAbs(pub usize);
1482 impl<F: BinaryGadgets> CircuitExecutor<F> for TestBinaryAbs {
1483 fn execute(
1484 &self,
1485 backend: &mut F,
1486 inputs: &[<F as crate::Fancy>::Item],
1487 channel: &mut Channel,
1488 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1489 let x = BinaryBundle::new(inputs.to_vec());
1490 let z = backend.bin_abs(&x, channel)?;
1491 backend.output_bundle(&z, channel)?;
1492 Ok(z.wires().to_vec())
1493 }
1494
1495 fn ninputs(&self) -> usize {
1496 self.0
1497 }
1498
1499 fn modulus(&self, _: usize) -> u16 {
1500 2
1501 }
1502 }
1503
1504 pub struct TestBinaryTwosComplement(pub usize);
1506 impl<F: BinaryGadgets> CircuitExecutor<F> for TestBinaryTwosComplement {
1507 fn execute(
1508 &self,
1509 backend: &mut F,
1510 inputs: &[<F as crate::Fancy>::Item],
1511 channel: &mut Channel,
1512 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1513 assert_eq!(inputs.len(), <Self as CircuitExecutor<F>>::ninputs(self));
1514
1515 let x = BinaryBundle::new(inputs.to_vec());
1516 let z = backend.bin_twos_complement(&x, channel)?;
1517 backend.output_bundle(&z, channel)?;
1518 Ok(z.wires().to_vec())
1519 }
1520
1521 fn ninputs(&self) -> usize {
1522 self.0
1523 }
1524
1525 fn modulus(&self, _: usize) -> u16 {
1526 2
1527 }
1528 }
1529
1530 pub struct TestBinaryDemux(pub usize);
1532 impl<F: BinaryGadgets> CircuitExecutor<F> for TestBinaryDemux {
1533 fn execute(
1534 &self,
1535 backend: &mut F,
1536 inputs: &[<F as crate::Fancy>::Item],
1537 channel: &mut Channel,
1538 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1539 let x = BinaryBundle::new(inputs.to_vec());
1540 let output = backend.bin_demux(&x, channel)?;
1541 backend.outputs(&output, channel)?;
1542 Ok(output)
1543 }
1544
1545 fn ninputs(&self) -> usize {
1546 self.0
1547 }
1548
1549 fn modulus(&self, _: usize) -> u16 {
1550 2
1551 }
1552 }
1553
1554 pub struct TestBinaryMax(pub usize, pub usize);
1556 impl<F: BinaryGadgets> CircuitExecutor<F> for TestBinaryMax {
1557 fn execute(
1558 &self,
1559 backend: &mut F,
1560 inputs: &[<F as crate::Fancy>::Item],
1561 channel: &mut Channel,
1562 ) -> Result<Vec<<F as crate::Fancy>::Item>> {
1563 let xs = inputs
1564 .chunks_exact(self.0)
1565 .map(|v| BinaryBundle::new(v.to_vec()))
1566 .collect::<Vec<_>>();
1567 let z = backend.bin_max(&xs, channel)?;
1568 backend.output_bundle(&z, channel)?;
1569 Ok(z.wires().to_vec())
1570 }
1571
1572 fn ninputs(&self) -> usize {
1573 self.0 * self.1
1574 }
1575
1576 fn modulus(&self, _: usize) -> u16 {
1577 2
1578 }
1579 }
1580 }
1581}
1582
1583#[cfg(test)]
1584mod fancy_binary {
1585 use crate::{circuit::circuits, dummy::Dummy, util::RngExt};
1586 use rand::thread_rng;
1587
1588 #[test]
1589 fn and_gate_fan_n() {
1590 let mut rng = thread_rng();
1591 let n = 2 + (rng.gen_usize() % 200);
1592 let c = circuits::binary::TestAndGateFanN(n);
1593
1594 for _ in 0..16 {
1595 let inputs = (0..n).map(|_| rng.gen_bool() as u16).collect::<Vec<_>>();
1596 let expected = inputs.iter().fold(1, |acc, &x| x & acc);
1597 let output = Dummy::eval(&c, &inputs).unwrap()[0];
1598 assert_eq!(output, expected);
1599 }
1600 }
1601
1602 #[test]
1603 fn binary_constant_gates() {
1604 let c = circuits::fancy::TestBinaryConstant;
1605 let inputs = [];
1606 let expected_0 = 0;
1607 let output_0: u16 = Dummy::eval(&c, &inputs).unwrap()[0];
1608 assert_eq!(output_0, expected_0);
1609 let expected_1 = 1;
1610 let output_1 = Dummy::eval(&c, &inputs).unwrap()[1];
1611 assert_eq!(output_1, expected_1);
1612 }
1613
1614 #[test]
1615 fn or_gate_fan_n() {
1616 let mut rng = thread_rng();
1617 let n = 2 + (rng.gen_usize() % 200);
1618 let c = circuits::binary::TestOrGateFanN(n);
1619
1620 for _ in 0..16 {
1621 let inputs = (0..n).map(|_| rng.gen_bool() as u16).collect::<Vec<_>>();
1622 let expected = inputs.iter().fold(0, |acc, &x| x | acc);
1623 let output = Dummy::eval(&c, &inputs).unwrap()[0];
1624 assert_eq!(output, expected);
1625 }
1626 }
1627
1628 #[test]
1629 fn xor_gate_fan_n() {
1630 let mut rng = thread_rng();
1631 let n = 2 + (rng.gen_usize() % 200);
1632 let c = circuits::binary::TestXorGateFanN(n);
1633
1634 for _ in 0..16 {
1635 let inputs = (0..n).map(|_| rng.gen_bool() as u16).collect::<Vec<_>>();
1636 let expected = inputs.iter().fold(0, |acc, &x| x ^ acc);
1637 let output = Dummy::eval(&c, &inputs).unwrap()[0];
1638 assert_eq!(output, expected);
1639 }
1640 }
1641
1642 #[test]
1643 fn binary_half_gate() {
1644 let mut rng = thread_rng();
1645 let c = circuits::binary::TestAndGate;
1646
1647 for _ in 0..16 {
1648 let x = rng.gen_bool() as u16;
1649 let y = rng.gen_bool() as u16;
1650 let output = Dummy::eval(&c, &[x, y]).unwrap()[0];
1651 assert_eq!(output, x * y % 2);
1652 }
1653 }
1654}
1655
1656#[cfg(test)]
1657mod fancy_arithmetic {
1658 use crate::{circuit::circuits, dummy::Dummy, util::RngExt};
1659 use rand::thread_rng;
1660
1661 #[test]
1662 fn constants() {
1663 let mut rng = thread_rng();
1664 let q = rng.gen_modulus();
1665 let c = rng.gen_u16() % q;
1666 let circ = circuits::arithmetic::TestConstants(q, c);
1667
1668 for _ in 0..64 {
1669 let x = rng.gen_u16() % q;
1670 let output = Dummy::eval(&circ, &[x]).unwrap()[0];
1671 assert_eq!(output, (x + c) % q);
1672 }
1673 }
1674
1675 #[test]
1676 fn arithmetic_half_gate() {
1677 let mut rng = thread_rng();
1678 let q = rng.gen_prime();
1679 let c = circuits::arithmetic::TestMulGate(q);
1680
1681 for _ in 0..16 {
1682 let x = rng.gen_u16() % q;
1683 let y = rng.gen_u16() % q;
1684 let output = Dummy::eval(&c, &[x, y]).unwrap()[0];
1685 assert_eq!(output, x * y % q);
1686 }
1687 }
1688}
1689
1690#[cfg(test)]
1691mod fancy_proj {
1692 use crate::{
1693 circuit::{CircuitExecutor, circuits},
1694 dummy::Dummy,
1695 util::RngExt,
1696 };
1697 use rand::thread_rng;
1698
1699 #[test]
1700 fn mod_change() {
1701 let mut rng = thread_rng();
1702 let p = rng.gen_prime();
1703 let q = rng.gen_prime();
1704 let c = circuits::proj::TestModChange(p, q);
1705
1706 for _ in 0..16 {
1707 let x = rng.gen_u16() % p;
1708 let output = Dummy::eval(&c, &[x]).unwrap()[0];
1709 assert_eq!(output, x % q);
1710 }
1711 }
1712
1713 #[test]
1714 fn add_many_mod_change() {
1715 let mut rng = thread_rng();
1716 let n = 113;
1717 let c = circuits::proj::TestAddManyModChange(n);
1718
1719 for _ in 0..64 {
1720 let inputs = (0
1721 ..<circuits::proj::TestAddManyModChange as CircuitExecutor<Dummy>>::ninputs(&c))
1722 .map(|i| {
1723 rng.gen_u16()
1724 % <circuits::proj::TestAddManyModChange as CircuitExecutor<Dummy>>::modulus(
1725 &c, i,
1726 )
1727 })
1728 .collect::<Vec<_>>();
1729 let expected: u16 = inputs.iter().sum();
1730 let output = Dummy::eval(&c, &inputs).unwrap()[0];
1731 assert_eq!(output, expected);
1732 }
1733 }
1734}
1735
1736#[cfg(test)]
1737mod bundle_gadgets {
1738 use crate::{
1739 circuit::circuits,
1740 dummy::Dummy,
1741 util::{RngExt, crt_factor, crt_inv_factor, factor, u128_from_bits, u128_to_bits},
1742 };
1743 use rand::thread_rng;
1744
1745 #[test]
1746 fn test_bundle_input_output() {
1747 let mut rng = thread_rng();
1748 let q = rng.gen_usable_composite_modulus();
1749 let c = circuits::bundle_gadgets::TestBundleInputOutput(factor(q));
1750
1751 for _ in 0..16 {
1752 let x = rng.gen_u128() % q;
1753 let y = Dummy::eval(&c, &crt_factor(x, q)).unwrap();
1754 let output = crt_inv_factor(&y, q);
1755 assert_eq!(output, x);
1756 }
1757 }
1758
1759 #[test]
1760 fn test_shift_extend() {
1761 let mut rng = thread_rng();
1762 let nbits = 64;
1763 let q = 1 << nbits;
1764
1765 for _ in 0..16 {
1766 let shift_size = rng.gen_usize() % nbits;
1767 let x = rng.gen_u128() % q;
1768 let c = circuits::bundle_gadgets::TestShiftExtend(nbits, shift_size);
1769
1770 let inputs = u128_to_bits(x, nbits);
1771 let output = Dummy::eval(&c, &inputs).unwrap();
1772 assert_eq!(u128_from_bits(&output), x << shift_size);
1773 }
1774 }
1775}
1776
1777#[cfg(test)]
1778mod crt_gadgets {
1779 use rand::thread_rng;
1780
1781 use crate::{
1782 circuit::circuits,
1783 dummy::Dummy,
1784 util::{self, RngExt, crt_factor, crt_inv_factor, factor},
1785 };
1786
1787 #[test]
1788 fn test_addition() {
1789 let mut rng = thread_rng();
1790 let q = rng.gen_usable_composite_modulus();
1791 let c = circuits::crt_gadgets::TestCrtAddition(factor(q));
1792
1793 for _ in 0..16 {
1794 let x = rng.gen_u128() % q;
1795 let y = rng.gen_u128() % q;
1796 let mut inputs = crt_factor(x, q);
1797 inputs.extend(crt_factor(y, q));
1798 let z = Dummy::eval(&c, &inputs).unwrap();
1799 let output = crt_inv_factor(&z, q);
1800 assert_eq!(output, (x + y) % q);
1801 }
1802 }
1803
1804 #[test]
1805 fn test_subtraction() {
1806 let mut rng = thread_rng();
1807 let q = rng.gen_usable_composite_modulus();
1808 let c = circuits::crt_gadgets::TestCrtSubtraction(util::factor(q));
1809
1810 for _ in 0..16 {
1811 let x = rng.gen_u128() % q;
1812 let y = rng.gen_u128() % q;
1813 let mut inputs = crt_factor(x, q);
1814 inputs.extend(crt_factor(y, q));
1815 let z = Dummy::eval(&c, &inputs).unwrap();
1816 let output = crt_inv_factor(&z, q);
1817 assert_eq!(output, (x + q - y) % q);
1818 }
1819 }
1820
1821 #[test]
1822 fn test_cmul() {
1823 let mut rng = thread_rng();
1824 let q = util::modulus_with_width(16);
1825 let y = rng.gen_u128() % q;
1826 let c = circuits::crt_gadgets::TestCrtCmul(util::factor(q), y);
1827
1828 for _ in 0..16 {
1829 let x = rng.gen_u128() % q;
1830 let z = Dummy::eval(&c, &crt_factor(x, q)).unwrap();
1831 let output = crt_inv_factor(&z, q);
1832 assert_eq!(output, (x * y) % q);
1833 }
1834 }
1835}
1836
1837#[cfg(test)]
1838mod arithmetic_bundle_gadgets {
1839 use rand::thread_rng;
1840
1841 use crate::{
1842 circuit::circuits,
1843 dummy::Dummy,
1844 util::{RngExt, crt_factor, crt_inv_factor, factor},
1845 };
1846
1847 #[test]
1848 fn test_multiplication() {
1849 let mut rng = thread_rng();
1850 let q = rng.gen_usable_composite_modulus();
1851 let c = circuits::arithmetic_bundle_gadgets::TestCrtMultiplication(factor(q));
1852
1853 for _ in 0..16 {
1854 let x = rng.gen_u64() as u128 % q;
1855 let y = rng.gen_u64() as u128 % q;
1856 let mut inputs = crt_factor(x, q);
1857 inputs.extend(crt_factor(y, q));
1858 let z = Dummy::eval(&c, &inputs).unwrap();
1859 let output = crt_inv_factor(&z, q);
1860 assert_eq!(output, (x * y) % q);
1861 }
1862 }
1863
1864 #[test]
1865 fn test_mask() {
1866 let mut rng = thread_rng();
1867 let q = rng.gen_usable_composite_modulus();
1868 let c = circuits::arithmetic_bundle_gadgets::TestMask(factor(q));
1869
1870 for _ in 0..16 {
1871 let b = rng.gen_bool();
1872 let x = rng.gen_u128() % q;
1873
1874 let mut inputs = vec![b as u16];
1875 inputs.extend(crt_factor(x, q));
1876 let z = Dummy::eval(&c, &inputs).unwrap();
1877 let output = crt_inv_factor(&z, q);
1878 if b {
1879 assert_eq!(output, x);
1880 } else {
1881 assert_eq!(output, 0);
1882 }
1883 }
1884 }
1885}
1886
1887#[cfg(test)]
1888mod crt_proj_gadgets {
1889 use crate::{
1890 circuit::circuits,
1891 dummy::Dummy,
1892 util::{RngExt, crt_factor, crt_inv_factor, factor, modulus_with_width, product},
1893 };
1894 use rand::thread_rng;
1895
1896 #[test]
1897 fn test_cexp() {
1898 let mut rng = thread_rng();
1899 let q = modulus_with_width(10);
1900 let y = rng.gen_u16() % 10;
1901 let c = circuits::crt_proj_gadgets::TestCrtCexp(factor(q), y);
1902
1903 for _ in 0..64 {
1904 let x = rng.gen_u16() as u128 % q;
1905 let z = Dummy::eval(&c, &crt_factor(x, q)).unwrap();
1906 let output = crt_inv_factor(&z, q);
1907 assert_eq!(output, x.pow(y as u32) % q);
1908 }
1909 }
1910
1911 #[test]
1912 #[ignore]
1913 fn test_division() {
1914 let mut rng = thread_rng();
1915
1916 for _ in 0..16 {
1917 let qs = rng.gen_usable_factors();
1918 let n = qs.len();
1919 let q = crate::util::product(&qs);
1920 let c = circuits::crt_proj_gadgets::TestCrtDivision(factor(q));
1921
1922 let q_ = crate::util::product(&qs[..n - 1]);
1923 let pt_x = rng.gen_u128() % q_;
1924 let pt_y = rng.gen_u128() % q_;
1925
1926 let mut inputs = crt_factor(pt_x, q);
1927 inputs.extend(crt_factor(pt_y, q));
1928 let z = Dummy::eval(&c, &inputs).unwrap();
1929 let output = crt_inv_factor(&z, q);
1930 assert_eq!(output, pt_x / pt_y);
1931 }
1932 }
1933
1934 #[test]
1935 fn test_remainder() {
1936 let mut rng = thread_rng();
1937 let ps = rng.gen_usable_factors();
1938 let q = ps.iter().fold(1, |acc, &x| (x as u128) * acc);
1939 let p = ps[rng.gen_u16() as usize % ps.len()];
1940 let c = circuits::crt_proj_gadgets::TestCrtRemainder(ps, p);
1941
1942 for _ in 0..64 {
1943 let x = rng.gen_u128() % q;
1944 let z = Dummy::eval(&c, &crt_factor(x, q)).unwrap();
1945 let output = crt_inv_factor(&z, q);
1946 assert_eq!(output, x % p as u128);
1947 }
1948 }
1949
1950 #[test]
1951 fn test_relu() {
1952 let mut rng = thread_rng();
1953 let q = modulus_with_width(10);
1954 let c = circuits::crt_proj_gadgets::TestRelu(factor(q));
1955
1956 for _ in 0..128 {
1957 let input = rng.gen_u128() % q;
1958 let expected = if input < q / 2 { input } else { 0 };
1959 let z = Dummy::eval(&c, &crt_factor(input, q)).unwrap();
1960 let output = crt_inv_factor(&z, q);
1961 assert_eq!(output, expected);
1962 }
1963 }
1964
1965 #[test]
1966 fn test_sgn() {
1967 let mut rng = thread_rng();
1968 let q = modulus_with_width(10);
1969 let c = circuits::crt_proj_gadgets::TestSgn(factor(q));
1970
1971 for _ in 0..128 {
1972 let input = rng.gen_u128() % q;
1973 let expected = if input < q / 2 { 1 } else { q - 1 };
1974 let z = Dummy::eval(&c, &crt_factor(input, q)).unwrap();
1975 let output = crt_inv_factor(&z, q);
1976 assert_eq!(output, expected);
1977 }
1978 }
1979
1980 #[test]
1981 fn test_leq() {
1982 let mut rng = thread_rng();
1983 let q = modulus_with_width(10);
1984 let c = circuits::crt_proj_gadgets::TestLeq(factor(q));
1985
1986 let x = rng.gen_u128() % q / 2;
1988 let mut inputs = crt_factor(x, q);
1989 inputs.extend(crt_factor(x, q));
1990 let output = Dummy::eval(&c, &inputs).unwrap()[0];
1991 assert_eq!(output, (x < x) as u16);
1992
1993 for _ in 0..64 {
1994 let x = rng.gen_u128() % q / 2;
1995 let y = rng.gen_u128() % q / 2;
1996 let mut inputs = crt_factor(x, q);
1997 inputs.extend(crt_factor(y, q));
1998 let output = Dummy::eval(&c, &inputs).unwrap()[0];
1999 assert_eq!(output, (x < y) as u16);
2000 }
2001 }
2002
2003 #[test]
2004 fn test_max() {
2005 let mut rng = thread_rng();
2006 let q = modulus_with_width(10);
2007 let n = 10;
2008 let c = circuits::crt_proj_gadgets::TestMax(factor(q), n);
2009
2010 for _ in 0..16 {
2011 let inputs = (0..n).map(|_| rng.gen_u128() % (q / 2)).collect::<Vec<_>>();
2012 let expected = *inputs.iter().max().unwrap();
2013
2014 let inputs = inputs
2015 .into_iter()
2016 .flat_map(|x| crt_factor(x, q))
2017 .collect::<Vec<_>>();
2018 let z = Dummy::eval(&c, &inputs).unwrap();
2019 let output = crt_inv_factor(&z, q);
2020 assert_eq!(output, expected);
2021 }
2022 }
2023
2024 #[test]
2025 fn test_crt_to_pmr() {
2026 fn to_pmr_pt(x: u128, ps: &[u16]) -> Vec<u16> {
2027 let mut ds = vec![0; ps.len()];
2028 let mut q = 1;
2029 for i in 0..ps.len() {
2030 let p = ps[i] as u128;
2031 ds[i] = ((x / q) % p) as u16;
2032 q *= p;
2033 }
2034 ds
2035 }
2036
2037 let mut rng = rand::thread_rng();
2038 for _ in 0..8 {
2039 let ps = rng.gen_usable_factors();
2040 let q = product(&ps);
2041
2042 let input = rng.gen_u128() % q;
2043 let expected = to_pmr_pt(input, &ps);
2044 let c = circuits::crt_proj_gadgets::TestCrtToPmr(ps);
2045 let output = Dummy::eval(&c, &crt_factor(input, q)).unwrap();
2046 assert_eq!(output, expected);
2047 }
2048 }
2049
2050 #[test]
2051 fn test_pmr_lt() {
2052 let mut rng = rand::thread_rng();
2053 for _ in 0..8 {
2054 let qs = rng.gen_usable_factors();
2055 let n = qs.len();
2056 let q = product(&qs);
2057 let q_ = product(&qs[..n - 1]);
2058 let pt_x = rng.gen_u128() % q_;
2059 let pt_y = rng.gen_u128() % q_;
2060 let c = circuits::crt_proj_gadgets::TestPmrLessThan(qs);
2061 let mut inputs = crt_factor(pt_x, q);
2062 inputs.extend(crt_factor(pt_y, q));
2063 let output = Dummy::eval(&c, &inputs).unwrap()[0];
2064 if pt_x < pt_y {
2065 assert_eq!(output, 1);
2066 } else {
2067 assert_eq!(output, 0);
2068 }
2069 }
2070 }
2071
2072 #[test]
2073 fn test_pmr_geq() {
2074 let mut rng = rand::thread_rng();
2075 for _ in 0..8 {
2076 let qs = rng.gen_usable_factors();
2077 let n = qs.len();
2078 let q = product(&qs);
2079 let q_ = product(&qs[..n - 1]);
2080 let pt_x = rng.gen_u128() % q_;
2081 let pt_y = rng.gen_u128() % q_;
2082 let c = circuits::crt_proj_gadgets::TestPmrGreaterThanOrEqual(qs);
2083 let mut inputs = crt_factor(pt_x, q);
2084 inputs.extend(crt_factor(pt_y, q));
2085 let output = Dummy::eval(&c, &inputs).unwrap()[0];
2086 if pt_x >= pt_y {
2087 assert_eq!(output, 1);
2088 } else {
2089 assert_eq!(output, 0);
2090 }
2091 }
2092 }
2093}
2094
2095#[cfg(test)]
2096mod arithmetic_proj_bundle_gadgets {
2097 use rand::thread_rng;
2098
2099 use crate::{
2100 circuit::circuits,
2101 dummy::Dummy,
2102 util::{RngExt, as_mixed_radix, crt_factor, factor, from_mixed_radix, product},
2103 };
2104
2105 #[test]
2106 fn test_eq_bundles() {
2107 let mut rng = thread_rng();
2108 let q = rng.gen_usable_composite_modulus();
2109 let c = circuits::arithmetic_proj_bundle_gadgets::TestEqBundles(factor(q));
2110
2111 let x = rng.gen_u128() % q;
2113 let mut inputs = crt_factor(x, q);
2114 inputs.extend(crt_factor(x, q));
2115 let output = Dummy::eval(&c, &inputs).unwrap()[0];
2116 assert_eq!(output, (x == x) as u16);
2117
2118 for _ in 0..64 {
2119 let x = rng.gen_u128() % q;
2120 let y = rng.gen_u128() % q;
2121 let mut inputs = crt_factor(x, q);
2122 inputs.extend(crt_factor(y, q));
2123 let output = Dummy::eval(&c, &inputs).unwrap()[0];
2124 assert_eq!(output, (x == y) as u16);
2125 }
2126 }
2127
2128 #[test]
2129 fn test_mixed_radix_addition() {
2130 let mut rng = thread_rng();
2131 let nargs = 2 + rng.gen_usize() % 100;
2132 let moduli = (0..7).map(|_| rng.gen_modulus()).collect::<Vec<_>>();
2133 let q: u128 = moduli.iter().map(|&q| q as u128).product();
2134 let circ =
2135 circuits::arithmetic_proj_bundle_gadgets::TestMixedRadixAddition(moduli.clone(), nargs);
2136
2137 let mut inputs = Vec::new();
2139 for _ in 0..nargs {
2140 inputs.extend(as_mixed_radix(q - 1, &moduli).iter());
2141 }
2142 let output = Dummy::eval(&circ, &inputs).unwrap();
2143 assert_eq!(
2144 from_mixed_radix(&output, &moduli),
2145 (q - 1) * (nargs as u128) % q
2146 );
2147
2148 for _ in 0..4 {
2150 let mut expected = 0;
2151 let mut inputs = Vec::new();
2152 for _ in 0..nargs {
2153 let x = rng.gen_u128() % q;
2154 expected = (expected + x) % q;
2155 inputs.extend(as_mixed_radix(x, &moduli).iter());
2156 }
2157 let output = Dummy::eval(&circ, &inputs).unwrap();
2158 assert_eq!(from_mixed_radix(&output, &moduli), expected);
2159 }
2160 }
2161
2162 #[test]
2163 fn test_mixed_radix_addition_msb_only() {
2164 let mut rng = thread_rng();
2165 let nargs = 2 + rng.gen_usize() % 10;
2166 let moduli = (0..7).map(|_| rng.gen_modulus()).collect::<Vec<_>>();
2167 let q = product(&moduli);
2168 let circ = circuits::arithmetic_proj_bundle_gadgets::TestMixedRadixAdditionMSBOnly(
2169 moduli.clone(),
2170 nargs,
2171 );
2172
2173 let mut inputs = Vec::new();
2175 for _ in 0..nargs {
2176 inputs.extend(as_mixed_radix(q - 1, &moduli).iter());
2177 }
2178 let output = Dummy::eval(&circ, &inputs).unwrap()[0];
2179 assert_eq!(
2180 output,
2181 *as_mixed_radix((q - 1) * (nargs as u128) % q, &moduli)
2182 .last()
2183 .unwrap()
2184 );
2185
2186 for _ in 0..4 {
2188 let mut expected = 0;
2189 let mut inputs = Vec::new();
2190 for _ in 0..nargs {
2191 let x = rng.gen_u128() % q;
2192 expected = (expected + x) % q;
2193 inputs.extend(as_mixed_radix(x, &moduli).iter());
2194 }
2195 let output = Dummy::eval(&circ, &inputs).unwrap()[0];
2196 assert_eq!(output, *as_mixed_radix(expected, &moduli).last().unwrap());
2197 }
2198 }
2199}
2200
2201#[cfg(test)]
2202mod binary_gadgets {
2203 use rand::thread_rng;
2204
2205 use crate::{
2206 circuit::circuits,
2207 dummy::Dummy,
2208 util::{self, RngExt},
2209 };
2210
2211 #[test]
2212 fn test_binary_addition() {
2213 let mut rng = thread_rng();
2214 let nbits = 64;
2215 let q = 1 << 64;
2216 let c = circuits::binary_gadgets::TestBinaryAddition(nbits);
2217
2218 for _ in 0..16 {
2219 let x = rng.gen_u128() % q;
2220 let y = rng.gen_u128() % q;
2221 let mut inputs = util::u128_to_bits(x, nbits);
2222 inputs.extend(util::u128_to_bits(y, nbits));
2223 let output = Dummy::eval(&c, &inputs).unwrap();
2224 assert_eq!(util::u128_from_bits(&output[1..]), (x + y) % q);
2225 assert_eq!(output[0], (x + y >= q) as u16);
2226 }
2227 }
2228
2229 #[test]
2230 fn test_binary_subtraction() {
2231 let mut rng = thread_rng();
2232 let nbits = 64;
2233 let q = 1 << nbits;
2234 let c = circuits::binary_gadgets::TestBinarySubtraction(nbits);
2235
2236 for _ in 0..16 {
2237 let x = rng.gen_u128() % q;
2238 let y = rng.gen_u128() % q;
2239 let mut inputs = util::u128_to_bits(x, nbits);
2240 inputs.extend(util::u128_to_bits(y, nbits));
2241 let output = Dummy::eval(&c, &inputs).unwrap();
2242 assert_eq!(
2243 util::u128_from_bits(&output[1..]),
2244 x.overflowing_sub(y).0 % q
2245 );
2246 assert_eq!(output[0], (y != 0 && x >= y) as u16);
2247 }
2248 }
2249
2250 #[test]
2251 fn test_binary_lt() {
2252 let mut rng = thread_rng();
2253 let nbits = 64;
2254 let q = 1 << nbits;
2255 let c = circuits::binary_gadgets::TestBinaryLessThan(nbits);
2256
2257 for _ in 0..16 {
2258 let x = rng.gen_u128() % q;
2259 let y = rng.gen_u128() % q;
2260 let mut inputs = util::u128_to_bits(x, nbits);
2261 inputs.extend(util::u128_to_bits(y, nbits));
2262 let output = Dummy::eval(&c, &inputs).unwrap();
2263 assert_eq!(util::u128_from_bits(&output) > 0, x < y);
2264 }
2265 }
2266
2267 #[test]
2268 fn test_binary_lt_signed() {
2269 let mut rng = thread_rng();
2270 let nbits = 16;
2271 let q = 1 << nbits;
2272 let c = circuits::binary_gadgets::TestBinaryLessThanSigned(nbits);
2273
2274 for _ in 0..16 {
2275 let x = rng.gen_u128() % q;
2276 let y = rng.gen_u128() % q;
2277 let mut inputs = util::u128_to_bits(x, nbits);
2278 inputs.extend(util::u128_to_bits(y, nbits));
2279 let output = Dummy::eval(&c, &inputs).unwrap();
2280 assert_eq!(output.len(), 1);
2281 assert_eq!(output[0] > 0, (x as i16) < (y as i16));
2282 }
2283 }
2284
2285 #[test]
2286 fn test_binary_multiplication_lower_half() {
2287 let mut rng = thread_rng();
2288 let nbits = 64;
2289 let q = 1 << nbits;
2290 let c = circuits::binary_gadgets::TestBinaryMultiplicationLowerHalf(nbits);
2291
2292 for _ in 0..16 {
2293 let x = rng.gen_u128() % q;
2294 let y = rng.gen_u128() % q;
2295 let mut inputs = util::u128_to_bits(x, nbits);
2296 inputs.extend(util::u128_to_bits(y, nbits));
2297 let output = Dummy::eval(&c, &inputs).unwrap();
2298 assert_eq!(util::u128_from_bits(&output), (x * y) % q);
2299 }
2300 }
2301
2302 #[test]
2303 fn test_binary_multiplication() {
2304 let mut rng = thread_rng();
2305 let nbits = 64;
2306 let q = 1 << 64;
2307 let c = circuits::binary_gadgets::TestBinaryMultiplication(nbits);
2308
2309 for _ in 0..16 {
2310 let x = rng.gen_u128() % q;
2311 let y = rng.gen_u128() % q;
2312 let mut inputs = util::u128_to_bits(x, nbits);
2313 inputs.extend(util::u128_to_bits(y, nbits));
2314 let output = Dummy::eval(&c, &inputs).unwrap();
2315 assert_eq!(util::u128_from_bits(&output), x * y);
2316 }
2317 }
2318
2319 #[test]
2320 fn test_binary_division() {
2321 let mut rng = thread_rng();
2322 let nbits = 64;
2323 let q = 1 << nbits;
2324 let c = circuits::binary_gadgets::TestBinaryDivision(nbits);
2325
2326 for _ in 0..16 {
2327 let x = rng.gen_u128() % q;
2328 let mut y = rng.gen_u128() % q;
2329 while y == 0 {
2330 y = rng.gen_u128() % q;
2331 }
2332 let mut inputs = util::u128_to_bits(x, nbits);
2333 inputs.extend(util::u128_to_bits(y, nbits));
2334 let output = Dummy::eval(&c, &inputs).unwrap();
2335 assert_eq!(util::u128_from_bits(&output), x / y);
2336 }
2337 }
2338
2339 #[test]
2340 fn test_bin_abs() {
2341 let mut rng = thread_rng();
2342 let nbits = 64;
2343 let q = 1 << nbits;
2344 let c = circuits::binary_gadgets::TestBinaryAbs(nbits);
2345
2346 for _ in 0..16 {
2347 let x = rng.gen_u128() % q;
2348 let output = Dummy::eval(&c, &util::u128_to_bits(x, nbits)).unwrap();
2349 assert_eq!(
2350 util::u128_from_bits(&output),
2351 if x >> (nbits - 1) > 0 {
2352 ((!x) + 1) & ((1 << nbits) - 1)
2353 } else {
2354 x
2355 }
2356 );
2357 }
2358 }
2359
2360 #[test]
2361 fn test_binary_eq() {
2362 let mut rng = thread_rng();
2363 let nbits = 64;
2364 let q = 1 << nbits;
2365 let c = circuits::binary_gadgets::TestBinaryEqBundles(nbits);
2366
2367 for _ in 0..16 {
2368 let x = rng.gen_u128() % q;
2369 let y = rng.gen_u128() % q;
2370 let mut inputs = util::u128_to_bits(x, nbits);
2371 inputs.extend(util::u128_to_bits(y, nbits));
2372 let output = Dummy::eval(&c, &inputs).unwrap();
2373 assert_eq!(output[0], (x == y) as u16);
2374 }
2375 }
2376
2377 #[test]
2378 fn test_binary_rsa() {
2379 let mut rng = thread_rng();
2380 let nbits = 64;
2381 let q = 1 << nbits;
2382
2383 for _ in 0..16 {
2384 let x = rng.gen_u128() % q;
2385 let shift_size = rng.gen_usize() % nbits;
2386 let c = circuits::binary_gadgets::TestBinaryArithmeticRightShift(nbits, shift_size);
2387 let output = Dummy::eval(&c, &util::u128_to_bits(x, nbits)).unwrap();
2388 assert_eq!(
2389 util::u128_from_bits(&output) as i64,
2390 (x as i64) >> shift_size
2391 );
2392 }
2393 }
2394
2395 #[test]
2396 fn test_binary_rsl() {
2397 let mut rng = thread_rng();
2398 let nbits = 64;
2399 let q = 1 << nbits;
2400
2401 for _ in 0..16 {
2402 let x = rng.gen_u128() % q;
2403 let shift_size = rng.gen_usize() % nbits;
2404 let c = circuits::binary_gadgets::TestBinaryLogicalRightShift(nbits, shift_size);
2405 let output = Dummy::eval(&c, &util::u128_to_bits(x, nbits)).unwrap();
2406 assert_eq!(util::u128_from_bits(&output), x >> shift_size);
2407 }
2408 }
2409
2410 #[test]
2411 fn test_bin_demux() {
2412 let mut rng = thread_rng();
2413 let nbits = 8;
2414 let q = 1 << nbits;
2415 let c = circuits::binary_gadgets::TestBinaryDemux(nbits);
2416
2417 for _ in 0..16 {
2418 let x = rng.gen_u128() % q;
2419 let output = Dummy::eval(&c, &util::u128_to_bits(x, nbits)).unwrap();
2420 for (i, y) in output.into_iter().enumerate() {
2421 if i as u128 == x {
2422 assert_eq!(y, 1);
2423 } else {
2424 assert_eq!(y, 0);
2425 }
2426 }
2427 }
2428 }
2429
2430 #[test]
2431 fn test_bin_twos_complement() {
2432 let mut rng = thread_rng();
2433 let nbits = 64;
2434 let q = 1 << nbits;
2435 let c = circuits::binary_gadgets::TestBinaryTwosComplement(nbits);
2436
2437 for _ in 0..16 {
2438 let x = rng.gen_u128() % q;
2439 let output = Dummy::eval(&c, &util::u128_to_bits(x, nbits)).unwrap();
2440 assert_eq!(util::u128_from_bits(&output), (((!x) % q) + 1) % q);
2441 }
2442 }
2443
2444 #[test]
2445 fn test_binary_max() {
2446 let mut rng = thread_rng();
2447 let n = 10;
2448 let nbits = 16;
2449 let q = 1 << nbits;
2450 let c = circuits::binary_gadgets::TestBinaryMax(nbits, n);
2451
2452 for _ in 0..16 {
2453 let inputs = (0..n).map(|_| rng.gen_u128() % q).collect::<Vec<_>>();
2454 let expected = *inputs.iter().max().unwrap();
2455
2456 let inputs = inputs
2457 .into_iter()
2458 .flat_map(|x| util::u128_to_bits(x, nbits))
2459 .collect::<Vec<_>>();
2460 let z = Dummy::eval(&c, &inputs).unwrap();
2461 let output = util::u128_from_bits(&z);
2462 assert_eq!(output, expected);
2463 }
2464 }
2465}