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}
191define_bdd_2w_to_1w_trait!(pub Add, add);
192define_bdd_2w_to_1w_trait!(pub Sub, sub);
193define_bdd_2w_to_1w_trait!(pub Sll, sll);
194define_bdd_2w_to_1w_trait!(pub Sra, sra);
195define_bdd_2w_to_1w_trait!(pub Srl, srl);
196define_bdd_2w_to_1w_trait!(pub Slt, slt);
197define_bdd_2w_to_1w_trait!(pub Sltu, sltu);
198define_bdd_2w_to_1w_trait!(pub Or, or);
199define_bdd_2w_to_1w_trait!(pub And, and);
200define_bdd_2w_to_1w_trait!(pub Xor, xor);
201
202impl_bdd_2w_to_1w_trait!(
203 Add,
204 add,
205 u32,
206 circuits::u32::add_codegen::AnyBitCircuit,
207 circuits::u32::add_codegen::OUTPUT_CIRCUITS
208);
209
210impl_bdd_2w_to_1w_trait!(
211 Sub,
212 sub,
213 u32,
214 circuits::u32::sub_codegen::AnyBitCircuit,
215 circuits::u32::sub_codegen::OUTPUT_CIRCUITS
216);
217
218impl_bdd_2w_to_1w_trait!(
219 Sll,
220 sll,
221 u32,
222 circuits::u32::sll_codegen::AnyBitCircuit,
223 circuits::u32::sll_codegen::OUTPUT_CIRCUITS
224);
225
226impl_bdd_2w_to_1w_trait!(
227 Sra,
228 sra,
229 u32,
230 circuits::u32::sra_codegen::AnyBitCircuit,
231 circuits::u32::sra_codegen::OUTPUT_CIRCUITS
232);
233
234impl_bdd_2w_to_1w_trait!(
235 Srl,
236 srl,
237 u32,
238 circuits::u32::srl_codegen::AnyBitCircuit,
239 circuits::u32::srl_codegen::OUTPUT_CIRCUITS
240);
241
242impl_bdd_2w_to_1w_trait!(
243 Slt,
244 slt,
245 u32,
246 circuits::u32::slt_codegen::AnyBitCircuit,
247 circuits::u32::slt_codegen::OUTPUT_CIRCUITS
248);
249
250impl_bdd_2w_to_1w_trait!(
251 Sltu,
252 sltu,
253 u32,
254 circuits::u32::sltu_codegen::AnyBitCircuit,
255 circuits::u32::sltu_codegen::OUTPUT_CIRCUITS
256);
257
258impl_bdd_2w_to_1w_trait!(
259 And,
260 and,
261 u32,
262 circuits::u32::and_codegen::AnyBitCircuit,
263 circuits::u32::and_codegen::OUTPUT_CIRCUITS
264);
265
266impl_bdd_2w_to_1w_trait!(
267 Or,
268 or,
269 u32,
270 circuits::u32::or_codegen::AnyBitCircuit,
271 circuits::u32::or_codegen::OUTPUT_CIRCUITS
272);
273
274impl_bdd_2w_to_1w_trait!(
275 Xor,
276 xor,
277 u32,
278 circuits::u32::xor_codegen::AnyBitCircuit,
279 circuits::u32::xor_codegen::OUTPUT_CIRCUITS
280);