poulpy/poulpy-schemes/src/bin_fhe/bdd_arithmetic/bdd_2w_to_1w.rs
poulpy-schemes/src/bin_fhe/bdd_arithmetic/bdd_2w_to_1w.rsRaw
1use std::marker::PhantomData;
2
3use poulpy_core::{
4 GLWECopy, GLWEPacking, ScratchTakeCore,
5 layouts::{GGLWEInfos, GGLWEPreparedToRef, GGSWPrepared, GLWEAutomorphismKeyHelper, GetGaloisElement},
6};
7use poulpy_hal::{
8 api::ModuleLogN,
9 layouts::{Backend, DataMut, DataRef, Module, Scratch},
10};
11
12use crate::bin_fhe::bdd_arithmetic::{
13 BitSize, ExecuteBDDCircuit, FheUint, FheUintPrepared, GetBitCircuitInfo, GetGGSWBit, UnsignedInteger, circuits,
14};
15
16impl<BE: Backend> ExecuteBDDCircuit2WTo1W<BE> for Module<BE> where Self: Sized + ExecuteBDDCircuit<BE> + GLWEPacking<BE> + GLWECopy
17{}
18
19pub trait ExecuteBDDCircuit2WTo1W<BE: Backend>
20where
21 Self: Sized + ModuleLogN + ExecuteBDDCircuit<BE> + GLWEPacking<BE> + GLWECopy,
22{
23 fn execute_bdd_circuit_2w_to_1w<R, C, A, B, K, H, T>(
24 &self,
25 out: &mut FheUint<R, T>,
26 circuit: &C,
27 a: &FheUintPrepared<A, T, BE>,
28 b: &FheUintPrepared<B, T, BE>,
29 key: &H,
30 scratch: &mut Scratch<BE>,
31 ) where
32 T: UnsignedInteger,
33 C: GetBitCircuitInfo,
34 R: DataMut,
35 A: DataRef,
36 B: DataRef,
37 K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos,
38 H: GLWEAutomorphismKeyHelper<K, BE>,
39 Scratch<BE>: ScratchTakeCore<BE>,
40 {
41 self.execute_bdd_circuit_2w_to_1w_multi_thread(1, out, circuit, a, b, key, scratch);
42 }
43
44 #[allow(clippy::too_many_arguments)]
45 /// Operations Z x Z -> Z
46 fn execute_bdd_circuit_2w_to_1w_multi_thread<R, C, A, B, K, H, T>(
47 &self,
48 threads: usize,
49 out: &mut FheUint<R, T>,
50 circuit: &C,
51 a: &FheUintPrepared<A, T, BE>,
52 b: &FheUintPrepared<B, T, BE>,
53 key: &H,
54 scratch: &mut Scratch<BE>,
55 ) where
56 T: UnsignedInteger,
57 C: GetBitCircuitInfo,
58 R: DataMut,
59 A: DataRef,
60 B: DataRef,
61 K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos,
62 H: GLWEAutomorphismKeyHelper<K, BE>,
63 Scratch<BE>: ScratchTakeCore<BE>,
64 {
65 // Collects inputs into a single array
66 let inputs: Vec<&dyn GetGGSWBit<BE>> = [a as &dyn GetGGSWBit<BE>, b as &dyn GetGGSWBit<BE>].to_vec();
67 let helper: FheUintHelper<'_, T, BE> = FheUintHelper {
68 data: inputs,
69 _phantom: PhantomData,
70 };
71
72 let (mut out_bits, scratch_1) = scratch.take_glwe_slice(T::BITS as usize, out);
73
74 // Evaluates out[i] = circuit[i](a, b)
75 self.execute_bdd_circuit_multi_thread(threads, &mut out_bits, &helper, circuit, scratch_1);
76
77 // Repacks the bits
78 out.pack(self, out_bits, key, scratch_1);
79 }
80}
81
82struct FheUintHelper<'a, T: UnsignedInteger, BE: Backend> {
83 data: Vec<&'a dyn GetGGSWBit<BE>>,
84 _phantom: PhantomData<T>,
85}
86
87impl<'a, T: UnsignedInteger, BE: Backend> GetGGSWBit<BE> for FheUintHelper<'a, T, BE> {
88 fn get_bit(&self, bit: usize) -> GGSWPrepared<&[u8], BE> {
89 let lo: usize = bit % T::BITS as usize;
90 let hi: usize = bit / T::BITS as usize;
91 self.data[hi].get_bit(lo)
92 }
93}
94
95impl<'a, T: UnsignedInteger, BE: Backend> BitSize for FheUintHelper<'a, T, BE> {
96 fn bit_size(&self) -> usize {
97 T::BITS as usize * self.data.len()
98 }
99}
100
101#[macro_export]
102macro_rules! define_bdd_2w_to_1w_trait {
103 ($(#[$meta:meta])* $vis:vis $trait_name:ident, $method_name:ident) => {
104 paste::paste! {
105 $(#[$meta])*
106 $vis trait $trait_name<T: UnsignedInteger, BE: Backend> {
107
108 /// Single-threaded version
109 fn $method_name<A, M, K, H, B>(
110 &mut self,
111 module: &M,
112 a: &FheUintPrepared<A, T, BE>,
113 b: &FheUintPrepared<B, T, BE>,
114 key: &H,
115 scratch: &mut Scratch<BE>,
116 ) where
117 M: ExecuteBDDCircuit2WTo1W<BE>,
118 A: DataRef,
119 B: DataRef,
120 K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos,
121 H: GLWEAutomorphismKeyHelper<K, BE>,
122 Scratch<BE>: ScratchTakeCore<BE>;
123
124 /// Multithreaded version – same vis, method_name + "_multi_thread"
125 fn [<$method_name _multi_thread>]<A, M, K, H, B>(
126 &mut self,
127 threads: usize,
128 module: &M,
129 a: &FheUintPrepared<A, T, BE>,
130 b: &FheUintPrepared<B, T, BE>,
131 key: &H,
132 scratch: &mut Scratch<BE>,
133 ) where
134 M: ExecuteBDDCircuit2WTo1W<BE>,
135 A: DataRef,
136 B: DataRef,
137 K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos,
138 H: GLWEAutomorphismKeyHelper<K, BE>,
139 Scratch<BE>: ScratchTakeCore<BE>;
140 }
141 }
142 };
143}
144
145#[macro_export]
146macro_rules! impl_bdd_2w_to_1w_trait {
147 ($trait_name:ident, $method_name:ident, $ty:ty, $circuit_ty:ty, $output_circuits:path) => {
148 paste::paste! {
149 impl<D: DataMut, BE: Backend> $trait_name<$ty, BE> for FheUint<D, $ty> {
150
151 fn $method_name<A, M, K, H, B>(
152 &mut self,
153 module: &M,
154 a: &FheUintPrepared<A, $ty, BE>,
155 b: &FheUintPrepared<B, $ty, BE>,
156 key: &H,
157 scratch: &mut Scratch<BE>,
158 ) where
159 M: ExecuteBDDCircuit2WTo1W<BE>,
160 A: DataRef,
161 B: DataRef,
162 K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos,
163 H: GLWEAutomorphismKeyHelper<K, BE>,
164 Scratch<BE>: ScratchTakeCore<BE>,
165 {
166 module.execute_bdd_circuit_2w_to_1w(self, &$output_circuits, a, b, key, scratch)
167 }
168
169 fn [<$method_name _multi_thread>]<A, M, K, H, B>(
170 &mut self,
171 threads: usize,
172 module: &M,
173 a: &FheUintPrepared<A, $ty, BE>,
174 b: &FheUintPrepared<B, $ty, BE>,
175 key: &H,
176 scratch: &mut Scratch<BE>,
177 ) where
178 M: ExecuteBDDCircuit2WTo1W<BE>,
179 A: DataRef,
180 B: DataRef,
181 K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos,
182 H: GLWEAutomorphismKeyHelper<K, BE>,
183 Scratch<BE>: ScratchTakeCore<BE>,
184 {
185 module.execute_bdd_circuit_2w_to_1w_multi_thread(threads, self, &$output_circuits, a, b, key, scratch)
186 }
187 }
188 }
189 };
190}
191
192// a + b
193define_bdd_2w_to_1w_trait!(pub Add, add);
194
195// a - b
196define_bdd_2w_to_1w_trait!(pub Sub, sub);
197
198// a << b
199define_bdd_2w_to_1w_trait!(pub Sll, sll);
200
201// a >> b arithmetic
202define_bdd_2w_to_1w_trait!(pub Sra, sra);
203
204// a >> b logical
205define_bdd_2w_to_1w_trait!(pub Srl, srl);
206
207// signed a < signed b
208define_bdd_2w_to_1w_trait!(pub Slt, slt);
209
210// unsigned a < unsigned b
211define_bdd_2w_to_1w_trait!(pub Sltu, sltu);
212
213// a or b
214define_bdd_2w_to_1w_trait!(pub Or, or);
215
216// a and b
217define_bdd_2w_to_1w_trait!(pub And, and);
218
219// a xor b
220define_bdd_2w_to_1w_trait!(pub Xor, xor);
221
222impl_bdd_2w_to_1w_trait!(
223 Add,
224 add,
225 u32,
226 circuits::u32::add_codegen::AnyBitCircuit,
227 circuits::u32::add_codegen::OUTPUT_CIRCUITS
228);
229
230impl_bdd_2w_to_1w_trait!(
231 Sub,
232 sub,
233 u32,
234 circuits::u32::sub_codegen::AnyBitCircuit,
235 circuits::u32::sub_codegen::OUTPUT_CIRCUITS
236);
237
238impl_bdd_2w_to_1w_trait!(
239 Sll,
240 sll,
241 u32,
242 circuits::u32::sll_codegen::AnyBitCircuit,
243 circuits::u32::sll_codegen::OUTPUT_CIRCUITS
244);
245
246impl_bdd_2w_to_1w_trait!(
247 Sra,
248 sra,
249 u32,
250 circuits::u32::sra_codegen::AnyBitCircuit,
251 circuits::u32::sra_codegen::OUTPUT_CIRCUITS
252);
253
254impl_bdd_2w_to_1w_trait!(
255 Srl,
256 srl,
257 u32,
258 circuits::u32::srl_codegen::AnyBitCircuit,
259 circuits::u32::srl_codegen::OUTPUT_CIRCUITS
260);
261
262impl_bdd_2w_to_1w_trait!(
263 Slt,
264 slt,
265 u32,
266 circuits::u32::slt_codegen::AnyBitCircuit,
267 circuits::u32::slt_codegen::OUTPUT_CIRCUITS
268);
269
270impl_bdd_2w_to_1w_trait!(
271 Sltu,
272 sltu,
273 u32,
274 circuits::u32::sltu_codegen::AnyBitCircuit,
275 circuits::u32::sltu_codegen::OUTPUT_CIRCUITS
276);
277
278impl_bdd_2w_to_1w_trait!(
279 And,
280 and,
281 u32,
282 circuits::u32::and_codegen::AnyBitCircuit,
283 circuits::u32::and_codegen::OUTPUT_CIRCUITS
284);
285
286impl_bdd_2w_to_1w_trait!(
287 Or,
288 or,
289 u32,
290 circuits::u32::or_codegen::AnyBitCircuit,
291 circuits::u32::or_codegen::OUTPUT_CIRCUITS
292);
293
294impl_bdd_2w_to_1w_trait!(
295 Xor,
296 xor,
297 u32,
298 circuits::u32::xor_codegen::AnyBitCircuit,
299 circuits::u32::xor_codegen::OUTPUT_CIRCUITS
300);