Skip to main content

fancy_garbling/circuits/arithmetic/
mod_change.rs

1use crate::{Circuit, FancyProj, HasModulus};
2use swanky_channel::Channel;
3use swanky_error::Result;
4
5/// Given `(x, modulus)`, change the modulus of `x` to `modulus`.
6pub struct ModChange;
7
8impl<F: FancyProj> Circuit<F> for ModChange {
9    type Input = (F::Item, u16);
10    type Output = F::Item;
11
12    fn execute(
13        &self,
14        backend: &mut F,
15        inputs: Self::Input,
16        channel: &mut Channel,
17    ) -> Result<Self::Output> {
18        let (x, to_modulus) = inputs;
19
20        let from_modulus = x.modulus();
21        if from_modulus == to_modulus {
22            return Ok(x.clone());
23        }
24        let tab = (0..from_modulus)
25            .map(|x| x % to_modulus)
26            .collect::<Vec<_>>();
27        backend.proj(&x, to_modulus, Some(tab), channel)
28    }
29}
30
31#[cfg(test)]
32mod test {
33    use crate::{
34        circuits::arithmetic::ModChange,
35        dummy::{Dummy, DummyVal},
36        util::RngExt,
37    };
38    use rand::{Rng, thread_rng};
39
40    #[test]
41    fn mod_change() {
42        let mut rng = thread_rng();
43        for _ in 0..16 {
44            let q = rng.gen_prime();
45            let p = rng.gen_prime();
46
47            let x = rng.r#gen::<u16>() % q;
48            let x_input = DummyVal::new(x, q);
49            let z = Dummy::eval(&ModChange, (x_input, p)).unwrap();
50            assert_eq!(z.val(), x % p);
51        }
52    }
53}