use crate::tfhe::bdd_arithmetic::FheUintBlocksPreparedDebug; use crate::tfhe::{ bdd_arithmetic::{FheUintBlocks, FheUintBlocksPrepared, UnsignedInteger}, blind_rotation::{BlindRotationAlgo, BlindRotationKey, BlindRotationKeyFactory}, circuit_bootstrapping::{ CircuitBootstrappingKey, CircuitBootstrappingKeyEncryptSk, CircuitBootstrappingKeyLayout, CircuitBootstrappingKeyPrepared, CircuitBootstrappingKeyPreparedFactory, CirtuitBootstrappingExecute, }, }; use poulpy_core::{ GLWEToLWESwitchingKeyEncryptSk, GetDistribution, LWEFromGLWE, ScratchTakeCore, layouts::{ GGSWInfos, GGSWPreparedFactory, GLWEInfos, GLWESecretToRef, GLWEToLWEKeyLayout, GLWEToLWESwitchingKey, GLWEToLWESwitchingKeyPreparedFactory, LWE, LWEInfos, LWESecretToRef, prepared::GLWEToLWESwitchingKeyPrepared, }, }; use poulpy_hal::{ layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}, source::Source, }; pub trait BDDKeyInfos { fn cbt_infos(&self) -> CircuitBootstrappingKeyLayout; fn ks_infos(&self) -> GLWEToLWEKeyLayout; } #[derive(Debug, Clone, Copy)] pub struct BDDKeyLayout { pub cbt: CircuitBootstrappingKeyLayout, pub ks: GLWEToLWEKeyLayout, } impl BDDKeyInfos for BDDKeyLayout { fn cbt_infos(&self) -> CircuitBootstrappingKeyLayout { self.cbt } fn ks_infos(&self) -> GLWEToLWEKeyLayout { self.ks } } pub struct BDDKey where D: Data, BRA: BlindRotationAlgo, { cbt: CircuitBootstrappingKey, ks: GLWEToLWESwitchingKey, } impl BDDKey, BRA> where BlindRotationKey, BRA>: BlindRotationKeyFactory, { pub fn alloc_from_infos(infos: &A) -> Self where A: BDDKeyInfos, { Self { cbt: CircuitBootstrappingKey::alloc_from_infos(&infos.cbt_infos()), ks: GLWEToLWESwitchingKey::alloc_from_infos(&infos.ks_infos()), } } } pub trait BDDKeyEncryptSk { fn bdd_key_encrypt_sk( &self, res: &mut BDDKey, sk_lwe: &S0, sk_glwe: &S1, source_xa: &mut Source, source_xe: &mut Source, scratch: &mut Scratch, ) where D: DataMut, S0: LWESecretToRef + GetDistribution + LWEInfos, S1: GLWESecretToRef + GetDistribution + GLWEInfos; } impl BDDKeyEncryptSk for Module where Self: CircuitBootstrappingKeyEncryptSk + GLWEToLWESwitchingKeyEncryptSk, Scratch: ScratchTakeCore, { fn bdd_key_encrypt_sk( &self, res: &mut BDDKey, sk_lwe: &S0, sk_glwe: &S1, source_xa: &mut Source, source_xe: &mut Source, scratch: &mut Scratch, ) where D: DataMut, S0: LWESecretToRef + GetDistribution + LWEInfos, S1: GLWESecretToRef + GetDistribution + GLWEInfos, { res.ks .encrypt_sk(self, sk_lwe, sk_glwe, source_xa, source_xe, scratch); res.cbt .encrypt_sk(self, sk_lwe, sk_glwe, source_xa, source_xe, scratch); } } impl BDDKey { pub fn encrypt_sk( &mut self, module: &M, sk_lwe: &S0, sk_glwe: &S1, source_xa: &mut Source, source_xe: &mut Source, scratch: &mut Scratch, ) where S0: LWESecretToRef + GetDistribution + LWEInfos, S1: GLWESecretToRef + GetDistribution + GLWEInfos, M: BDDKeyEncryptSk, Scratch: ScratchTakeCore, { module.bdd_key_encrypt_sk(self, sk_lwe, sk_glwe, source_xa, source_xe, scratch); } } pub struct BDDKeyPrepared where D: Data, BRA: BlindRotationAlgo, BE: Backend, { pub(crate) cbt: CircuitBootstrappingKeyPrepared, pub(crate) ks: GLWEToLWESwitchingKeyPrepared, } pub trait BDDKeyPreparedFactory where Self: Sized + CircuitBootstrappingKeyPreparedFactory + GLWEToLWESwitchingKeyPreparedFactory, { fn alloc_bdd_key_from_infos(&self, infos: &A) -> BDDKeyPrepared, BRA, BE> where A: BDDKeyInfos, { BDDKeyPrepared { cbt: CircuitBootstrappingKeyPrepared::alloc_from_infos(self, &infos.cbt_infos()), ks: GLWEToLWESwitchingKeyPrepared::alloc_from_infos(self, &infos.ks_infos()), } } fn prepare_bdd_key_tmp_bytes(&self, infos: &A) -> usize where A: BDDKeyInfos, { self.circuit_bootstrapping_key_prepare_tmp_bytes(&infos.cbt_infos()) .max(self.prepare_glwe_to_lwe_switching_key_tmp_bytes(&infos.ks_infos())) } fn prepare_bdd_key(&self, res: &mut BDDKeyPrepared, other: &BDDKey, scratch: &mut Scratch) where DM: DataMut, DR: DataRef, Scratch: ScratchTakeCore, { res.cbt.prepare(self, &other.cbt, scratch); res.ks.prepare(self, &other.ks, scratch); } } impl BDDKeyPreparedFactory for Module where Self: Sized + CircuitBootstrappingKeyPreparedFactory + GLWEToLWESwitchingKeyPreparedFactory { } impl BDDKeyPrepared, BRA, BE> { pub fn alloc_from_infos(module: &M, infos: &A) -> Self where M: BDDKeyPreparedFactory, A: BDDKeyInfos, { module.alloc_bdd_key_from_infos(infos) } } impl BDDKeyPrepared { pub fn prepare(&mut self, module: &M, other: &BDDKey, scratch: &mut Scratch) where DR: DataRef, M: BDDKeyPreparedFactory, Scratch: ScratchTakeCore, { module.prepare_bdd_key(self, other, scratch); } } pub trait FheUintBlocksPrepare { fn fhe_uint_blocks_prepare_tmp_bytes( &self, block_size: usize, extension_factor: usize, res_infos: &R, infos: &A, ) -> usize where R: GGSWInfos, A: BDDKeyInfos; fn fhe_uint_blocks_prepare( &self, res: &mut FheUintBlocksPrepared, bits: &FheUintBlocks, key: &BDDKeyPrepared, scratch: &mut Scratch, ) where DM: DataMut, DR0: DataRef, DR1: DataRef; } impl FheUintBlocksPrepare for Module where Self: LWEFromGLWE + CirtuitBootstrappingExecute + GGSWPreparedFactory, Scratch: ScratchTakeCore, { fn fhe_uint_blocks_prepare_tmp_bytes( &self, block_size: usize, extension_factor: usize, res_infos: &R, bdd_infos: &A, ) -> usize where R: GGSWInfos, A: BDDKeyInfos, { self.circuit_bootstrapping_execute_tmp_bytes( block_size, extension_factor, res_infos, &bdd_infos.cbt_infos(), ) } fn fhe_uint_blocks_prepare( &self, res: &mut FheUintBlocksPrepared, bits: &FheUintBlocks, key: &BDDKeyPrepared, scratch: &mut Scratch, ) where DM: DataMut, DR0: DataRef, DR1: DataRef, { assert_eq!(res.blocks.len(), bits.blocks.len()); let mut lwe: LWE> = LWE::alloc_from_infos(&bits.blocks[0]); //TODO: add TakeLWE let (mut tmp_ggsw, scratch_1) = scratch.take_ggsw(res); for (dst, src) in res.blocks.iter_mut().zip(bits.blocks.iter()) { lwe.from_glwe(self, src, &key.ks, scratch_1); key.cbt .execute_to_constant(self, &mut tmp_ggsw, &lwe, 1, 1, scratch_1); dst.prepare(self, &tmp_ggsw, scratch_1); } } } impl FheUintBlocksPrepared { pub fn prepare( &mut self, module: &M, other: &FheUintBlocks, key: &BDDKeyPrepared, scratch: &mut Scratch, ) where BRA: BlindRotationAlgo, O: DataRef, K: DataRef, M: FheUintBlocksPrepare, Scratch: ScratchTakeCore, { module.fhe_uint_blocks_prepare(self, other, key, scratch); } } pub trait FheUintBlockDebugPrepare { fn fhe_uint_block_debug_prepare( &self, res: &mut FheUintBlocksPreparedDebug, bits: &FheUintBlocks, key: &BDDKeyPrepared, scratch: &mut Scratch, ) where DM: DataMut, DR0: DataRef, DR1: DataRef; }