fancy_garbling/
dummy.rs

1//! Dummy implementation of `Fancy`.
2//!
3//! Useful for evaluating the circuits produced by `Fancy` without actually
4//! creating any circuits.
5
6use crate::{
7    FancyArithmetic, FancyBinary, check_binary, derive_binary,
8    errors::{DummyError, FancyError},
9    fancy::{Fancy, FancyInput, FancyReveal, HasModulus},
10};
11
12/// Simple struct that performs the fancy computation over `u16`.
13pub struct Dummy {}
14
15/// Wrapper around `u16`.
16#[derive(Clone, Debug)]
17pub struct DummyVal {
18    val: u16,
19    modulus: u16,
20}
21
22impl HasModulus for DummyVal {
23    fn modulus(&self) -> u16 {
24        self.modulus
25    }
26}
27
28impl DummyVal {
29    /// Create a new DummyVal.
30    pub fn new(val: u16, modulus: u16) -> Self {
31        Self { val, modulus }
32    }
33
34    /// Extract the value.
35    pub fn val(&self) -> u16 {
36        self.val
37    }
38}
39
40impl Dummy {
41    /// Create a new Dummy.
42    pub fn new() -> Dummy {
43        Dummy {}
44    }
45}
46
47impl FancyInput for Dummy {
48    type Item = DummyVal;
49    type Error = DummyError;
50
51    /// Encode a single dummy value.
52    fn encode(&mut self, value: u16, modulus: u16) -> Result<DummyVal, DummyError> {
53        Ok(DummyVal::new(value, modulus))
54    }
55
56    /// Encode a slice of inputs and a slice of moduli as DummyVals.
57    fn encode_many(&mut self, xs: &[u16], moduli: &[u16]) -> Result<Vec<DummyVal>, DummyError> {
58        if xs.len() != moduli.len() {
59            return Err(DummyError::EncodingError);
60        }
61        Ok(xs
62            .iter()
63            .zip(moduli.iter())
64            .map(|(x, q)| DummyVal::new(*x, *q))
65            .collect())
66    }
67
68    fn receive_many(&mut self, _moduli: &[u16]) -> Result<Vec<DummyVal>, DummyError> {
69        // Receive is undefined for Dummy which is a single party "protocol"
70        Err(DummyError::EncodingError)
71    }
72}
73
74derive_binary!(Dummy);
75
76impl FancyArithmetic for Dummy {
77    fn add(&mut self, x: &DummyVal, y: &DummyVal) -> Result<DummyVal, Self::Error> {
78        if x.modulus() != y.modulus() {
79            return Err(Self::Error::from(FancyError::UnequalModuli));
80        }
81        Ok(DummyVal {
82            val: (x.val + y.val) % x.modulus,
83            modulus: x.modulus,
84        })
85    }
86
87    fn sub(&mut self, x: &DummyVal, y: &DummyVal) -> Result<DummyVal, Self::Error> {
88        if x.modulus() != y.modulus() {
89            return Err(Self::Error::from(FancyError::UnequalModuli));
90        }
91        Ok(DummyVal {
92            val: (x.modulus + x.val - y.val) % x.modulus,
93            modulus: x.modulus,
94        })
95    }
96
97    fn cmul(&mut self, x: &DummyVal, c: u16) -> Result<DummyVal, Self::Error> {
98        Ok(DummyVal {
99            val: (x.val * c) % x.modulus,
100            modulus: x.modulus,
101        })
102    }
103
104    fn mul(&mut self, x: &DummyVal, y: &DummyVal) -> Result<DummyVal, Self::Error> {
105        Ok(DummyVal {
106            val: x.val * y.val % x.modulus,
107            modulus: x.modulus,
108        })
109    }
110
111    fn proj(
112        &mut self,
113        x: &DummyVal,
114        modulus: u16,
115        tt: Option<Vec<u16>>,
116    ) -> Result<DummyVal, Self::Error> {
117        let tt = tt.ok_or_else(|| Self::Error::from(FancyError::NoTruthTable))?;
118        if tt.len() < x.modulus() as usize || !tt.iter().all(|&x| x < modulus) {
119            return Err(Self::Error::from(FancyError::InvalidTruthTable));
120        }
121        let val = tt[x.val as usize];
122        Ok(DummyVal { val, modulus })
123    }
124}
125
126impl Fancy for Dummy {
127    type Item = DummyVal;
128    type Error = DummyError;
129
130    fn constant(&mut self, val: u16, modulus: u16) -> Result<DummyVal, Self::Error> {
131        Ok(DummyVal { val, modulus })
132    }
133
134    fn output(&mut self, x: &DummyVal) -> Result<Option<u16>, Self::Error> {
135        Ok(Some(x.val))
136    }
137}
138
139impl FancyReveal for Dummy {
140    fn reveal(&mut self, x: &DummyVal) -> Result<u16, DummyError> {
141        Ok(x.val)
142    }
143}
144
145#[cfg(test)]
146mod bundle {
147    use super::*;
148    use crate::{
149        fancy::{ArithmeticBundleGadgets, BinaryGadgets, Bundle, BundleGadgets, CrtGadgets},
150        util::{self, RngExt},
151    };
152    use itertools::Itertools;
153    use rand::thread_rng;
154
155    const NITERS: usize = 1 << 10;
156
157    #[test]
158    fn test_addition() {
159        let mut rng = thread_rng();
160        for _ in 0..NITERS {
161            let q = rng.gen_usable_composite_modulus();
162            let x = rng.gen_u128() % q;
163            let y = rng.gen_u128() % q;
164            let mut d = Dummy::new();
165            let out;
166            {
167                let x = d.crt_encode(x, q).unwrap();
168                let y = d.crt_encode(y, q).unwrap();
169                let z = d.crt_add(&x, &y).unwrap();
170                out = d.crt_output(&z).unwrap().unwrap();
171            }
172            assert_eq!(out, (x + y) % q);
173        }
174    }
175
176    #[test]
177    fn test_subtraction() {
178        let mut rng = thread_rng();
179        for _ in 0..NITERS {
180            let q = rng.gen_usable_composite_modulus();
181            let x = rng.gen_u128() % q;
182            let y = rng.gen_u128() % q;
183            let mut d = Dummy::new();
184            let out;
185            {
186                let x = d.crt_encode(x, q).unwrap();
187                let y = d.crt_encode(y, q).unwrap();
188                let z = d.crt_sub(&x, &y).unwrap();
189                out = d.crt_output(&z).unwrap().unwrap();
190            }
191            assert_eq!(out, (x + q - y) % q);
192        }
193    }
194
195    #[test]
196    fn test_binary_cmul() {
197        let mut rng = thread_rng();
198        for _ in 0..NITERS {
199            let nbits = 64;
200            let q = 1 << nbits;
201            let x = rng.gen_u128() % q;
202            let c = 1 + rng.gen_u128() % q;
203            let mut d = Dummy::new();
204            let out;
205            {
206                let x = d.bin_encode(x, nbits).unwrap();
207                let z = d.bin_cmul(&x, c, nbits).unwrap();
208                out = d.bin_output(&z).unwrap().unwrap();
209            }
210            assert_eq!(out, (x * c) % q);
211        }
212    }
213
214    #[test]
215    fn test_binary_multiplication() {
216        let mut rng = thread_rng();
217        for _ in 0..NITERS {
218            let nbits = 64;
219            let q = 1 << nbits;
220            let x = rng.gen_u128() % q;
221            let y = rng.gen_u128() % q;
222            let mut d = Dummy::new();
223            let out;
224            {
225                let x = d.bin_encode(x, nbits).unwrap();
226                let y = d.bin_encode(y, nbits).unwrap();
227                let z = d.bin_multiplication_lower_half(&x, &y).unwrap();
228                out = d.bin_output(&z).unwrap().unwrap();
229            }
230            assert_eq!(out, (x * y) % q);
231        }
232    }
233
234    #[test]
235    fn test_shift_extend() {
236        let mut rng = thread_rng();
237        for _ in 0..NITERS {
238            let nbits = 64;
239            let q = 1 << nbits;
240            let shift_size = rng.gen_usize() % nbits;
241            let x = rng.gen_u128() % q;
242            let mut d = Dummy::new();
243            let out;
244            {
245                use crate::BinaryBundle;
246                let x = d.bin_encode(x, nbits).unwrap();
247                let z = d.shift_extend(&x, shift_size).unwrap();
248                out = d.bin_output(&BinaryBundle::from(z)).unwrap().unwrap();
249            }
250            assert_eq!(out, x << shift_size);
251        }
252    }
253
254    #[test]
255    fn test_binary_full_multiplication() {
256        let mut rng = thread_rng();
257        for _ in 0..NITERS {
258            let nbits = 64;
259            let q = 1 << nbits;
260            let x = rng.gen_u128() % q;
261            let y = rng.gen_u128() % q;
262            let mut d = Dummy::new();
263            let out;
264            {
265                let x = d.bin_encode(x, nbits).unwrap();
266                let y = d.bin_encode(y, nbits).unwrap();
267                let z = d.bin_mul(&x, &y).unwrap();
268                println!("z.len() = {}", z.size());
269                out = d.bin_output(&z).unwrap().unwrap();
270            }
271            assert_eq!(out, x * y);
272        }
273    }
274
275    #[test]
276    fn test_binary_division() {
277        let mut rng = thread_rng();
278        for _ in 0..NITERS {
279            let nbits = 64;
280            let q = 1 << nbits;
281            let x = rng.gen_u128() % q;
282            let y = rng.gen_u128() % q;
283            let mut d = Dummy::new();
284            let out;
285            {
286                let x = d.bin_encode(x, nbits).unwrap();
287                let y = d.bin_encode(y, nbits).unwrap();
288                let z = d.bin_div(&x, &y).unwrap();
289                out = d.bin_output(&z).unwrap().unwrap();
290            }
291            assert_eq!(out, x / y);
292        }
293    }
294
295    #[test]
296    fn max() {
297        let mut rng = thread_rng();
298        let q = util::modulus_with_width(10);
299        let n = 10;
300        for _ in 0..NITERS {
301            let inps = (0..n).map(|_| rng.gen_u128() % (q / 2)).collect_vec();
302            let should_be = *inps.iter().max().unwrap();
303            let mut d = Dummy::new();
304            let out;
305            {
306                let xs = inps
307                    .into_iter()
308                    .map(|x| d.crt_encode(x, q).unwrap())
309                    .collect_vec();
310                let z = d.crt_max(&xs, "100%").unwrap();
311                out = d.crt_output(&z).unwrap().unwrap();
312            }
313            assert_eq!(out, should_be);
314        }
315    }
316
317    #[test]
318    fn twos_complement() {
319        let mut rng = thread_rng();
320        let nbits = 16;
321        let q = 1 << nbits;
322        for _ in 0..NITERS {
323            let x = rng.gen_u128() % q;
324            let should_be = (((!x) % q) + 1) % q;
325            let mut d = Dummy::new();
326            let out;
327            {
328                let x = d.bin_encode(x, nbits).unwrap();
329                let y = d.bin_twos_complement(&x).unwrap();
330                out = d.bin_output(&y).unwrap().unwrap();
331            }
332            assert_eq!(out, should_be, "x={} y={} should_be={}", x, out, should_be);
333        }
334    }
335
336    #[test]
337    fn binary_addition() {
338        let mut rng = thread_rng();
339        let nbits = 16;
340        let q = 1 << nbits;
341        for _ in 0..NITERS {
342            let x = rng.gen_u128() % q;
343            let y = rng.gen_u128() % q;
344            let should_be = (x + y) % q;
345            let mut d = Dummy::new();
346            let out;
347            let overflow;
348            {
349                let x = d.bin_encode(x, nbits).unwrap();
350                let y = d.bin_encode(y, nbits).unwrap();
351                let (z, _overflow) = d.bin_addition(&x, &y).unwrap();
352                overflow = d.output(&_overflow).unwrap().unwrap();
353                out = d.bin_output(&z).unwrap().unwrap();
354            }
355            assert_eq!(out, should_be);
356            assert_eq!(overflow > 0, x + y >= q);
357        }
358    }
359
360    #[test]
361    fn binary_subtraction() {
362        let mut rng = thread_rng();
363        let nbits = 16;
364        let q = 1 << nbits;
365        for _ in 0..NITERS {
366            let x = rng.gen_u128() % q;
367            let y = rng.gen_u128() % q;
368            let (should_be, _) = x.overflowing_sub(y);
369            let should_be = should_be % q;
370            let mut d = Dummy::new();
371            let overflow;
372            let out;
373            {
374                let x = d.bin_encode(x, nbits).unwrap();
375                let y = d.bin_encode(y, nbits).unwrap();
376                let (z, _overflow) = d.bin_subtraction(&x, &y).unwrap();
377                overflow = d.output(&_overflow).unwrap().unwrap();
378                out = d.bin_output(&z).unwrap().unwrap();
379            }
380            assert_eq!(out, should_be);
381            assert_eq!(overflow > 0, (y != 0 && x >= y), "x={} y={}", x, y);
382        }
383    }
384
385    #[test]
386    fn binary_lt() {
387        let mut rng = thread_rng();
388        let nbits = 16;
389        let q = 1 << nbits;
390        for _ in 0..NITERS {
391            let x = rng.gen_u128() % q;
392            let y = rng.gen_u128() % q;
393            let should_be = x < y;
394            let mut d = Dummy::new();
395            let out;
396            {
397                let x = d.bin_encode(x, nbits).unwrap();
398                let y = d.bin_encode(y, nbits).unwrap();
399                let z = d.bin_lt(&x, &y).unwrap();
400                out = d.output(&z).unwrap().unwrap();
401            }
402            assert_eq!(out > 0, should_be, "x={} y={}", x, y);
403        }
404    }
405
406    #[test]
407    fn binary_lt_signed() {
408        let mut rng = thread_rng();
409        let nbits = 16;
410        let q = 1 << nbits;
411        for _ in 0..NITERS {
412            let x = rng.gen_u128() % q;
413            let y = rng.gen_u128() % q;
414            let should_be = (x as i16) < (y as i16);
415            let mut d = Dummy::new();
416            let out;
417            {
418                let x = d.bin_encode(x, nbits).unwrap();
419                let y = d.bin_encode(y, nbits).unwrap();
420                let z = d.bin_lt_signed(&x, &y).unwrap();
421                out = d.output(&z).unwrap().unwrap();
422            }
423            assert_eq!(out > 0, should_be, "x={} y={}", x as i16, y as i16);
424        }
425    }
426
427    #[test]
428    fn binary_max() {
429        let mut rng = thread_rng();
430        let n = 10;
431        let nbits = 16;
432        let q = 1 << nbits;
433        for _ in 0..NITERS {
434            let inps = (0..n).map(|_| rng.gen_u128() % q).collect_vec();
435            let should_be = *inps.iter().max().unwrap();
436            let mut d = Dummy::new();
437            let out;
438            {
439                let xs = inps
440                    .into_iter()
441                    .map(|x| d.bin_encode(x, nbits).unwrap())
442                    .collect_vec();
443                let z = d.bin_max(&xs).unwrap();
444                out = d.bin_output(&z).unwrap().unwrap();
445            }
446            assert_eq!(out, should_be);
447        }
448    }
449
450    #[test] // bundle relu
451    fn test_relu() {
452        let mut rng = thread_rng();
453        for _ in 0..NITERS {
454            let q = crate::util::modulus_with_nprimes(4 + rng.gen_usize() % 7); // exact relu supports up to 11 primes
455            let x = rng.gen_u128() % q;
456            let mut d = Dummy::new();
457            let out;
458            {
459                let x = d.crt_encode(x, q).unwrap();
460                let z = d.crt_relu(&x, "100%", None).unwrap();
461                out = d.crt_output(&z).unwrap().unwrap();
462            }
463            if x >= q / 2 {
464                assert_eq!(out, 0);
465            } else {
466                assert_eq!(out, x);
467            }
468        }
469    }
470
471    #[test]
472    fn test_mask() {
473        let mut rng = thread_rng();
474        for _ in 0..NITERS {
475            let q = crate::util::modulus_with_nprimes(4 + rng.gen_usize() % 7);
476            let x = rng.gen_u128() % q;
477            let b = rng.gen_bool();
478            let mut d = Dummy::new();
479            let out;
480            {
481                let b = d.encode(b as u16, 2).unwrap();
482                let x = d.crt_encode(x, q).unwrap();
483                let z = d.mask(&b, &x).unwrap().into();
484                out = d.crt_output(&z).unwrap().unwrap();
485            }
486            assert!(
487                if b { out == x } else { out == 0 },
488                "b={} x={} z={}",
489                b,
490                x,
491                out
492            );
493        }
494    }
495
496    #[test]
497    fn binary_abs() {
498        let mut rng = thread_rng();
499        for _ in 0..NITERS {
500            let nbits = 64;
501            let q = 1 << nbits;
502            let x = rng.gen_u128() % q;
503            let mut d = Dummy::new();
504            let out;
505            {
506                let x = d.bin_encode(x, nbits).unwrap();
507                let z = d.bin_abs(&x).unwrap();
508                out = d.bin_output(&z).unwrap().unwrap();
509            }
510            let should_be = if x >> (nbits - 1) > 0 {
511                ((!x) + 1) & ((1 << nbits) - 1)
512            } else {
513                x
514            };
515            assert_eq!(out, should_be);
516        }
517    }
518
519    #[test]
520    fn binary_demux() {
521        let mut rng = thread_rng();
522        for _ in 0..NITERS {
523            let nbits = 8;
524            let q = 1 << nbits;
525            let x = rng.gen_u128() % q;
526            let mut d = Dummy::new();
527            let outs;
528            {
529                let x = d.bin_encode(x, nbits).unwrap();
530                let zs = d.bin_demux(&x).unwrap();
531                outs = d.outputs(&zs).unwrap().unwrap();
532            }
533            for (i, z) in outs.into_iter().enumerate() {
534                if i as u128 == x {
535                    assert_eq!(z, 1);
536                } else {
537                    assert_eq!(z, 0);
538                }
539            }
540        }
541    }
542
543    #[test]
544    fn binary_eq() {
545        let mut rng = thread_rng();
546        for _ in 0..NITERS {
547            let nbits = rng.gen_usize() % 100 + 2;
548            let q = 1 << nbits;
549            let x = rng.gen_u128() % q;
550            let y = if rng.gen_bool() {
551                x
552            } else {
553                rng.gen_u128() % q
554            };
555            let mut d = Dummy::new();
556            let out;
557            {
558                let x = d.bin_encode(x, nbits).unwrap();
559                let y = d.bin_encode(y, nbits).unwrap();
560                let z = d.bin_eq_bundles(&x, &y).unwrap();
561                out = d.output(&z).unwrap().unwrap();
562            }
563            assert_eq!(out, (x == y) as u16);
564        }
565    }
566
567    #[test]
568    fn binary_proj_eq() {
569        let mut rng = thread_rng();
570        for _ in 0..NITERS {
571            let nbits = rng.gen_usize() % 100 + 2;
572            let q = 1 << nbits;
573            let x = rng.gen_u128() % q;
574            let y = if rng.gen_bool() {
575                x
576            } else {
577                rng.gen_u128() % q
578            };
579            let mut d = Dummy::new();
580            let out;
581            {
582                let x = d.bin_encode(x, nbits).unwrap();
583                let y = d.bin_encode(y, nbits).unwrap();
584                let z = d.eq_bundles(&x, &y).unwrap();
585                out = d.output(&z).unwrap().unwrap();
586            }
587            assert_eq!(out, (x == y) as u16);
588        }
589    }
590
591    #[test]
592    fn binary_rsa() {
593        let mut rng = thread_rng();
594        for _ in 0..NITERS {
595            let nbits = 64;
596            let q = 1 << nbits;
597            let x = rng.gen_u128() % q;
598            let shift_size = rng.gen_usize() % nbits;
599            let mut d = Dummy::new();
600            let out;
601            {
602                let x = d.bin_encode(x, nbits).unwrap();
603                let z = d.bin_rsa(&x, shift_size).unwrap();
604                out = d.bin_output(&z).unwrap().unwrap() as i64;
605            }
606            let should_be = (x as i64) >> shift_size;
607            assert_eq!(out, should_be);
608        }
609    }
610
611    #[test]
612    fn binary_rsl() {
613        let mut rng = thread_rng();
614        for _ in 0..NITERS {
615            let nbits = 64;
616            let q = 1 << nbits;
617            let x = rng.gen_u128() % q;
618            let shift_size = rng.gen_usize() % nbits;
619            let mut d = Dummy::new();
620            let out;
621            {
622                let x = d.bin_encode(x, nbits).unwrap();
623                let z = d.bin_rsl(&x, shift_size).unwrap();
624                out = d.bin_output(&z).unwrap().unwrap();
625            }
626            let should_be = x >> shift_size;
627            assert_eq!(out, should_be);
628        }
629    }
630
631    #[test]
632    fn test_mixed_radix_addition_msb_only() {
633        let mut rng = thread_rng();
634        for _ in 0..NITERS {
635            let nargs = 2 + rng.gen_usize() % 10;
636            let mods = (0..7).map(|_| rng.gen_modulus()).collect_vec();
637            let Q: u128 = util::product(&mods);
638
639            println!("nargs={} mods={:?} Q={}", nargs, mods, Q);
640
641            // test maximum overflow
642            let xs = (0..nargs)
643                .map(|_| {
644                    Bundle::new(
645                        util::as_mixed_radix(Q - 1, &mods)
646                            .into_iter()
647                            .zip(&mods)
648                            .map(|(x, q)| DummyVal::new(x, *q))
649                            .collect_vec(),
650                    )
651                })
652                .collect_vec();
653
654            let mut d = Dummy::new();
655
656            let z = d.mixed_radix_addition_msb_only(&xs).unwrap();
657            let res = d.output(&z).unwrap().unwrap();
658
659            let should_be = *util::as_mixed_radix((Q - 1) * (nargs as u128) % Q, &mods)
660                .last()
661                .unwrap();
662            assert_eq!(res, should_be);
663
664            // test random values
665            for _ in 0..4 {
666                let mut sum = 0;
667
668                let xs = (0..nargs)
669                    .map(|_| {
670                        let x = rng.gen_u128() % Q;
671                        sum = (sum + x) % Q;
672                        Bundle::new(
673                            util::as_mixed_radix(x, &mods)
674                                .into_iter()
675                                .zip(&mods)
676                                .map(|(x, q)| DummyVal::new(x, *q))
677                                .collect_vec(),
678                        )
679                    })
680                    .collect_vec();
681
682                let mut d = Dummy::new();
683                let z = d.mixed_radix_addition_msb_only(&xs).unwrap();
684                let res = d.output(&z).unwrap().unwrap();
685
686                let should_be = *util::as_mixed_radix(sum, &mods).last().unwrap();
687                assert_eq!(res, should_be);
688            }
689        }
690    }
691}
692
693#[cfg(test)]
694mod pmr_tests {
695    use super::*;
696    use crate::{
697        fancy::{BundleGadgets, CrtGadgets, FancyInput},
698        util::RngExt,
699    };
700
701    #[test]
702    fn pmr() {
703        let mut rng = rand::thread_rng();
704        for _ in 0..8 {
705            let ps = rng.gen_usable_factors();
706            let q = crate::util::product(&ps);
707            let pt = rng.gen_u128() % q;
708
709            let mut f = Dummy::new();
710            let x = f.crt_encode(pt, q).unwrap();
711            let z = f.crt_to_pmr(&x).unwrap();
712            let res = f.output_bundle(&z).unwrap().unwrap();
713
714            let should_be = to_pmr_pt(pt, &ps);
715            assert_eq!(res, should_be);
716        }
717    }
718
719    fn to_pmr_pt(x: u128, ps: &[u16]) -> Vec<u16> {
720        let mut ds = vec![0; ps.len()];
721        let mut q = 1;
722        for i in 0..ps.len() {
723            let p = ps[i] as u128;
724            ds[i] = ((x / q) % p) as u16;
725            q *= p;
726        }
727        ds
728    }
729
730    #[test]
731    fn pmr_lt() {
732        let mut rng = rand::thread_rng();
733        for _ in 0..8 {
734            let qs = rng.gen_usable_factors();
735            let n = qs.len();
736            let q = crate::util::product(&qs);
737            let q_ = crate::util::product(&qs[..n - 1]);
738            let pt_x = rng.gen_u128() % q_;
739            let pt_y = rng.gen_u128() % q_;
740
741            let mut f = Dummy::new();
742            let crt_x = f.crt_encode(pt_x, q).unwrap();
743            let crt_y = f.crt_encode(pt_y, q).unwrap();
744            let z = f.pmr_lt(&crt_x, &crt_y).unwrap();
745            let res = f.output(&z).unwrap().unwrap();
746
747            let should_be = if pt_x < pt_y { 1 } else { 0 };
748            assert_eq!(res, should_be, "q={}, x={}, y={}", q, pt_x, pt_y);
749        }
750    }
751
752    #[test]
753    fn pmr_geq() {
754        let mut rng = rand::thread_rng();
755        for _ in 0..8 {
756            let qs = rng.gen_usable_factors();
757            let n = qs.len();
758            let q = crate::util::product(&qs);
759            let q_ = crate::util::product(&qs[..n - 1]);
760            let pt_x = rng.gen_u128() % q_;
761            let pt_y = rng.gen_u128() % q_;
762
763            let mut f = Dummy::new();
764            let crt_x = f.crt_encode(pt_x, q).unwrap();
765            let crt_y = f.crt_encode(pt_y, q).unwrap();
766            let z = f.pmr_geq(&crt_x, &crt_y).unwrap();
767            let res = f.output(&z).unwrap().unwrap();
768
769            let should_be = if pt_x >= pt_y { 1 } else { 0 };
770            assert_eq!(res, should_be, "q={}, x={}, y={}", q, pt_x, pt_y);
771        }
772    }
773
774    #[test]
775    #[ignore]
776    fn crt_div() {
777        let mut rng = rand::thread_rng();
778        for _ in 0..8 {
779            let qs = rng.gen_usable_factors();
780            let n = qs.len();
781            let q = crate::util::product(&qs);
782            let q_ = crate::util::product(&qs[..n - 1]);
783            let pt_x = rng.gen_u128() % q_;
784            let pt_y = rng.gen_u128() % q_;
785
786            let mut f = Dummy::new();
787            let crt_x = f.crt_encode(pt_x, q).unwrap();
788            let crt_y = f.crt_encode(pt_y, q).unwrap();
789            let z = f.crt_div(&crt_x, &crt_y).unwrap();
790            let res = f.crt_output(&z).unwrap().unwrap();
791
792            let should_be = pt_x / pt_y;
793            assert_eq!(res, should_be, "q={}, x={}, y={}", q, pt_x, pt_y);
794        }
795    }
796}