fancy_garbling/circuits/binary/
binary_abs.rs1use crate::{
2 BinaryBundle, FancyBinary,
3 circuit::Circuit,
4 circuits::binary::{BinaryMultiplex, BinaryTwosComplement},
5};
6use core::marker::PhantomData;
7use swanky_channel::Channel;
8use swanky_error::Result;
9
10#[derive(Default)]
12pub struct BinaryAbs<'a>(PhantomData<&'a ()>);
13
14impl<'a> BinaryAbs<'a> {
15 pub fn new() -> Self {
17 Default::default()
18 }
19}
20
21impl<'a, F: FancyBinary> Circuit<F> for BinaryAbs<'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 inputs: Self::Input,
32 channel: &mut Channel,
33 ) -> Result<Self::Output> {
34 let x = inputs;
35
36 let sign = x.wires().last().unwrap();
37 let negated = BinaryTwosComplement::new().execute(backend, x, channel)?;
38 BinaryMultiplex::new().execute(backend, (sign.clone(), x, &negated), channel)
39 }
40}
41
42#[cfg(test)]
43mod test {
44 use crate::{
45 circuits::binary::BinaryAbs,
46 dummy::{Dummy, DummyVal},
47 };
48 use rand::{Rng, thread_rng};
49
50 #[test]
51 fn binary_abs() {
52 let mut rng = thread_rng();
53 let nbits = 64;
54 let q = 1 << nbits;
55
56 for _ in 0..16 {
57 let x = rng.r#gen::<u128>() % q;
58 let x_input = DummyVal::to_binary(x, nbits);
59 let circuit = BinaryAbs::new();
60 let output = Dummy::eval(&circuit, &x_input).unwrap();
61 assert_eq!(
62 DummyVal::from_binary(&output),
63 if x >> (nbits - 1) > 0 {
64 ((!x) + 1) & ((1 << nbits) - 1)
65 } else {
66 x
67 }
68 );
69 }
70 }
71}