1use crate::{
7 FancyArithmetic, FancyBinary, check_binary, derive_binary,
8 errors::{DummyError, FancyError},
9 fancy::{Fancy, FancyInput, FancyReveal, HasModulus},
10};
11
12pub struct Dummy {}
14
15#[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 pub fn new(val: u16, modulus: u16) -> Self {
31 Self { val, modulus }
32 }
33
34 pub fn val(&self) -> u16 {
36 self.val
37 }
38}
39
40impl Dummy {
41 pub fn new() -> Dummy {
43 Dummy {}
44 }
45}
46
47impl FancyInput for Dummy {
48 type Item = DummyVal;
49 type Error = DummyError;
50
51 fn encode(&mut self, value: u16, modulus: u16) -> Result<DummyVal, DummyError> {
53 Ok(DummyVal::new(value, modulus))
54 }
55
56 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 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] 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); 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 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 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}