fancy_garbling/circuits/arithmetic/
subtraction.rs1use crate::{CrtBundle, FancyArithmetic, circuit::Circuit};
2use core::marker::PhantomData;
3use swanky_channel::Channel;
4use swanky_error::Result;
5
6#[derive(Default)]
8pub struct Subtraction<'a>(PhantomData<&'a ()>);
9
10impl<'a> Subtraction<'a> {
11 pub fn new() -> Self {
13 Default::default()
14 }
15}
16
17impl<'a, F: FancyArithmetic> Circuit<F> for Subtraction<'a>
18where
19 F::Item: 'a,
20{
21 type Input = (&'a CrtBundle<F::Item>, &'a CrtBundle<F::Item>);
22 type Output = CrtBundle<F::Item>;
23
24 fn execute(
25 &self,
26 backend: &mut F,
27 inputs: Self::Input,
28 _: &mut Channel,
29 ) -> Result<Self::Output> {
30 let (x, y) = inputs;
31 assert_eq!(x.size(), y.size(), "`x` and `y` must be the same length");
32 Ok(CrtBundle::new(
33 x.wires()
34 .iter()
35 .zip(y.wires().iter())
36 .map(|(x, y)| backend.sub(x, y))
37 .collect(),
38 ))
39 }
40}
41
42#[cfg(test)]
43mod test {
44 use crate::{
45 circuits::arithmetic::Subtraction,
46 dummy::{Dummy, DummyVal},
47 util::RngExt,
48 };
49 use rand::{Rng, thread_rng};
50
51 #[test]
52 fn subtraction() {
53 let mut rng = thread_rng();
54 let q = rng.gen_usable_composite_modulus();
55
56 for _ in 0..16 {
57 let x = rng.r#gen::<u128>() % q;
58 let y = rng.r#gen::<u128>() % q;
59 let x_input = DummyVal::to_crt(x, q);
60 let y_input = DummyVal::to_crt(y, q);
61 let circuit = Subtraction::new();
62 let z = Dummy::eval(&circuit, (&x_input, &y_input)).unwrap();
63 let output = DummyVal::from_crt(&z, q);
64 assert_eq!(output, (x + q - y) % q);
65 }
66 }
67}