1use crate::errors::FancyError;
7use itertools::Itertools;
8
9mod binary;
10mod bundle;
11mod crt;
12mod input;
13mod reveal;
14pub use binary::{BinaryBundle, BinaryGadgets};
15pub use bundle::{ArithmeticBundleGadgets, BinaryBundleGadgets, Bundle, BundleGadgets};
16pub use crt::{CrtBundle, CrtGadgets};
17pub use input::FancyInput;
18pub use reveal::FancyReveal;
19
20pub trait HasModulus {
22 fn modulus(&self) -> u16;
24}
25
26pub trait FancyBinary: Fancy {
29 fn xor(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error>;
31
32 fn and(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error>;
34
35 fn negate(&mut self, x: &Self::Item) -> Result<Self::Item, Self::Error>;
37
38 fn or(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error> {
40 let notx = self.negate(x)?;
41 let noty = self.negate(y)?;
42 let z = self.and(¬x, ¬y)?;
43 self.negate(&z)
44 }
45
46 fn adder(
48 &mut self,
49 x: &Self::Item,
50 y: &Self::Item,
51 carry_in: Option<&Self::Item>,
52 ) -> Result<(Self::Item, Self::Item), Self::Error> {
53 if let Some(c) = carry_in {
54 let z1 = self.xor(x, y)?;
55 let z2 = self.xor(&z1, c)?;
56 let z3 = self.xor(x, c)?;
57 let z4 = self.and(&z1, &z3)?;
58 let carry = self.xor(&z4, x)?;
59 Ok((z2, carry))
60 } else {
61 let z = self.xor(x, y)?;
62 let carry = self.and(x, y)?;
63 Ok((z, carry))
64 }
65 }
66 fn and_many(&mut self, args: &[Self::Item]) -> Result<Self::Item, Self::Error> {
68 if args.is_empty() {
69 return Err(Self::Error::from(FancyError::InvalidArgNum {
70 got: args.len(),
71 needed: 1,
72 }));
73 }
74 args.iter()
75 .skip(1)
76 .fold(Ok(args[0].clone()), |acc, x| self.and(&(acc?), x))
77 }
78
79 fn or_many(&mut self, args: &[Self::Item]) -> Result<Self::Item, Self::Error> {
81 if args.is_empty() {
82 return Err(Self::Error::from(FancyError::InvalidArgNum {
83 got: args.len(),
84 needed: 1,
85 }));
86 }
87 args.iter()
88 .skip(1)
89 .fold(Ok(args[0].clone()), |acc, x| self.or(&(acc?), x))
90 }
91
92 fn xor_many(&mut self, args: &[Self::Item]) -> Result<Self::Item, Self::Error> {
94 if args.len() < 2 {
95 return Err(Self::Error::from(FancyError::InvalidArgNum {
96 got: args.len(),
97 needed: 2,
98 }));
99 }
100 args.iter()
101 .skip(1)
102 .fold(Ok(args[0].clone()), |acc, x| self.xor(&(acc?), x))
103 }
104
105 fn mux_constant_bits(
107 &mut self,
108 x: &Self::Item,
109 b1: bool,
110 b2: bool,
111 ) -> Result<Self::Item, Self::Error> {
112 match (b1, b2) {
113 (false, true) => Ok(x.clone()),
114 (true, false) => self.negate(x),
115 (false, false) => self.constant(0, 2),
116 (true, true) => self.constant(1, 2),
117 }
118 }
119
120 fn mux(
122 &mut self,
123 b: &Self::Item,
124 x: &Self::Item,
125 y: &Self::Item,
126 ) -> Result<Self::Item, Self::Error> {
127 let xor = self.xor(x, y)?;
128 let and = self.and(b, &xor)?;
129 self.xor(&and, x)
130 }
131}
132
133pub trait Fancy {
138 type Item: Clone + HasModulus;
140
141 type Error: std::fmt::Debug + std::fmt::Display + std::convert::From<FancyError>;
143
144 fn constant(&mut self, x: u16, q: u16) -> Result<Self::Item, Self::Error>;
146
147 fn output(&mut self, x: &Self::Item) -> Result<Option<u16>, Self::Error>;
150
151 fn outputs(&mut self, xs: &[Self::Item]) -> Result<Option<Vec<u16>>, Self::Error> {
153 let mut zs = Vec::with_capacity(xs.len());
154 for x in xs.iter() {
155 zs.push(self.output(x)?);
156 }
157 Ok(zs.into_iter().collect())
158 }
159}
160
161pub trait FancyArithmetic: Fancy {
163 fn add(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error>;
165
166 fn sub(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error>;
168
169 fn cmul(&mut self, x: &Self::Item, c: u16) -> Result<Self::Item, Self::Error>;
171
172 fn mul(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error>;
174
175 fn proj(
179 &mut self,
180 x: &Self::Item,
181 q: u16,
182 tt: Option<Vec<u16>>,
183 ) -> Result<Self::Item, Self::Error>;
184
185 fn add_many(&mut self, args: &[Self::Item]) -> Result<Self::Item, Self::Error> {
190 if args.len() < 2 {
191 return Err(Self::Error::from(FancyError::InvalidArgNum {
192 got: args.len(),
193 needed: 2,
194 }));
195 }
196 let mut z = args[0].clone();
197 for x in args.iter().skip(1) {
198 z = self.add(&z, x)?;
199 }
200 Ok(z)
201 }
202 fn mod_change(&mut self, x: &Self::Item, to_modulus: u16) -> Result<Self::Item, Self::Error> {
204 let from_modulus = x.modulus();
205 if from_modulus == to_modulus {
206 return Ok(x.clone());
207 }
208 let tab = (0..from_modulus).map(|x| x % to_modulus).collect_vec();
209 self.proj(x, to_modulus, Some(tab))
210 }
211}
212
213macro_rules! check_binary {
214 ($x:ident) => {
215 if $x.modulus() != 2 {
216 return Err(Self::Error::from(FancyError::InvalidArgMod {
217 got: $x.modulus(),
218 needed: 2,
219 }));
220 }
221 };
222}
223
224macro_rules! derive_binary {
236 ($f:ident$(<$( $t:tt ),+>)?) => {
237 impl FancyBinary for $f$(< $($t),* >)? {
238 fn xor(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error> {
239 check_binary!(x);
240 check_binary!(y);
241
242 self.add(x, y)
243 }
244
245 fn and(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error> {
246 check_binary!(x);
247 check_binary!(y);
248
249 self.mul(x, y)
250 }
251
252 fn negate(&mut self, x: &Self::Item) -> Result<Self::Item, Self::Error> {
253 check_binary!(x);
254
255 let c = self.constant(1, 2)?;
256 self.xor(x, &c)
257 }
258 }
259 };
260}
261pub(crate) use check_binary;
262pub(crate) use derive_binary;