poulpy/poulpy-schemes/src/tfhe/bdd_arithmetic/bdd_2w_to_1w.rs
poulpy-schemes/src/tfhe/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::tfhe::bdd_arithmetic::{
13 BitSize, ExecuteBDDCircuit, FheUint, FheUintPrepared, GetBitCircuitInfo, GetGGSWBit, UnsignedInteger, circuits,
14};
15
16impl<T: UnsignedInteger, BE: Backend> ExecuteBDDCircuit2WTo1W<T, BE> for Module<BE> where
17 Self: Sized + ExecuteBDDCircuit<T, BE> + GLWEPacking<BE> + GLWECopy
18{
19}
20
21pub trait ExecuteBDDCircuit2WTo1W<T: UnsignedInteger, BE: Backend>
22where
23 Self: Sized + ModuleLogN + ExecuteBDDCircuit<T, BE> + GLWEPacking<BE> + GLWECopy,
24{
25 /// Operations Z x Z -> Z
26 fn execute_bdd_circuit_2w_to_1w<R, C, A, B, K, H>(
27 &self,
28 out: &mut FheUint<R, T>,
29 circuit: &C,
30 a: &FheUintPrepared<A, T, BE>,
31 b: &FheUintPrepared<B, T, BE>,
32 key: &H,
33 scratch: &mut Scratch<BE>,
34 ) where
35 C: GetBitCircuitInfo<T>,
36 R: DataMut,
37 A: DataRef,
38 B: DataRef,
39 K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos,
40 H: GLWEAutomorphismKeyHelper<K, BE>,
41 Scratch<BE>: ScratchTakeCore<BE>,
42 {
43 // Collects inputs into a single array
44 let inputs: Vec<&dyn GetGGSWBit<BE>> = [a as &dyn GetGGSWBit<BE>, b as &dyn GetGGSWBit<BE>].to_vec();
45 let helper: FheUintHelper<'_, T, BE> = FheUintHelper {
46 data: inputs,
47 _phantom: PhantomData,
48 };
49
50 let (mut out_bits, scratch_1) = scratch.take_glwe_slice(T::BITS as usize, out);
51
52 // Evaluates out[i] = circuit[i](a, b)
53 self.execute_bdd_circuit(&mut out_bits, &helper, circuit, scratch_1);
54
55 // Repacks the bits
56 out.pack(self, out_bits, key, scratch_1);
57 }
58}
59
60struct FheUintHelper<'a, T: UnsignedInteger, BE: Backend> {
61 data: Vec<&'a dyn GetGGSWBit<BE>>,
62 _phantom: PhantomData<T>,
63}
64
65impl<'a, T: UnsignedInteger, BE: Backend> GetGGSWBit<BE> for FheUintHelper<'a, T, BE> {
66 fn get_bit(&self, bit: usize) -> GGSWPrepared<&[u8], BE> {
67 let lo: usize = bit % T::BITS as usize;
68 let hi: usize = bit / T::BITS as usize;
69 self.data[hi].get_bit(lo)
70 }
71}
72
73impl<'a, T: UnsignedInteger, BE: Backend> BitSize for FheUintHelper<'a, T, BE> {
74 fn bit_size(&self) -> usize {
75 T::BITS as usize * self.data.len()
76 }
77}
78
79pub struct JoinedBits<A, B> {
80 pub lo: A,
81 pub hi: B,
82 pub split: usize, // 32 in your example
83}
84
85impl<A, B, BE> GetGGSWBit<BE> for JoinedBits<A, B>
86where
87 BE: Backend,
88 A: GetGGSWBit<BE>,
89 B: GetGGSWBit<BE>,
90{
91 fn get_bit(&self, bit: usize) -> GGSWPrepared<&[u8], BE> {
92 if bit < self.split {
93 self.lo.get_bit(bit)
94 } else {
95 self.hi.get_bit(bit - self.split)
96 }
97 }
98}
99
100#[macro_export]
101macro_rules! define_bdd_2w_to_1w_trait {
102 ($(#[$meta:meta])* $vis:vis $trait_name:ident, $method_name:ident) => {
103 $(#[$meta])*
104 $vis trait $trait_name<T: UnsignedInteger, BE: Backend> {
105 fn $method_name<A, M, K, H, B>(
106 &mut self,
107 module: &M,
108 a: &FheUintPrepared<A, T, BE>,
109 b: &FheUintPrepared<B, T, BE>,
110 key: &H,
111 scratch: &mut Scratch<BE>,
112 ) where
113 M: ExecuteBDDCircuit2WTo1W<T, BE>,
114 A: DataRef,
115 B: DataRef,
116 K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos,
117 H: GLWEAutomorphismKeyHelper<K, BE>,
118 Scratch<BE>: ScratchTakeCore<BE>;
119 }
120 };
121}
122
123#[macro_export]
124macro_rules! impl_bdd_2w_to_1w_trait {
125 ($trait_name:ident, $method_name:ident, $ty:ty, $circuit_ty:ty, $output_circuits:path) => {
126 impl<D: DataMut, BE: Backend> $trait_name<$ty, BE> for FheUint<D, $ty> {
127 fn $method_name<A, M, K, H, B>(
128 &mut self,
129 module: &M,
130 a: &FheUintPrepared<A, $ty, BE>,
131 b: &FheUintPrepared<B, $ty, BE>,
132 key: &H,
133 scratch: &mut Scratch<BE>,
134 ) where
135 M: ExecuteBDDCircuit2WTo1W<$ty, BE>,
136 A: DataRef,
137 B: DataRef,
138 K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos,
139 H: GLWEAutomorphismKeyHelper<K, BE>,
140 Scratch<BE>: ScratchTakeCore<BE>,
141 {
142 module.execute_bdd_circuit_2w_to_1w(self, &$output_circuits, a, b, key, scratch)
143 }
144 }
145 };
146}
147
148define_bdd_2w_to_1w_trait!(pub Add, add);
149define_bdd_2w_to_1w_trait!(pub Sub, sub);
150define_bdd_2w_to_1w_trait!(pub Sll, sll);
151define_bdd_2w_to_1w_trait!(pub Sra, sra);
152define_bdd_2w_to_1w_trait!(pub Srl, srl);
153define_bdd_2w_to_1w_trait!(pub Slt, slt);
154define_bdd_2w_to_1w_trait!(pub Sltu, sltu);
155define_bdd_2w_to_1w_trait!(pub Or, or);
156define_bdd_2w_to_1w_trait!(pub And, and);
157define_bdd_2w_to_1w_trait!(pub Xor, xor);
158
159impl_bdd_2w_to_1w_trait!(
160 Add,
161 add,
162 u32,
163 circuits::u32::add_codegen::AnyBitCircuit,
164 circuits::u32::add_codegen::OUTPUT_CIRCUITS
165);
166
167impl_bdd_2w_to_1w_trait!(
168 Sub,
169 sub,
170 u32,
171 circuits::u32::sub_codegen::AnyBitCircuit,
172 circuits::u32::sub_codegen::OUTPUT_CIRCUITS
173);
174
175impl_bdd_2w_to_1w_trait!(
176 Sll,
177 sll,
178 u32,
179 circuits::u32::sll_codegen::AnyBitCircuit,
180 circuits::u32::sll_codegen::OUTPUT_CIRCUITS
181);
182
183impl_bdd_2w_to_1w_trait!(
184 Sra,
185 sra,
186 u32,
187 circuits::u32::sra_codegen::AnyBitCircuit,
188 circuits::u32::sra_codegen::OUTPUT_CIRCUITS
189);
190
191impl_bdd_2w_to_1w_trait!(
192 Srl,
193 srl,
194 u32,
195 circuits::u32::srl_codegen::AnyBitCircuit,
196 circuits::u32::srl_codegen::OUTPUT_CIRCUITS
197);
198
199impl_bdd_2w_to_1w_trait!(
200 Slt,
201 slt,
202 u32,
203 circuits::u32::slt_codegen::AnyBitCircuit,
204 circuits::u32::slt_codegen::OUTPUT_CIRCUITS
205);
206
207impl_bdd_2w_to_1w_trait!(
208 Sltu,
209 sltu,
210 u32,
211 circuits::u32::sltu_codegen::AnyBitCircuit,
212 circuits::u32::sltu_codegen::OUTPUT_CIRCUITS
213);
214
215impl_bdd_2w_to_1w_trait!(
216 And,
217 and,
218 u32,
219 circuits::u32::and_codegen::AnyBitCircuit,
220 circuits::u32::and_codegen::OUTPUT_CIRCUITS
221);
222
223impl_bdd_2w_to_1w_trait!(
224 Or,
225 or,
226 u32,
227 circuits::u32::or_codegen::AnyBitCircuit,
228 circuits::u32::or_codegen::OUTPUT_CIRCUITS
229);
230
231impl_bdd_2w_to_1w_trait!(
232 Xor,
233 xor,
234 u32,
235 circuits::u32::xor_codegen::AnyBitCircuit,
236 circuits::u32::xor_codegen::OUTPUT_CIRCUITS
237);