fancy_garbling/circuits/binary/
binary_twos_complement.rs1use crate::{
2 BinaryBundle, FancyBinary,
3 circuit::Circuit,
4 circuits::binary::{BinaryAdditionNoCarry, BinaryConstant},
5};
6use core::marker::PhantomData;
7use swanky_channel::Channel;
8use swanky_error::Result;
9
10#[derive(Default)]
12pub struct BinaryTwosComplement<'a>(PhantomData<&'a ()>);
13
14impl<'a> BinaryTwosComplement<'a> {
15 pub fn new() -> Self {
17 Default::default()
18 }
19}
20
21impl<'a, F: FancyBinary> Circuit<F> for BinaryTwosComplement<'a>
22where
23 F::Item: 'a,
24{
25 type Input = &'a BinaryBundle<F::Item>;
26 type Output = BinaryBundle<F::Item>;
27
28 fn execute(
29 &self,
30 backend: &mut F,
31 input: Self::Input,
32 channel: &mut Channel,
33 ) -> Result<Self::Output> {
34 let not_xs = BinaryBundle::new(
35 input
36 .wires()
37 .iter()
38 .map(|x| backend.negate(x))
39 .collect::<Vec<_>>(),
40 );
41 let one = BinaryConstant::new(1, input.size()).execute(backend, (), channel)?;
42 BinaryAdditionNoCarry::new().execute(backend, (¬_xs, &one), channel)
43 }
44}
45
46pub mod test {
47 use crate::circuit::CircuitInputMapper;
48
49 use super::*;
50
51 pub struct TestBinaryTwosComplement(pub usize);
53 impl<F: FancyBinary> Circuit<F> for TestBinaryTwosComplement {
54 type Input = BinaryBundle<F::Item>;
55 type Output = BinaryBundle<F::Item>;
56
57 fn execute(
58 &self,
59 backend: &mut F,
60 inputs: Self::Input,
61 channel: &mut Channel,
62 ) -> Result<Self::Output> {
63 BinaryTwosComplement::new().execute(backend, &inputs, channel)
64 }
65 }
66
67 impl<F: FancyBinary> CircuitInputMapper<F> for TestBinaryTwosComplement {
68 fn map(&self, inputs: Vec<<F as crate::Fancy>::Item>) -> Self::Input {
69 assert_eq!(inputs.len(), self.0);
70 BinaryBundle::new(inputs)
71 }
72
73 fn ninputs(&self) -> usize {
74 self.0
75 }
76
77 fn modulus(&self, _: usize) -> u16 {
78 2
79 }
80 }
81
82 #[test]
83 fn binary_twos_complement() {
84 use crate::dummy::{Dummy, DummyVal};
85 use rand::Rng;
86
87 let mut rng = rand::thread_rng();
88 let nbits = 64;
89 let q = 1 << nbits;
90 let c = TestBinaryTwosComplement(nbits);
91
92 for _ in 0..16 {
93 let x = rng.r#gen::<u128>() % q;
94 let x_input = DummyVal::to_binary(x, nbits);
95 let output = Dummy::eval(&c, x_input).unwrap();
96 assert_eq!(DummyVal::from_binary(&output), (((!x) % q) + 1) % q);
97 }
98 }
99}