arnaucube
arnaucube/poulpyPublic Self-hosted repository
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<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
101pub struct JoinedBits<A, B> {
102    pub lo: A,
103    pub hi: B,
104    pub split: usize, // 32 in your example
105}
106
107impl<A, B, BE> GetGGSWBit<BE> for JoinedBits<A, B>
108where
109    BE: Backend,
110    A: GetGGSWBit<BE>,
111    B: GetGGSWBit<BE>,
112{
113    fn get_bit(&self, bit: usize) -> GGSWPrepared<&[u8], BE> {
114        if bit < self.split {
115            self.lo.get_bit(bit)
116        } else {
117            self.hi.get_bit(bit - self.split)
118        }
119    }
120}
121
122#[macro_export]
123macro_rules! define_bdd_2w_to_1w_trait {
124    ($(#[$meta:meta])* $vis:vis $trait_name:ident, $method_name:ident) => {
125        paste::paste! {
126            $(#[$meta])*
127            $vis trait $trait_name<T: UnsignedInteger, BE: Backend> {
128
129                /// Single-threaded version
130                fn $method_name<A, M, K, H, B>(
131                    &mut self,
132                    module: &M,
133                    a: &FheUintPrepared<A, T, BE>,
134                    b: &FheUintPrepared<B, T, BE>,
135                    key: &H,
136                    scratch: &mut Scratch<BE>,
137                ) where
138                    M: ExecuteBDDCircuit2WTo1W<BE>,
139                    A: DataRef,
140                    B: DataRef,
141                    K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos,
142                    H: GLWEAutomorphismKeyHelper<K, BE>,
143                    Scratch<BE>: ScratchTakeCore<BE>;
144
145                /// Multithreaded version – same vis, method_name + "_multi_thread"
146                fn [<$method_name _multi_thread>]<A, M, K, H, B>(
147                    &mut self,
148                    threads: usize,
149                    module: &M,
150                    a: &FheUintPrepared<A, T, BE>,
151                    b: &FheUintPrepared<B, T, BE>,
152                    key: &H,
153                    scratch: &mut Scratch<BE>,
154                ) where
155                    M: ExecuteBDDCircuit2WTo1W<BE>,
156                    A: DataRef,
157                    B: DataRef,
158                    K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos,
159                    H: GLWEAutomorphismKeyHelper<K, BE>,
160                    Scratch<BE>: ScratchTakeCore<BE>;
161            }
162        }
163    };
164}
165
166#[macro_export]
167macro_rules! impl_bdd_2w_to_1w_trait {
168    ($trait_name:ident, $method_name:ident, $ty:ty, $circuit_ty:ty, $output_circuits:path) => {
169        paste::paste! {
170            impl<D: DataMut, BE: Backend> $trait_name<$ty, BE> for FheUint<D, $ty> {
171
172                fn $method_name<A, M, K, H, B>(
173                    &mut self,
174                    module: &M,
175                    a: &FheUintPrepared<A, $ty, BE>,
176                    b: &FheUintPrepared<B, $ty, BE>,
177                    key: &H,
178                    scratch: &mut Scratch<BE>,
179                ) where
180                    M: ExecuteBDDCircuit2WTo1W<BE>,
181                    A: DataRef,
182                    B: DataRef,
183                    K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos,
184                    H: GLWEAutomorphismKeyHelper<K, BE>,
185                    Scratch<BE>: ScratchTakeCore<BE>,
186                {
187                    module.execute_bdd_circuit_2w_to_1w(self, &$output_circuits, a, b, key, scratch)
188                }
189
190                fn [<$method_name _multi_thread>]<A, M, K, H, B>(
191                    &mut self,
192                    threads: usize,
193                    module: &M,
194                    a: &FheUintPrepared<A, $ty, BE>,
195                    b: &FheUintPrepared<B, $ty, BE>,
196                    key: &H,
197                    scratch: &mut Scratch<BE>,
198                ) where
199                    M: ExecuteBDDCircuit2WTo1W<BE>,
200                    A: DataRef,
201                    B: DataRef,
202                    K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos,
203                    H: GLWEAutomorphismKeyHelper<K, BE>,
204                    Scratch<BE>: ScratchTakeCore<BE>,
205                {
206                    module.execute_bdd_circuit_2w_to_1w_multi_thread(threads, self, &$output_circuits, a, b, key, scratch)
207                }
208            }
209        }
210    };
211}
212
213define_bdd_2w_to_1w_trait!(pub Add, add);
214define_bdd_2w_to_1w_trait!(pub Sub, sub);
215define_bdd_2w_to_1w_trait!(pub Sll, sll);
216define_bdd_2w_to_1w_trait!(pub Sra, sra);
217define_bdd_2w_to_1w_trait!(pub Srl, srl);
218define_bdd_2w_to_1w_trait!(pub Slt, slt);
219define_bdd_2w_to_1w_trait!(pub Sltu, sltu);
220define_bdd_2w_to_1w_trait!(pub Or, or);
221define_bdd_2w_to_1w_trait!(pub And, and);
222define_bdd_2w_to_1w_trait!(pub Xor, xor);
223
224impl_bdd_2w_to_1w_trait!(
225    Add,
226    add,
227    u32,
228    circuits::u32::add_codegen::AnyBitCircuit,
229    circuits::u32::add_codegen::OUTPUT_CIRCUITS
230);
231
232impl_bdd_2w_to_1w_trait!(
233    Sub,
234    sub,
235    u32,
236    circuits::u32::sub_codegen::AnyBitCircuit,
237    circuits::u32::sub_codegen::OUTPUT_CIRCUITS
238);
239
240impl_bdd_2w_to_1w_trait!(
241    Sll,
242    sll,
243    u32,
244    circuits::u32::sll_codegen::AnyBitCircuit,
245    circuits::u32::sll_codegen::OUTPUT_CIRCUITS
246);
247
248impl_bdd_2w_to_1w_trait!(
249    Sra,
250    sra,
251    u32,
252    circuits::u32::sra_codegen::AnyBitCircuit,
253    circuits::u32::sra_codegen::OUTPUT_CIRCUITS
254);
255
256impl_bdd_2w_to_1w_trait!(
257    Srl,
258    srl,
259    u32,
260    circuits::u32::srl_codegen::AnyBitCircuit,
261    circuits::u32::srl_codegen::OUTPUT_CIRCUITS
262);
263
264impl_bdd_2w_to_1w_trait!(
265    Slt,
266    slt,
267    u32,
268    circuits::u32::slt_codegen::AnyBitCircuit,
269    circuits::u32::slt_codegen::OUTPUT_CIRCUITS
270);
271
272impl_bdd_2w_to_1w_trait!(
273    Sltu,
274    sltu,
275    u32,
276    circuits::u32::sltu_codegen::AnyBitCircuit,
277    circuits::u32::sltu_codegen::OUTPUT_CIRCUITS
278);
279
280impl_bdd_2w_to_1w_trait!(
281    And,
282    and,
283    u32,
284    circuits::u32::and_codegen::AnyBitCircuit,
285    circuits::u32::and_codegen::OUTPUT_CIRCUITS
286);
287
288impl_bdd_2w_to_1w_trait!(
289    Or,
290    or,
291    u32,
292    circuits::u32::or_codegen::AnyBitCircuit,
293    circuits::u32::or_codegen::OUTPUT_CIRCUITS
294);
295
296impl_bdd_2w_to_1w_trait!(
297    Xor,
298    xor,
299    u32,
300    circuits::u32::xor_codegen::AnyBitCircuit,
301    circuits::u32::xor_codegen::OUTPUT_CIRCUITS
302);