use poulpy_core::{ GLWECopy, GLWEPacking, ScratchTakeCore, layouts::{GGLWEInfos, GGLWEPreparedToRef, GLWEAutomorphismKeyHelper, GetGaloisElement}, }; use poulpy_hal::{ api::ModuleLogN, layouts::{Backend, DataMut, DataRef, Module, Scratch}, }; use crate::tfhe::bdd_arithmetic::{ExecuteBDDCircuit, FheUint, FheUintPrepared, GetBitCircuitInfo, UnsignedInteger, circuits}; impl ExecuteBDDCircuit1WTo1W for Module where Self: Sized + ExecuteBDDCircuit + GLWEPacking + GLWECopy {} pub trait ExecuteBDDCircuit1WTo1W where Self: Sized + ModuleLogN + ExecuteBDDCircuit + GLWEPacking + GLWECopy, { fn execute_bdd_circuit_1w_to_1w( &self, out: &mut FheUint, circuit: &C, a: &FheUintPrepared, key: &H, scratch: &mut Scratch, ) where T: UnsignedInteger, C: GetBitCircuitInfo, R: DataMut, A: DataRef, K: GGLWEPreparedToRef + GetGaloisElement + GGLWEInfos, H: GLWEAutomorphismKeyHelper, Scratch: ScratchTakeCore, { self.execute_bdd_circuit_1w_to_1w_multi_thread(1, out, circuit, a, key, scratch); } #[allow(clippy::too_many_arguments)] /// Operations Z x Z -> Z fn execute_bdd_circuit_1w_to_1w_multi_thread( &self, threads: usize, out: &mut FheUint, circuit: &C, a: &FheUintPrepared, key: &H, scratch: &mut Scratch, ) where T: UnsignedInteger, C: GetBitCircuitInfo, R: DataMut, A: DataRef, K: GGLWEPreparedToRef + GetGaloisElement + GGLWEInfos, H: GLWEAutomorphismKeyHelper, Scratch: ScratchTakeCore, { let (mut out_bits, scratch_1) = scratch.take_glwe_slice(T::BITS as usize, out); // Evaluates out[i] = circuit[i](a, b) self.execute_bdd_circuit_multi_thread(threads, &mut out_bits, a, circuit, scratch_1); // Repacks the bits out.pack(self, out_bits, key, scratch_1); } } #[macro_export] macro_rules! define_bdd_1w_to_1w_trait { ($(#[$meta:meta])* $vis:vis $trait_name:ident, $method_name:ident) => { paste::paste! { $(#[$meta])* $vis trait $trait_name { /// Single-threaded version fn $method_name( &mut self, module: &M, a: &FheUintPrepared, key: &H, scratch: &mut Scratch, ) where M: ExecuteBDDCircuit1WTo1W, A: DataRef, K: GGLWEPreparedToRef + GetGaloisElement + GGLWEInfos, H: GLWEAutomorphismKeyHelper, Scratch: ScratchTakeCore; /// Multithreaded version – same vis, method_name + "_multi_thread" fn [<$method_name _multi_thread>]( &mut self, threads: usize, module: &M, a: &FheUintPrepared, key: &H, scratch: &mut Scratch, ) where M: ExecuteBDDCircuit1WTo1W, A: DataRef, K: GGLWEPreparedToRef + GetGaloisElement + GGLWEInfos, H: GLWEAutomorphismKeyHelper, Scratch: ScratchTakeCore; } } }; } #[macro_export] macro_rules! impl_bdd_1w_to_1w_trait { ($trait_name:ident, $method_name:ident, $ty:ty, $circuit_ty:ty, $output_circuits:path) => { paste::paste! { impl $trait_name<$ty, BE> for FheUint { fn $method_name( &mut self, module: &M, a: &FheUintPrepared, key: &H, scratch: &mut Scratch, ) where M: ExecuteBDDCircuit1WTo1W, A: DataRef, K: GGLWEPreparedToRef + GetGaloisElement + GGLWEInfos, H: GLWEAutomorphismKeyHelper, Scratch: ScratchTakeCore, { module.execute_bdd_circuit_1w_to_1w(self, &$output_circuits, a, key, scratch) } fn [<$method_name _multi_thread>]( &mut self, threads: usize, module: &M, a: &FheUintPrepared, key: &H, scratch: &mut Scratch, ) where M: ExecuteBDDCircuit1WTo1W, A: DataRef, K: GGLWEPreparedToRef + GetGaloisElement + GGLWEInfos, H: GLWEAutomorphismKeyHelper, Scratch: ScratchTakeCore, { module.execute_bdd_circuit_1w_to_1w_multi_thread(threads, self, &$output_circuits, a, key, scratch) } } } }; } define_bdd_1w_to_1w_trait!(pub Identity, identity); impl_bdd_1w_to_1w_trait!( Identity, identity, u32, circuits::u32::identity_codgen::AnyBitCircuit, circuits::u32::identity_codgen::OUTPUT_CIRCUITS );