arnaucube
arnaucube/poulpyPublic Self-hosted repository
clippy
Pro7ech jeanphilippe.bossuat@gmail.com
Wed, 22 Oct 2025 16:43:46 +0200
commit

cedf7b9c593f64c5598f863d41bf71c504213a8c

parent

5755aea58c7d6df8d2f2d1831a9791d64a505a04

M poulpy-core/src/automorphism/gglwe_atk.rs → poulpy-core/src/automorphism/gglwe_atk.rs

@@ -116,7 +116,7 @@ }

} } - res.set_p((p * key.p()) % (self.cyclotomic_order() as i64)); + res.set_p((p * key.p()) % self.cyclotomic_order()); } fn glwe_automorphism_key_automorphism_inplace<R, K>(&self, res: &mut R, key: &K, scratch: &mut Scratch<BE>)

@@ -160,6 +160,6 @@ }

} } - res.set_p((res.p() * key.p()) % (self.cyclotomic_order() as i64)); + res.set_p((res.p() * key.p()) % self.cyclotomic_order()); } }
M poulpy-core/src/encryption/ggsw.rs → poulpy-core/src/encryption/ggsw.rs

@@ -107,7 +107,7 @@ let k: usize = res.k().into();

let base2k: usize = res.base2k().into(); let rank: usize = res.rank().into(); let dsize: usize = res.dsize().into(); - let cols: usize = (rank + 1).into(); + let cols: usize = rank + 1; let (mut tmp_pt, scratch_1) = scratch.take_glwe_plaintext(res);
M poulpy-core/src/encryption/glwe.rs → poulpy-core/src/encryption/glwe.rs

@@ -427,6 +427,7 @@ }

} pub(crate) trait GLWEEncryptSkInternal<BE: Backend> { + #[allow(clippy::too_many_arguments)] fn glwe_encrypt_sk_internal<R, P, S>( &self, base2k: usize,
M poulpy-core/src/layouts/compressed/glwe.rs → poulpy-core/src/layouts/compressed/glwe.rs

@@ -192,7 +192,7 @@

impl<D: DataRef> GLWECompressedToRef for GLWECompressed<D> { fn to_ref(&self) -> GLWECompressed<&[u8]> { GLWECompressed { - seed: self.seed.clone(), + seed: self.seed, base2k: self.base2k, k: self.k, rank: self.rank,

@@ -208,7 +208,7 @@

impl<D: DataMut> GLWECompressedToMut for GLWECompressed<D> { fn to_mut(&mut self) -> GLWECompressed<&mut [u8]> { GLWECompressed { - seed: self.seed.clone(), + seed: self.seed, base2k: self.base2k, k: self.k, rank: self.rank,
M poulpy-core/src/layouts/compressed/glwe_switching_key.rs → poulpy-core/src/layouts/compressed/glwe_switching_key.rs

@@ -146,8 +146,8 @@ }

impl<D: DataMut> ReaderFrom for GLWESwitchingKeyCompressed<D> { fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - self.input_degree = Degree(reader.read_u32::<LittleEndian>()? as u32); - self.output_degree = Degree(reader.read_u32::<LittleEndian>()? as u32); + self.input_degree = Degree(reader.read_u32::<LittleEndian>()?); + self.output_degree = Degree(reader.read_u32::<LittleEndian>()?); self.key.read_from(reader) } }
M poulpy-core/src/layouts/glwe_switching_key.rs → poulpy-core/src/layouts/glwe_switching_key.rs

@@ -240,8 +240,8 @@ }

impl<D: DataMut> ReaderFrom for GLWESwitchingKey<D> { fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - self.input_degree = Degree(reader.read_u32::<LittleEndian>()? as u32); - self.output_degree = Degree(reader.read_u32::<LittleEndian>()? as u32); + self.input_degree = Degree(reader.read_u32::<LittleEndian>()?); + self.output_degree = Degree(reader.read_u32::<LittleEndian>()?); self.key.read_from(reader) } }
M poulpy-core/src/layouts/mod.rs → poulpy-core/src/layouts/mod.rs

@@ -43,7 +43,7 @@ }

impl<B: Backend> GetDegree for Module<B> { fn ring_degree(&self) -> Degree { - Self::n(&self).into() + Self::n(self).into() } }
M poulpy-core/src/layouts/prepared/glwe_automorphism_key.rs → poulpy-core/src/layouts/prepared/glwe_automorphism_key.rs

@@ -69,7 +69,7 @@ pub trait GLWEAutomorphismKeyPreparedFactory<B: Backend>

where Self: GGLWEPreparedFactory<B>, { - fn alloc_automorphism_key_prepared( + fn alloc_glwe_automorphism_key_prepared( &self, base2k: Base2K, k: TorusPrecision,

@@ -83,7 +83,7 @@ p: 0,

} } - fn alloc_automorphism_key_prepared_from_infos<A>(&self, infos: &A) -> GLWEAutomorphismKeyPrepared<Vec<u8>, B> + fn alloc_glwe_automorphism_key_prepared_from_infos<A>(&self, infos: &A) -> GLWEAutomorphismKeyPrepared<Vec<u8>, B> where A: GGLWEInfos, {

@@ -92,7 +92,7 @@ infos.rank_in(),

infos.rank_out(), "rank_in != rank_out is not supported for AutomorphismKeyPrepared" ); - self.alloc_automorphism_key_prepared( + self.alloc_glwe_automorphism_key_prepared( infos.base2k(), infos.k(), infos.rank(),

@@ -101,7 +101,7 @@ infos.dsize(),

) } - fn bytes_of_automorphism_key_prepared( + fn bytes_of_glwe_automorphism_key_prepared( &self, base2k: Base2K, k: TorusPrecision,

@@ -112,7 +112,7 @@ ) -> usize {

self.bytes_of_gglwe_prepared(base2k, k, rank, rank, dnum, dsize) } - fn bytes_of_automorphism_key_prepared_from_infos<A>(&self, infos: &A) -> usize + fn bytes_of_glwe_automorphism_key_prepared_from_infos<A>(&self, infos: &A) -> usize where A: GGLWEInfos, {

@@ -121,7 +121,7 @@ infos.rank_in(),

infos.rank_out(), "rank_in != rank_out is not supported for AutomorphismKeyPrepared" ); - self.bytes_of_automorphism_key_prepared( + self.bytes_of_glwe_automorphism_key_prepared( infos.base2k(), infos.k(), infos.rank(),

@@ -130,14 +130,14 @@ infos.dsize(),

) } - fn prepare_automorphism_key_tmp_bytes<A>(&self, infos: &A) -> usize + fn prepare_glwe_automorphism_key_tmp_bytes<A>(&self, infos: &A) -> usize where A: GGLWEInfos, { self.prepare_gglwe_tmp_bytes(infos) } - fn prepare_automorphism_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>) + fn prepare_glwe_automorphism_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>) where R: GGLWEPreparedToMut<B> + SetGaloisElement, O: GGLWEToRef + GetGaloisElement,

@@ -155,14 +155,14 @@ where

A: GGLWEInfos, M: GLWEAutomorphismKeyPreparedFactory<B>, { - module.alloc_automorphism_key_prepared_from_infos(infos) + module.alloc_glwe_automorphism_key_prepared_from_infos(infos) } pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self where M: GLWEAutomorphismKeyPreparedFactory<B>, { - module.alloc_automorphism_key_prepared(base2k, k, rank, dnum, dsize) + module.alloc_glwe_automorphism_key_prepared(base2k, k, rank, dnum, dsize) } pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize

@@ -170,14 +170,14 @@ where

A: GGLWEInfos, M: GLWEAutomorphismKeyPreparedFactory<B>, { - module.bytes_of_automorphism_key_prepared_from_infos(infos) + module.bytes_of_glwe_automorphism_key_prepared_from_infos(infos) } pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize where M: GLWEAutomorphismKeyPreparedFactory<B>, { - module.bytes_of_automorphism_key_prepared(base2k, k, rank, dnum, dsize) + module.bytes_of_glwe_automorphism_key_prepared(base2k, k, rank, dnum, dsize) } }

@@ -186,7 +186,7 @@ pub fn prepare_tmp_bytes<M>(&self, module: &M) -> usize

where M: GLWEAutomorphismKeyPreparedFactory<B>, { - module.prepare_automorphism_key_tmp_bytes(self) + module.prepare_glwe_automorphism_key_tmp_bytes(self) } }

@@ -196,7 +196,7 @@ where

O: GGLWEToRef + GetGaloisElement, M: GLWEAutomorphismKeyPreparedFactory<B>, { - module.prepare_automorphism_key(self, other, scratch); + module.prepare_glwe_automorphism_key(self, other, scratch); } }
M poulpy-core/src/layouts/prepared/glwe_secret.rs → poulpy-core/src/layouts/prepared/glwe_secret.rs

@@ -166,7 +166,10 @@ }

} } -pub trait GLWESecretPreparedToMut<B: Backend> { +pub trait GLWESecretPreparedToMut<B: Backend> +where + Self: GLWESecretPreparedToRef<B>, +{ fn to_mut(&mut self) -> GLWESecretPrepared<&mut [u8], B>; }
M poulpy-core/src/layouts/prepared/glwe_to_lwe_switching_key.rs → poulpy-core/src/layouts/prepared/glwe_to_lwe_switching_key.rs

@@ -102,11 +102,11 @@ );

self.bytes_of_glwe_to_lwe_switching_key_prepared(infos.base2k(), infos.k(), infos.rank_in(), infos.dnum()) } - fn prepare_glwe_to_lwe_switching_key_tmp_bytes<A>(&self, infos: &A) + fn prepare_glwe_to_lwe_switching_key_tmp_bytes<A>(&self, infos: &A) -> usize where A: GGLWEInfos, { - self.prepare_glwe_switching_key_tmp_bytes(infos); + self.prepare_glwe_switching_key_tmp_bytes(infos) } fn prepare_glwe_to_lwe_switching_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>)
M poulpy-core/src/tests/test_suite/encryption/gglwe_atk.rs → poulpy-core/src/tests/test_suite/encryption/gglwe_atk.rs

@@ -81,7 +81,7 @@ &sk.data.as_vec_znx(),

i, ); }); - let mut sk_out_prepared: GLWESecretPrepared<Vec<u8>, BE> = GLWESecretPrepared::alloc(module, sk_out.rank().into()); + let mut sk_out_prepared: GLWESecretPrepared<Vec<u8>, BE> = GLWESecretPrepared::alloc(module, sk_out.rank()); sk_out_prepared.prepare(module, &sk_out); atk.key

@@ -150,7 +150,7 @@ &sk.data.as_vec_znx(),

i, ); }); - let mut sk_out_prepared: GLWESecretPrepared<Vec<u8>, BE> = GLWESecretPrepared::alloc(module, sk_out.rank().into()); + let mut sk_out_prepared: GLWESecretPrepared<Vec<u8>, BE> = GLWESecretPrepared::alloc(module, sk_out.rank()); sk_out_prepared.prepare(module, &sk_out); let mut atk: GLWEAutomorphismKey<Vec<u8>> = GLWEAutomorphismKey::alloc_from_infos(&atk_infos);
M poulpy-schemes/src/tfhe/bdd_arithmetic/bdd_2w_to_1w.rs → poulpy-schemes/src/tfhe/bdd_arithmetic/bdd_2w_to_1w.rs

@@ -3,72 +3,44 @@ use poulpy_core::layouts::prepared::GGSWPreparedToRef;

use poulpy_hal::layouts::{Backend, DataMut, DataRef, Module, Scratch}; use crate::tfhe::bdd_arithmetic::{ - BitCircuitInfo, Circuit, CircuitExecute, FheUintBlocks, FheUintBlocksPrep, UnsignedInteger, circuits, + ExecuteBDDCircuit, FheUintBlocks, FheUintBlocksPrepared, GetBitCircuitInfo, UnsignedInteger, circuits, }; -/// Operations Z x Z -> Z -pub(crate) struct Circuits2WTo1W<C: BitCircuitInfo + 'static, const WORD_SIZE: usize>(pub &'static Circuit<C, WORD_SIZE>); - -pub trait EvalBDD2WTo1W<BE: Backend, T: UnsignedInteger> { - fn eval_bdd_2w_to_1w<R, A, B>( - &self, - module: &Module<BE>, - out: &mut FheUintBlocks<R, T>, - a: &FheUintBlocksPrep<A, BE, T>, - b: &FheUintBlocksPrep<B, BE, T>, - scratch: &mut Scratch<BE>, - ) where - R: DataMut, - A: DataRef, - B: DataRef; -} +impl<T: UnsignedInteger, BE: Backend> ExecuteBDDCircuit2WTo1W<T, BE> for Module<BE> where Self: Sized + ExecuteBDDCircuit<T, BE> {} -impl<C: BitCircuitInfo + 'static, const WORD_SIZE: usize, BE: Backend, T: UnsignedInteger> EvalBDD2WTo1W<BE, T> - for Circuits2WTo1W<C, WORD_SIZE> +pub trait ExecuteBDDCircuit2WTo1W<T: UnsignedInteger, BE: Backend> where - Circuit<C, WORD_SIZE>: CircuitExecute<BE, T>, + Self: Sized + ExecuteBDDCircuit<T, BE>, { - fn eval_bdd_2w_to_1w<R, A, B>( + /// Operations Z x Z -> Z + fn execute_bdd_circuit_2w_to_1w<R, C, A, B>( &self, - module: &Module<BE>, out: &mut FheUintBlocks<R, T>, - a: &FheUintBlocksPrep<A, BE, T>, - b: &FheUintBlocksPrep<B, BE, T>, + circuit: &C, + a: &FheUintBlocksPrepared<A, T, BE>, + b: &FheUintBlocksPrepared<B, T, BE>, scratch: &mut Scratch<BE>, ) where + C: GetBitCircuitInfo<T>, R: DataMut, A: DataRef, B: DataRef, - { - eval_bdd_2w_to_1w(module, self.0, out, a, b, scratch); - } -} - -pub fn eval_bdd_2w_to_1w<R: DataMut, A: DataRef, B: DataRef, T: UnsignedInteger, C: CircuitExecute<BE, T>, BE: Backend>( - module: &Module<BE>, - circuit: &C, - out: &mut FheUintBlocks<R, T>, - a: &FheUintBlocksPrep<A, BE, T>, - b: &FheUintBlocksPrep<B, BE, T>, - scratch: &mut Scratch<BE>, -) { - #[cfg(debug_assertions)] { assert_eq!(out.blocks.len(), T::WORD_SIZE); assert_eq!(b.blocks.len(), T::WORD_SIZE); assert_eq!(b.blocks.len(), T::WORD_SIZE); - } - // Collects inputs into a single array - let inputs: Vec<&dyn GGSWPreparedToRef<BE>> = a - .blocks - .iter() - .map(|x| x as &dyn GGSWPreparedToRef<BE>) - .chain(b.blocks.iter().map(|x| x as &dyn GGSWPreparedToRef<BE>)) - .collect_vec(); + // Collects inputs into a single array + let inputs: Vec<&dyn GGSWPreparedToRef<BE>> = a + .blocks + .iter() + .map(|x| x as &dyn GGSWPreparedToRef<BE>) + .chain(b.blocks.iter().map(|x| x as &dyn GGSWPreparedToRef<BE>)) + .collect_vec(); - // Evaluates out[i] = circuit[i](a, b) - circuit.execute(module, &mut out.blocks, &inputs, scratch); + // Evaluates out[i] = circuit[i](a, b) + self.execute_bdd_circuit(&mut out.blocks, &inputs, circuit, scratch); + } } #[macro_export]

@@ -76,13 +48,14 @@ macro_rules! define_bdd_2w_to_1w_trait {

($(#[$meta:meta])* $vis:vis $trait_name:ident, $method_name:ident) => { $(#[$meta])* $vis trait $trait_name<T: UnsignedInteger, BE: Backend> { - fn $method_name<A, B>( + fn $method_name<A, M, B>( &mut self, - module: &Module<BE>, - a: &FheUintBlocksPrep<A, BE, T>, - b: &FheUintBlocksPrep<B, BE, T>, + module: &M, + a: &FheUintBlocksPrepared<A, T, BE>, + b: &FheUintBlocksPrepared<B, T, BE>, scratch: &mut Scratch<BE>, ) where + M: ExecuteBDDCircuit2WTo1W<T, BE>, A: DataRef, B: DataRef; }

@@ -92,23 +65,19 @@

#[macro_export] macro_rules! impl_bdd_2w_to_1w_trait { ($trait_name:ident, $method_name:ident, $ty:ty, $n:literal, $circuit_ty:ty, $output_circuits:path) => { - impl<D: DataMut, BE: Backend> $trait_name<$ty, BE> for FheUintBlocks<D, $ty> - where - Circuits2WTo1W<$circuit_ty, $n>: EvalBDD2WTo1W<BE, $ty>, - { - fn $method_name<A, B>( + impl<D: DataMut, BE: Backend> $trait_name<$ty, BE> for FheUintBlocks<D, $ty> { + fn $method_name<A, M, B>( &mut self, - module: &Module<BE>, - a: &FheUintBlocksPrep<A, BE, $ty>, - b: &FheUintBlocksPrep<B, BE, $ty>, + module: &M, + a: &FheUintBlocksPrepared<A, $ty, BE>, + b: &FheUintBlocksPrepared<B, $ty, BE>, scratch: &mut Scratch<BE>, ) where + M: ExecuteBDDCircuit2WTo1W<$ty, BE>, A: DataRef, B: DataRef, { - const OP: Circuits2WTo1W<$circuit_ty, $n> = Circuits2WTo1W::<$circuit_ty, $n>(&$output_circuits); - - OP.eval_bdd_2w_to_1w(module, self, a, b, scratch); + module.execute_bdd_circuit_2w_to_1w(self, &$output_circuits, a, b, scratch) } } };
M poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/block.rs → poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/block.rs

@@ -1,26 +1,17 @@

use std::marker::PhantomData; -use poulpy_core::layouts::{Base2K, GLWE, GLWEInfos, GLWEPlaintextLayout, LWEInfos, Rank, TorusPrecision}; +use poulpy_core::{ + GLWEDecrypt, GLWENoise, + layouts::{Base2K, GLWE, GLWEInfos, GLWEPlaintextLayout, GLWESecretPreparedToRef, LWEInfos, Rank, TorusPrecision}, +}; #[cfg(test)] +use poulpy_core::GLWEEncryptSk; use poulpy_core::ScratchTakeCore; -use poulpy_core::{layouts::prepared::GLWESecretPrepared}; -use poulpy_hal::api::VecZnxBigBytesOf; +use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}; #[cfg(test)] -use poulpy_hal::api::{ - VecZnxAddInplace, VecZnxAddNormal, VecZnxFillUniform, VecZnxNormalize, VecZnxSub, -}; #[cfg(test)] use poulpy_hal::source::Source; -use poulpy_hal::{ - api::{ - VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxDftApply, - VecZnxDftBytesOf, VecZnxIdftApplyConsume, VecZnxNormalizeTmpBytes, - }, - layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}, -}; - -use poulpy_hal::api::{SvpApplyDftToDftInplace, VecZnxNormalizeInplace, VecZnxSubInplace}; use crate::tfhe::bdd_arithmetic::{FromBits, ToBits, UnsignedInteger};

@@ -79,25 +70,13 @@ pub(crate) fn encrypt_sk<S, BE: Backend>(

&mut self, module: &Module<BE>, value: T, - sk: &GLWESecretPrepared<S, BE>, + sk: &S, source_xa: &mut Source, source_xe: &mut Source, scratch: &mut Scratch<BE>, ) where - S: DataRef, - Module<BE>: VecZnxDftBytesOf - + VecZnxBigNormalize<BE> - + VecZnxDftApply<BE> - + SvpApplyDftToDftInplace<BE> - + VecZnxIdftApplyConsume<BE> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<BE> - + VecZnxAddNormal - + VecZnxNormalize<BE> - + VecZnxSub, + S: GLWESecretPreparedToRef<BE> + GLWEInfos, + Module<BE>: GLWEEncryptSk<BE>, Scratch<BE>: ScratchTakeCore<BE>, { use poulpy_core::layouts::GLWEPlaintextLayout;

@@ -115,29 +94,20 @@ base2k: self.base2k(),

k: 1_usize.into(), }; - let (mut pt, scratch_1) = scratch.take_glwe_pt(&pt_infos); + let (mut pt, scratch_1) = scratch.take_glwe_plaintext(&pt_infos); for i in 0..T::WORD_SIZE { pt.encode_coeff_i64(value.bit(i) as i64, TorusPrecision(2), 0); - self.blocks[i].encrypt_sk(&module, &pt, sk, source_xa, source_xe, scratch_1); + self.blocks[i].encrypt_sk(module, &pt, sk, source_xa, source_xe, scratch_1); } } } impl<D: DataRef, T: UnsignedInteger + FromBits + ToBits> FheUintBlocks<D, T> { - pub fn decrypt<S: DataRef, BE: Backend>( - &self, - module: &Module<BE>, - sk: &GLWESecretPrepared<S, BE>, - scratch: &mut Scratch<BE>, - ) -> T + pub fn decrypt<S, BE: Backend>(&self, module: &Module<BE>, sk: &S, scratch: &mut Scratch<BE>) -> T where - Module<BE>: VecZnxDftApply<BE> - + SvpApplyDftToDftInplace<BE> - + VecZnxIdftApplyConsume<BE> - + VecZnxBigAddInplace<BE> - + VecZnxBigAddSmallInplace<BE> - + VecZnxBigNormalize<BE>, + Module<BE>: GLWEDecrypt<BE>, + S: GLWESecretPreparedToRef<BE> + GLWEInfos, Scratch<BE>: ScratchTakeCore<BE>, { #[cfg(debug_assertions)]

@@ -153,7 +123,7 @@ base2k: self.base2k(),

k: self.k(), }; - let (mut pt, scratch_1) = scratch.take_glwe_pt(&pt_infos); + let (mut pt, scratch_1) = scratch.take_glwe_plaintext(&pt_infos); let mut bits: Vec<u8> = vec![0u8; T::WORD_SIZE];

@@ -169,25 +139,10 @@

T::from_bits(&bits) } - pub fn noise<S: DataRef, BE: Backend>( - &self, - module: &Module<BE>, - sk: &GLWESecretPrepared<S, BE>, - want: T, - scratch: &mut Scratch<BE>, - ) -> Vec<f64> + pub fn noise<S, BE: Backend>(&self, module: &Module<BE>, sk: &S, want: T, scratch: &mut Scratch<BE>) -> Vec<f64> where - Module<BE>: VecZnxDftBytesOf - + VecZnxBigBytesOf - + VecZnxDftApply<BE> - + SvpApplyDftToDftInplace<BE> - + VecZnxIdftApplyConsume<BE> - + VecZnxBigAddInplace<BE> - + VecZnxBigAddSmallInplace<BE> - + VecZnxBigNormalize<BE> - + VecZnxNormalizeTmpBytes - + VecZnxSubInplace - + VecZnxNormalizeInplace<BE>, + Module<BE>: GLWENoise<BE>, + S: GLWESecretPreparedToRef<BE> + GLWEInfos, Scratch<BE>: ScratchTakeCore<BE>, { #[cfg(debug_assertions)]

@@ -203,7 +158,7 @@ base2k: self.base2k(),

k: 1_usize.into(), }; - let (mut pt_want, scratch_1) = scratch.take_glwe_pt(&pt_infos); + let (mut pt_want, scratch_1) = scratch.take_glwe_plaintext(&pt_infos); let mut noise: Vec<f64> = vec![0f64; T::WORD_SIZE];
A poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/block_debug.rs

@@ -0,0 +1,147 @@

+use std::marker::PhantomData; + +use crate::tfhe::bdd_arithmetic::{BDDKeyPrepared, FheUintBlockDebugPrepare, ToBits}; +use crate::tfhe::{ + bdd_arithmetic::{FheUintBlocks, UnsignedInteger}, + blind_rotation::BlindRotationAlgo, + circuit_bootstrapping::CirtuitBootstrappingExecute, +}; +use poulpy_core::GGSWNoise; +#[cfg(test)] +use poulpy_core::layouts::{Base2K, Dnum, Dsize, Rank, TorusPrecision}; +use poulpy_core::layouts::{GGSW, GLWESecretPreparedToRef}; +use poulpy_core::{ + LWEFromGLWE, ScratchTakeCore, + layouts::{GGSWInfos, GGSWPreparedFactory, GLWEInfos, LWE, LWEInfos}, +}; +#[cfg(test)] +use poulpy_hal::api::ModuleN; +use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}; + +pub(crate) struct FheUintBlocksPreparedDebug<D: Data, T: UnsignedInteger> { + pub(crate) blocks: Vec<GGSW<D>>, + pub(crate) _base: u8, + pub(crate) _phantom: PhantomData<T>, +} + +#[cfg(test)] +impl<T: UnsignedInteger> FheUintBlocksPreparedDebug<Vec<u8>, T> { + #[allow(dead_code)] + pub(crate) fn alloc<A, M>(module: &M, infos: &A) -> Self + where + M: ModuleN, + A: GGSWInfos, + { + Self::alloc_with( + module, + infos.base2k(), + infos.k(), + infos.dnum(), + infos.dsize(), + infos.rank(), + ) + } + + #[allow(dead_code)] + pub(crate) fn alloc_with<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self + where + M: ModuleN, + { + Self { + blocks: (0..T::WORD_SIZE) + .map(|_| GGSW::alloc(module.n().into(), base2k, k, rank, dnum, dsize)) + .collect(), + _base: 1, + _phantom: PhantomData, + } + } +} + +impl<D: DataRef, T: UnsignedInteger> LWEInfos for FheUintBlocksPreparedDebug<D, T> { + fn base2k(&self) -> poulpy_core::layouts::Base2K { + self.blocks[0].base2k() + } + + fn k(&self) -> poulpy_core::layouts::TorusPrecision { + self.blocks[0].k() + } + + fn n(&self) -> poulpy_core::layouts::Degree { + self.blocks[0].n() + } +} + +impl<D: DataRef, T: UnsignedInteger> GLWEInfos for FheUintBlocksPreparedDebug<D, T> { + fn rank(&self) -> poulpy_core::layouts::Rank { + self.blocks[0].rank() + } +} + +impl<D: DataRef, T: UnsignedInteger> GGSWInfos for FheUintBlocksPreparedDebug<D, T> { + fn dsize(&self) -> poulpy_core::layouts::Dsize { + self.blocks[0].dsize() + } + + fn dnum(&self) -> poulpy_core::layouts::Dnum { + self.blocks[0].dnum() + } +} + +impl<D: DataRef, T: UnsignedInteger + ToBits> FheUintBlocksPreparedDebug<D, T> { + pub(crate) fn noise<S, M, BE: Backend>(&self, module: &M, sk: &S, want: T) + where + S: GLWESecretPreparedToRef<BE>, + M: GGSWNoise<BE>, + { + for (i, ggsw) in self.blocks.iter().enumerate() { + use poulpy_hal::layouts::{ScalarZnx, ZnxViewMut}; + let mut pt_want = ScalarZnx::alloc(self.n().into(), 1); + pt_want.at_mut(0, 0)[0] = want.bit(i) as i64; + ggsw.print_noise(module, sk, &pt_want); + } + } +} + +impl<BRA: BlindRotationAlgo, BE: Backend, T: UnsignedInteger> FheUintBlockDebugPrepare<BRA, T, BE> for Module<BE> +where + Self: LWEFromGLWE<BE> + CirtuitBootstrappingExecute<BRA, BE> + GGSWPreparedFactory<BE>, + Scratch<BE>: ScratchTakeCore<BE>, +{ + fn fhe_uint_block_debug_prepare<DM, DR0, DR1>( + &self, + res: &mut FheUintBlocksPreparedDebug<DM, T>, + bits: &FheUintBlocks<DR0, T>, + key: &BDDKeyPrepared<DR1, BRA, BE>, + scratch: &mut Scratch<BE>, + ) where + DM: DataMut, + DR0: DataRef, + DR1: DataRef, + { + assert_eq!(res.blocks.len(), bits.blocks.len()); + + let mut lwe: LWE<Vec<u8>> = LWE::alloc_from_infos(&bits.blocks[0]); //TODO: add TakeLWE + for (dst, src) in res.blocks.iter_mut().zip(bits.blocks.iter()) { + lwe.from_glwe(self, src, &key.ks, scratch); + key.cbt.execute_to_constant(self, dst, &lwe, 1, 1, scratch); + } + } +} + +impl<D: DataMut, T: UnsignedInteger> FheUintBlocksPreparedDebug<D, T> { + pub fn prepare<BRA, M, O, K, BE: Backend>( + &mut self, + module: &M, + other: &FheUintBlocks<O, T>, + key: &BDDKeyPrepared<K, BRA, BE>, + scratch: &mut Scratch<BE>, + ) where + BRA: BlindRotationAlgo, + O: DataRef, + K: DataRef, + M: FheUintBlockDebugPrepare<BRA, T, BE>, + Scratch<BE>: ScratchTakeCore<BE>, + { + module.fhe_uint_block_debug_prepare(self, other, key, scratch); + } +}
M poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/block_prepared.rs → poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/block_prepared.rs

@@ -1,89 +1,60 @@

use std::marker::PhantomData; -use poulpy_core::layouts::{Base2K, Dnum, Dsize, GGSWInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision, prepared::GGSWPrepared}; +use poulpy_core::layouts::{ + Base2K, Dnum, Dsize, GGSWInfos, GGSWPreparedFactory, GLWEInfos, LWEInfos, Rank, TorusPrecision, prepared::GGSWPrepared, +}; #[cfg(test)] -use poulpy_core::{ - layouts::{prepared::GLWESecretPrepared, GGSW}, ScratchTakeCore, -}; -use poulpy_hal::{ - api::VmpPMatAlloc, - layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}, -}; +use poulpy_core::{GGSWEncryptSk, ScratchTakeCore, layouts::GLWESecretPreparedToRef}; +use poulpy_hal::layouts::{Backend, Data, DataRef, Module}; #[cfg(test)] use poulpy_hal::{ - api::{ - SvpApplyDftToDftInplace, VecZnxAddInplace, VecZnxAddNormal, - VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigBytesOf, - VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAlloc, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, - VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, - VecZnxSubInplace, VmpPrepare, - }, + api::ModuleN, + layouts::{DataMut, Scratch}, source::Source, }; -use crate::tfhe::bdd_arithmetic::{FheUintBlocks, FheUintPrepare, ToBits, UnsignedInteger}; +#[cfg(test)] +use crate::tfhe::bdd_arithmetic::ToBits; +use crate::tfhe::bdd_arithmetic::UnsignedInteger; -#[cfg(test)] -pub(crate) struct FheUintBlocksPrepDebug<D: Data, T: UnsignedInteger> { - pub(crate) blocks: Vec<GGSW<D>>, +/// A prepared FHE ciphertext encrypting the bits of an [UnsignedInteger]. +pub struct FheUintBlocksPrepared<D: Data, T: UnsignedInteger, B: Backend> { + pub(crate) blocks: Vec<GGSWPrepared<D, B>>, pub(crate) _base: u8, pub(crate) _phantom: PhantomData<T>, } -#[cfg(test)] -impl<T: UnsignedInteger> FheUintBlocksPrepDebug<Vec<u8>, T> { - #[allow(dead_code)] - pub(crate) fn alloc<A, BE: Backend>(module: &Module<BE>, infos: &A) -> Self - where - A: GGSWInfos, - { - Self::alloc_with( - module, - infos.base2k(), - infos.k(), - infos.dnum(), - infos.dsize(), - infos.rank(), - ) - } +impl<T: UnsignedInteger, BE: Backend> FheUintBlocksPreparedFactory<T, BE> for Module<BE> where + Self: Sized + GGSWPreparedFactory<BE> +{ +} - #[allow(dead_code)] - pub(crate) fn alloc_with<BE: Backend>( - module: &Module<BE>, +pub trait FheUintBlocksPreparedFactory<T: UnsignedInteger, BE: Backend> +where + Self: Sized + GGSWPreparedFactory<BE>, +{ + fn alloc_fhe_uint_blocks_prepared( + &self, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank, - ) -> Self { - Self { + ) -> FheUintBlocksPrepared<Vec<u8>, T, BE> { + FheUintBlocksPrepared { blocks: (0..T::WORD_SIZE) - .map(|_| GGSW::alloc(module.n().into(), base2k, k, rank, dnum, dsize)) + .map(|_| GGSWPrepared::alloc(self, base2k, k, dnum, dsize, rank)) .collect(), _base: 1, _phantom: PhantomData, } } -} -/// A prepared FHE ciphertext encrypting the bits of an [UnsignedInteger]. -pub struct FheUintBlocksPrep<D: Data, B: Backend, T: UnsignedInteger> { - pub(crate) blocks: Vec<GGSWPrepared<D, B>>, - pub(crate) _base: u8, - pub(crate) _phantom: PhantomData<T>, -} - -impl<T: UnsignedInteger, BE: Backend> FheUintBlocksPrep<Vec<u8>, BE, T> -where - Module<BE>: VmpPMatAlloc<BE>, -{ - #[allow(dead_code)] - pub(crate) fn alloc<A>(module: &Module<BE>, infos: &A) -> Self + fn alloc_fhe_uint_blocks_prepared_from_infos<A>(&self, infos: &A) -> FheUintBlocksPrepared<Vec<u8>, T, BE> where A: GGSWInfos, { - Self::alloc_with( - module, + self.alloc_fhe_uint_blocks_prepared( infos.base2k(), infos.k(), infos.dnum(),

@@ -91,160 +62,90 @@ infos.dsize(),

infos.rank(), ) } +} +impl<T: UnsignedInteger, BE: Backend> FheUintBlocksPrepared<Vec<u8>, T, BE> { #[allow(dead_code)] - pub(crate) fn alloc_with(module: &Module<BE>, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self + pub(crate) fn alloc<A, M>(module: &M, infos: &A) -> Self where - Module<BE>: VmpPMatAlloc<BE>, + A: GGSWInfos, + M: FheUintBlocksPreparedFactory<T, BE>, { - Self { - blocks: (0..T::WORD_SIZE) - .map(|_| GGSWPrepared::alloc(module, base2k, k, dnum, dsize, rank)) - .collect(), - _base: 1, - _phantom: PhantomData, - } + module.alloc_fhe_uint_blocks_prepared_from_infos(infos) + } + + #[allow(dead_code)] + pub(crate) fn alloc_with<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self + where + M: FheUintBlocksPreparedFactory<T, BE>, + { + module.alloc_fhe_uint_blocks_prepared(base2k, k, dnum, dsize, rank) } } -impl<D: DataMut, T: UnsignedInteger + ToBits, BE: Backend> FheUintBlocksPrep<D, BE, T> { - #[allow(dead_code)] - #[cfg(test)] - pub(crate) fn encrypt_sk<S>( - &mut self, - module: &Module<BE>, +#[cfg(test)] +impl<T: UnsignedInteger + ToBits, BE: Backend> FheUintBlocksPreparedEncryptSk<T, BE> for Module<BE> where + Self: Sized + ModuleN + GGSWEncryptSk<BE> + GGSWPreparedFactory<BE> +{ +} + +#[cfg(test)] +pub trait FheUintBlocksPreparedEncryptSk<T: UnsignedInteger + ToBits, BE: Backend> +where + Self: Sized + ModuleN + GGSWEncryptSk<BE> + GGSWPreparedFactory<BE>, +{ + fn fhe_uint_blocks_prepared_encrypt_sk<DM, S>( + &self, + res: &mut FheUintBlocksPrepared<DM, T, BE>, value: T, - sk: &GLWESecretPrepared<S, BE>, + sk: &S, source_xa: &mut Source, source_xe: &mut Source, scratch: &mut Scratch<BE>, ) where - S: DataRef, - Module<BE>: VecZnxAddScalarInplace - + VecZnxDftBytesOf - + VecZnxBigNormalize<BE> - + VecZnxDftApply<BE> - + SvpApplyDftToDftInplace<BE> - + VecZnxIdftApplyConsume<BE> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<BE> - + VecZnxAddNormal - + VecZnxNormalize<BE> - + VecZnxSub - + VmpPrepare<BE>, + DM: DataMut, + S: GLWESecretPreparedToRef<BE> + GLWEInfos, Scratch<BE>: ScratchTakeCore<BE>, { - #[cfg(debug_assertions)] - { - assert!(module.n().is_multiple_of(T::WORD_SIZE)); - assert_eq!(self.n(), module.n() as u32); - assert_eq!(sk.n(), module.n() as u32); - } + use poulpy_hal::api::ScratchTakeBasic; + + assert!(self.n().is_multiple_of(T::WORD_SIZE)); + assert_eq!(res.n(), self.n() as u32); + assert_eq!(sk.n(), self.n() as u32); - let (mut tmp_ggsw, scratch_1) = scratch.take_ggsw(self); - let (mut pt, scratch_2) = scratch_1.take_scalar_znx(module.n(), 1); + let (mut tmp_ggsw, scratch_1) = scratch.take_ggsw(res); + let (mut pt, scratch_2) = scratch_1.take_scalar_znx(self.n(), 1); for i in 0..T::WORD_SIZE { - use poulpy_hal::layouts::ZnxViewMut; pt.at_mut(0, 0)[0] = value.bit(i) as i64; - tmp_ggsw.encrypt_sk(&module, &pt, sk, source_xa, source_xe, scratch_2); - self.blocks[i].prepare(module, &tmp_ggsw, scratch_2); + tmp_ggsw.encrypt_sk(self, &pt, sk, source_xa, source_xe, scratch_2); + res.blocks[i].prepare(self, &tmp_ggsw, scratch_2); } } - - /// Prepares [FheUintBits] to [FheUintBitsPrep]. - pub fn prepare<BIT, KEY>(&mut self, module: &Module<BE>, bits: &FheUintBlocks<BIT, T>, key: &KEY, scratch: &mut Scratch<BE>) - where - BIT: DataRef, - KEY: FheUintPrepare<BE, FheUintBlocksPrep<D, BE, T>, FheUintBlocks<BIT, T>>, - { - key.prepare(module, self, bits, scratch); - } } #[cfg(test)] -impl<D: DataMut, T: UnsignedInteger + ToBits> FheUintBlocksPrepDebug<D, T> { - pub(crate) fn prepare<BIT, KEY, BE: Backend>( +impl<D: DataMut, T: UnsignedInteger + ToBits, BE: Backend> FheUintBlocksPrepared<D, T, BE> { + pub(crate) fn encrypt_sk<M, S>( &mut self, - module: &Module<BE>, - bits: &FheUintBlocks<BIT, T>, - key: &KEY, + module: &M, + value: T, + sk: &S, + source_xa: &mut Source, + source_xe: &mut Source, scratch: &mut Scratch<BE>, ) where - BIT: DataRef, - KEY: FheUintPrepare<BE, FheUintBlocksPrepDebug<D, T>, FheUintBlocks<BIT, T>>, - { - key.prepare(module, self, bits, scratch); - } -} - -#[cfg(test)] -impl<D: DataRef, T: UnsignedInteger + ToBits> FheUintBlocksPrepDebug<D, T> { - #[allow(dead_code)] - pub(crate) fn noise<S: DataRef, BE: Backend>(&self, module: &Module<BE>, sk: &GLWESecretPrepared<S, BE>, want: T) - where - Module<BE>: VecZnxDftBytesOf - + VecZnxBigBytesOf - + VecZnxDftApply<BE> - + SvpApplyDftToDftInplace<BE> - + VecZnxIdftApplyConsume<BE> - + VecZnxBigAddInplace<BE> - + VecZnxBigAddSmallInplace<BE> - + VecZnxBigNormalize<BE> - + VecZnxNormalizeTmpBytes - + VecZnxBigAlloc<BE> - + VecZnxDftAlloc<BE> - + VecZnxBigNormalizeTmpBytes - + VecZnxIdftApplyTmpA<BE> - + VecZnxAddScalarInplace - + VecZnxSubInplace, + S: GLWESecretPreparedToRef<BE> + GLWEInfos, + M: FheUintBlocksPreparedEncryptSk<T, BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - for (i, ggsw) in self.blocks.iter().enumerate() { - use poulpy_hal::layouts::{ScalarZnx, ZnxViewMut}; - let mut pt_want = ScalarZnx::alloc(self.n().into(), 1); - pt_want.at_mut(0, 0)[0] = want.bit(i) as i64; - ggsw.print_noise(module, sk, &pt_want); - } - } -} - -impl<D: DataRef, T: UnsignedInteger, B: Backend> LWEInfos for FheUintBlocksPrep<D, B, T> { - fn base2k(&self) -> poulpy_core::layouts::Base2K { - self.blocks[0].base2k() - } - - fn k(&self) -> poulpy_core::layouts::TorusPrecision { - self.blocks[0].k() - } - - fn n(&self) -> poulpy_core::layouts::Degree { - self.blocks[0].n() + module.fhe_uint_blocks_prepared_encrypt_sk(self, value, sk, source_xa, source_xe, scratch); } } -impl<D: DataRef, T: UnsignedInteger, B: Backend> GLWEInfos for FheUintBlocksPrep<D, B, T> { - fn rank(&self) -> poulpy_core::layouts::Rank { - self.blocks[0].rank() - } -} - -impl<D: DataRef, T: UnsignedInteger, B: Backend> GGSWInfos for FheUintBlocksPrep<D, B, T> { - fn dsize(&self) -> poulpy_core::layouts::Dsize { - self.blocks[0].dsize() - } - - fn dnum(&self) -> poulpy_core::layouts::Dnum { - self.blocks[0].dnum() - } -} - -#[cfg(test)] -impl<D: DataRef, T: UnsignedInteger> LWEInfos for FheUintBlocksPrepDebug<D, T> { +impl<D: DataRef, T: UnsignedInteger, B: Backend> LWEInfos for FheUintBlocksPrepared<D, T, B> { fn base2k(&self) -> poulpy_core::layouts::Base2K { self.blocks[0].base2k() }

@@ -258,15 +159,13 @@ self.blocks[0].n()

} } -#[cfg(test)] -impl<D: DataRef, T: UnsignedInteger> GLWEInfos for FheUintBlocksPrepDebug<D, T> { +impl<D: DataRef, T: UnsignedInteger, B: Backend> GLWEInfos for FheUintBlocksPrepared<D, T, B> { fn rank(&self) -> poulpy_core::layouts::Rank { self.blocks[0].rank() } } -#[cfg(test)] -impl<D: DataRef, T: UnsignedInteger> GGSWInfos for FheUintBlocksPrepDebug<D, T> { +impl<D: DataRef, T: UnsignedInteger, B: Backend> GGSWInfos for FheUintBlocksPrepared<D, T, B> { fn dsize(&self) -> poulpy_core::layouts::Dsize { self.blocks[0].dsize() }
M poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/mod.rs → poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/mod.rs

@@ -2,6 +2,11 @@ mod block;

mod block_prepared; mod word; +#[cfg(test)] +mod block_debug; +#[cfg(test)] +pub(crate) use block_debug::*; + pub use block::*; pub use block_prepared::*; pub use word::*;
M poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/word.rs → poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/word.rs

@@ -1,20 +1,14 @@

use itertools::Itertools; use poulpy_core::{ + GLWECopy, GLWEDecrypt, GLWEEncryptSk, GLWEPacking, ScratchTakeCore, layouts::{ - prepared::{GLWEAutomorphismKeyPrepared, GLWESecretPrepared}, GLWEInfos, GLWEPlaintextLayout, LWEInfos, TorusPrecision, GLWE - }, ScratchTakeCore, + GLWE, GLWEInfos, GLWEPlaintextLayout, GLWESecretPreparedToRef, LWEInfos, TorusPrecision, + prepared::GLWEAutomorphismKeyPrepared, + }, }; use poulpy_hal::{ - api::{ - ScratchAvailable, SvpApplyDftToDftInplace, VecZnxAddInplace, VecZnxAddNormal, - VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, - VecZnxBigAutomorphismInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallNegateInplace, VecZnxCopy, - VecZnxDftApply, VecZnxDftBytesOf, VecZnxDftCopy, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, - VecZnxNegateInplace, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, - VecZnxRshInplace, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, - VmpApplyDftToDftTmpBytes, - }, - layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}, + api::ModuleN, + layouts::{Backend, Data, DataMut, DataRef, Scratch}, source::Source, }; use std::{collections::HashMap, marker::PhantomData};

@@ -26,40 +20,15 @@ pub struct FheUintWord<D: Data, T: UnsignedInteger>(pub(crate) GLWE<D>, pub(crate) PhantomData<T>);

impl<D: DataMut, T: UnsignedInteger> FheUintWord<D, T> { #[allow(dead_code)] - fn post_process<ATK, BE: Backend>( + fn post_process<ATK, M, BE: Backend>( &mut self, - module: &Module<BE>, + module: &M, mut tmp_res: Vec<GLWE<&mut [u8]>>, auto_keys: &HashMap<i64, GLWEAutomorphismKeyPrepared<ATK, BE>>, scratch: &mut Scratch<BE>, ) where ATK: DataRef, - Module<BE>: VecZnxSub - + VecZnxCopy - + VecZnxNegateInplace - + VecZnxDftBytesOf - + VecZnxAddInplace - + VmpApplyDftToDftTmpBytes - + VecZnxNormalizeTmpBytes - + VecZnxDftApply<BE> - + VmpApplyDftToDft<BE> - + VmpApplyDftToDftAdd<BE> - + VecZnxIdftApplyConsume<BE> - + VecZnxBigNormalize<BE> - + VecZnxNormalize<BE> - + VecZnxRotateInplace<BE> - + VecZnxNormalizeInplace<BE> - + VecZnxSwitchRing - + VecZnxBigAutomorphismInplace<BE> - + VecZnxRshInplace<BE> - + VecZnxDftCopy<BE> - + VecZnxIdftApplyTmpA<BE> - + VecZnxSubInplace - + VecZnxBigNormalizeTmpBytes - + VecZnxBigAddSmallInplace<BE> - + VecZnxAutomorphismInplace<BE> - + VecZnxBigSubSmallNegateInplace<BE> - + VecZnxRotate, + M: GLWEPacking<BE> + GLWECopy, Scratch<BE>: ScratchTakeCore<BE>, { // Repacks the GLWE ciphertexts bits

@@ -69,10 +38,11 @@ let mut cts: HashMap<usize, &mut GLWE<&mut [u8]>> = HashMap::new();

for (i, ct) in tmp_res.iter_mut().enumerate().take(T::WORD_SIZE) { cts.insert(i * gap, ct); } - glwe_packing(module, &mut cts, log_gap, auto_keys, scratch); + + module.glwe_pack(&mut cts, log_gap, auto_keys, scratch); // And copies the repacked ciphertext on the receiver. - self.0.copy(module, cts.remove(&0).unwrap()) + module.glwe_copy(&mut self.0, cts.remove(&0).unwrap()); } }

@@ -97,29 +67,17 @@ }

} impl<D: DataMut, T: UnsignedInteger + ToBits> FheUintWord<D, T> { - pub fn encrypt_sk<S: DataRef, BE: Backend>( + pub fn encrypt_sk<S, M, BE: Backend>( &mut self, - module: &Module<BE>, + module: &M, data: T, - sk: &GLWESecretPrepared<S, BE>, + sk: &S, source_xa: &mut Source, source_xe: &mut Source, scratch: &mut Scratch<BE>, ) where - Module<BE>: VecZnxAddScalarInplace - + VecZnxDftBytesOf - + VecZnxBigNormalize<BE> - + VecZnxDftApply<BE> - + SvpApplyDftToDftInplace<BE> - + VecZnxIdftApplyConsume<BE> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<BE> - + VecZnxAddNormal - + VecZnxNormalize<BE> - + VecZnxSub, + S: GLWESecretPreparedToRef<BE> + GLWEInfos, + M: ModuleN + GLWEEncryptSk<BE>, Scratch<BE>: ScratchTakeCore<BE>, { #[cfg(debug_assertions)]

@@ -143,7 +101,7 @@ base2k: self.base2k(),

k: 1_usize.into(), }; - let (mut pt, scratch_1) = scratch.take_glwe_pt(&pt_infos); + let (mut pt, scratch_1) = scratch.take_glwe_plaintext(&pt_infos); pt.encode_vec_i64(&data_bits, TorusPrecision(1)); self.0

@@ -152,19 +110,10 @@ }

} impl<D: DataRef, T: UnsignedInteger + FromBits> FheUintWord<D, T> { - pub fn decrypt<S: DataRef, BE: Backend>( - &self, - module: &Module<BE>, - sk: &GLWESecretPrepared<S, BE>, - scratch: &mut Scratch<BE>, - ) -> T + pub fn decrypt<S, M, BE: Backend>(&self, module: &M, sk: &S, scratch: &mut Scratch<BE>) -> T where - Module<BE>: VecZnxDftApply<BE> - + SvpApplyDftToDftInplace<BE> - + VecZnxIdftApplyConsume<BE> - + VecZnxBigAddInplace<BE> - + VecZnxBigAddSmallInplace<BE> - + VecZnxBigNormalize<BE>, + S: GLWESecretPreparedToRef<BE> + GLWEInfos, + M: GLWEDecrypt<BE>, Scratch<BE>: ScratchTakeCore<BE>, { #[cfg(debug_assertions)]

@@ -182,7 +131,7 @@ base2k: self.base2k(),

k: 1_usize.into(), }; - let (mut pt, scratch_1) = scratch.take_glwe_pt(&pt_infos); + let (mut pt, scratch_1) = scratch.take_glwe_plaintext(&pt_infos); self.0.decrypt(module, &mut pt, sk, scratch_1);
M poulpy-schemes/src/tfhe/bdd_arithmetic/eval.rs → poulpy-schemes/src/tfhe/bdd_arithmetic/eval.rs

@@ -1,13 +1,12 @@

use itertools::Itertools; use poulpy_core::{ + GLWEAdd, GLWECopy, GLWEExternalProduct, GLWESub, ScratchTakeCore, layouts::{ - prepared::{GGSWPrepared, GGSWPreparedToRef}, GLWEToMut, LWEInfos, GLWE - }, GLWEExternalProduct, ScratchTakeCore + GLWE, LWEInfos, + prepared::{GGSWPrepared, GGSWPreparedToRef}, + }, }; -use poulpy_hal::{ - api::{VecZnxAddInplace, VecZnxCopy, VecZnxNegateInplace, VecZnxSub}, - layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxZero}, -}; +use poulpy_hal::layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxZero}; use crate::tfhe::bdd_arithmetic::UnsignedInteger;

@@ -29,45 +28,43 @@ }

pub struct Circuit<C: BitCircuitInfo, const N: usize>(pub [C; N]); -pub trait CircuitExecute<BE: Backend, T: UnsignedInteger> -where - Self: GetBitCircuitInfo<T>, -{ - fn execute<O>( +pub trait ExecuteBDDCircuit<T: UnsignedInteger, BE: Backend> { + fn execute_bdd_circuit<C, O>( &self, - module: &Module<BE>, out: &mut [GLWE<O>], inputs: &[&dyn GGSWPreparedToRef<BE>], + circuit: &C, scratch: &mut Scratch<BE>, ) where + C: GetBitCircuitInfo<T>, O: DataMut; } -impl<C: BitCircuitInfo, const N: usize, T: UnsignedInteger, BE: Backend> CircuitExecute<BE, T> for Circuit<C, N> +impl<T: UnsignedInteger, BE: Backend> ExecuteBDDCircuit<T, BE> for Module<BE> where - Self: GetBitCircuitInfo<T>, - Module<BE>: Cmux<BE> + VecZnxCopy, + Self: Cmux<BE> + GLWECopy, Scratch<BE>: ScratchTakeCore<BE>, { - fn execute<O>( + fn execute_bdd_circuit<C, O>( &self, - module: &Module<BE>, out: &mut [GLWE<O>], inputs: &[&dyn GGSWPreparedToRef<BE>], + circuit: &C, scratch: &mut Scratch<BE>, ) where + C: GetBitCircuitInfo<T>, O: DataMut, { #[cfg(debug_assertions)] { - assert_eq!(inputs.len(), self.input_size()); - assert!(out.len() >= self.output_size()); + assert_eq!(inputs.len(), circuit.input_size()); + assert!(out.len() >= circuit.output_size()); } - for (i, out_i) in out.iter_mut().enumerate().take(self.output_size()) { - let (nodes, levels, max_inter_state) = self.get_circuit(i); + for (i, out_i) in out.iter_mut().enumerate().take(circuit.output_size()) { + let (nodes, levels, max_inter_state) = circuit.get_circuit(i); - let (mut level, scratch_1) = scratch.take_glwe_ct_slice(max_inter_state * 2, out_i); + let (mut level, scratch_1) = scratch.take_glwe_slice(max_inter_state * 2, out_i); level.iter_mut().for_each(|ct| ct.data_mut().zero());

@@ -87,9 +84,9 @@ let nodes_lvl: &[Node] = &nodes[start..end];

for (j, node) in nodes_lvl.iter().enumerate() { if node.low_index == node.high_index { - next_level[j].copy(module, prev_level[node.low_index]); + self.glwe_copy(next_level[j], prev_level[node.low_index]); } else { - module.cmux( + self.cmux( next_level[j], prev_level[node.high_index], prev_level[node.low_index],

@@ -105,7 +102,7 @@

// handle last output // there's always only 1 node at last level let node: &Node = nodes.last().unwrap(); - module.cmux( + self.cmux( out_i, prev_level[node.high_index], prev_level[node.low_index],

@@ -114,7 +111,7 @@ scratch_1,

); } - for out_i in out.iter_mut().skip(self.output_size()) { + for out_i in out.iter_mut().skip(circuit.output_size()) { out_i.data_mut().zero(); } }

@@ -167,7 +164,8 @@ }

impl<BE: Backend> Cmux<BE> for Module<BE> where - Module<BE>: GLWEExternalProduct<BE> + VecZnxSub + VecZnxCopy + VecZnxNegateInplace + VecZnxAddInplace, + Module<BE>: GLWEExternalProduct<BE> + GLWESub + GLWEAdd, + Scratch<BE>: ScratchTakeCore<BE>, { fn cmux<O, T, F, S>(&self, out: &mut GLWE<O>, t: &GLWE<T>, f: &GLWE<F>, s: &GGSWPrepared<S, BE>, scratch: &mut Scratch<BE>) where

@@ -177,8 +175,8 @@ F: DataRef,

S: DataRef, { // let mut out: GLWECiphertext<&mut [u8]> = out.to_mut(); - out.sub(self, t, f); - out.external_product_inplace(self, s, scratch); - out.to_mut().add_inplace(self, f); + self.glwe_sub(out, t, f); + self.glwe_external_product_inplace(out, s, scratch); + self.glwe_add_inplace(out, f); } }
M poulpy-schemes/src/tfhe/bdd_arithmetic/key.rs → poulpy-schemes/src/tfhe/bdd_arithmetic/key.rs

@@ -1,26 +1,21 @@

#[cfg(test)] -use crate::tfhe::bdd_arithmetic::FheUintBlocksPrepDebug; +use crate::tfhe::bdd_arithmetic::FheUintBlocksPreparedDebug; use crate::tfhe::{ - bdd_arithmetic::{FheUintBlocks, FheUintBlocksPrep, UnsignedInteger}, - blind_rotation::{BlindRotationAlgo, BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyEncryptSk}, + bdd_arithmetic::{FheUintBlocks, FheUintBlocksPrepared, UnsignedInteger}, + blind_rotation::{BlindRotationAlgo, BlindRotationKey, BlindRotationKeyFactory}, circuit_bootstrapping::{ CircuitBootstrappingKey, CircuitBootstrappingKeyEncryptSk, CircuitBootstrappingKeyLayout, - CircuitBootstrappingKeyPrepared, CirtuitBootstrappingExecute, + CircuitBootstrappingKeyPrepared, CircuitBootstrappingKeyPreparedFactory, CirtuitBootstrappingExecute, }, }; use poulpy_core::{ + GLWEToLWESwitchingKeyEncryptSk, GetDistribution, LWEFromGLWE, ScratchTakeCore, layouts::{ - prepared::GLWEToLWESwitchingKeyPrepared, GLWESecret, GLWEToLWEKeyLayout, GLWEToLWESwitchingKey, LWESecret - }, ScratchTakeCore, + GGSWInfos, GGSWPreparedFactory, GLWEInfos, GLWESecretToRef, GLWEToLWEKeyLayout, GLWEToLWESwitchingKey, + GLWEToLWESwitchingKeyPreparedFactory, LWE, LWEInfos, LWESecretToRef, prepared::GLWEToLWESwitchingKeyPrepared, + }, }; use poulpy_hal::{ - api::{ - ScratchAvailable, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, - VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, - VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize, - VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, - VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPrepare, - }, layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}, source::Source, };

@@ -46,193 +41,256 @@ self.ks

} } -pub struct BDDKey<CBT, LWE, BRA> +pub struct BDDKey<D, BRA> where - CBT: Data, - LWE: Data, + D: Data, BRA: BlindRotationAlgo, { - cbt: CircuitBootstrappingKey<CBT, BRA>, - ks: GLWEToLWESwitchingKey<LWE>, + cbt: CircuitBootstrappingKey<D, BRA>, + ks: GLWEToLWESwitchingKey<D>, } -impl<BRA: BlindRotationAlgo> BDDKey<Vec<u8>, Vec<u8>, BRA> { - pub fn encrypt_sk<DLwe, DGlwe, A, BE: Backend>( - module: &Module<BE>, - sk_lwe: &LWESecret<DLwe>, - sk_glwe: &GLWESecret<DGlwe>, - infos: &A, - source_xa: &mut Source, - source_xe: &mut Source, - scratch: &mut Scratch<BE>, - ) -> Self +impl<BRA: BlindRotationAlgo> BDDKey<Vec<u8>, BRA> +where + BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyFactory<BRA>, +{ + pub fn alloc_from_infos<A>(infos: &A) -> Self where A: BDDKeyInfos, - DLwe: DataRef, - DGlwe: DataRef, - BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyAlloc + BlindRotationKeyEncryptSk<BE>, - Module<BE>: SvpApplyDftToDft<BE> - + VecZnxIdftApplyTmpA<BE> - + VecZnxAddScalarInplace - + VecZnxDftBytesOf - + VecZnxBigNormalize<BE> - + VecZnxDftApply<BE> - + SvpApplyDftToDftInplace<BE> - + VecZnxIdftApplyConsume<BE> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<BE> - + VecZnxAddNormal - + VecZnxNormalize<BE> - + VecZnxSub - + SvpPrepare<BE> - + VecZnxSwitchRing - + SvpPPolBytesOf - + SvpPPolAlloc<BE> - + VecZnxAutomorphism - + VecZnxAutomorphismInplace<BE>, - Scratch<BE>: ScratchTakeCore<BE>, { - let mut ks: GLWEToLWESwitchingKey<Vec<u8>> = GLWEToLWESwitchingKey::alloc(&infos.ks_infos()); - ks.encrypt_sk(module, sk_lwe, sk_glwe, source_xa, source_xe, scratch); - Self { - cbt: CircuitBootstrappingKey::encrypt_sk( - module, - sk_lwe, - sk_glwe, - &infos.cbt_infos(), - source_xa, - source_xe, - scratch, - ), - ks, + cbt: CircuitBootstrappingKey::alloc_from_infos(&infos.cbt_infos()), + ks: GLWEToLWESwitchingKey::alloc_from_infos(&infos.ks_infos()), } } } -pub struct BDDKeyPrepared<CBT, LWE, BRA, BE> +pub trait BDDKeyEncryptSk<BRA: BlindRotationAlgo, BE: Backend> { + fn bdd_key_encrypt_sk<D, S0, S1>( + &self, + res: &mut BDDKey<D, BRA>, + sk_lwe: &S0, + sk_glwe: &S1, + source_xa: &mut Source, + source_xe: &mut Source, + scratch: &mut Scratch<BE>, + ) where + D: DataMut, + S0: LWESecretToRef + GetDistribution + LWEInfos, + S1: GLWESecretToRef + GetDistribution + GLWEInfos; +} + +impl<BE: Backend, BRA: BlindRotationAlgo> BDDKeyEncryptSk<BRA, BE> for Module<BE> where - CBT: Data, - LWE: Data, + Self: CircuitBootstrappingKeyEncryptSk<BRA, BE> + GLWEToLWESwitchingKeyEncryptSk<BE>, + Scratch<BE>: ScratchTakeCore<BE>, +{ + fn bdd_key_encrypt_sk<D, S0, S1>( + &self, + res: &mut BDDKey<D, BRA>, + sk_lwe: &S0, + sk_glwe: &S1, + source_xa: &mut Source, + source_xe: &mut Source, + scratch: &mut Scratch<BE>, + ) 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<D: DataMut, BRA: BlindRotationAlgo> BDDKey<D, BRA> { + pub fn encrypt_sk<S0, S1, M, BE: Backend>( + &mut self, + module: &M, + sk_lwe: &S0, + sk_glwe: &S1, + source_xa: &mut Source, + source_xe: &mut Source, + scratch: &mut Scratch<BE>, + ) where + S0: LWESecretToRef + GetDistribution + LWEInfos, + S1: GLWESecretToRef + GetDistribution + GLWEInfos, + M: BDDKeyEncryptSk<BRA, BE>, + Scratch<BE>: ScratchTakeCore<BE>, + { + module.bdd_key_encrypt_sk(self, sk_lwe, sk_glwe, source_xa, source_xe, scratch); + } +} + +pub struct BDDKeyPrepared<D, BRA, BE> +where + D: Data, BRA: BlindRotationAlgo, BE: Backend, { - cbt: CircuitBootstrappingKeyPrepared<CBT, BRA, BE>, - ks: GLWEToLWESwitchingKeyPrepared<LWE, BE>, + pub(crate) cbt: CircuitBootstrappingKeyPrepared<D, BRA, BE>, + pub(crate) ks: GLWEToLWESwitchingKeyPrepared<D, BE>, } -impl<CBT: DataMut, LWE: DataMut, BRA: BlindRotationAlgo, BE: Backend> PrepareAlloc<BE, BDDKeyPrepared<CBT, LWE, BRA, BE>> - for BDDKey<CBT, LWE, BRA> +pub trait BDDKeyPreparedFactory<BRA: BlindRotationAlgo, BE: Backend> where - CircuitBootstrappingKey<CBT, BRA>: PrepareAlloc<BE, CircuitBootstrappingKeyPrepared<CBT, BRA, BE>>, - GLWEToLWESwitchingKey<LWE>: PrepareAlloc<BE, GLWEToLWESwitchingKeyPrepared<LWE, BE>>, + Self: Sized + CircuitBootstrappingKeyPreparedFactory<BRA, BE> + GLWEToLWESwitchingKeyPreparedFactory<BE>, { - fn prepare_alloc(&self, module: &Module<BE>, scratch: &mut Scratch<BE>) -> BDDKeyPrepared<CBT, LWE, BRA, BE> { + fn alloc_bdd_key_from_infos<A>(&self, infos: &A) -> BDDKeyPrepared<Vec<u8>, BRA, BE> + where + A: BDDKeyInfos, + { BDDKeyPrepared { - cbt: self.cbt.prepare_alloc(module, scratch), - ks: self.ks.prepare_alloc(module, scratch), + cbt: CircuitBootstrappingKeyPrepared::alloc_from_infos(self, &infos.cbt_infos()), + ks: GLWEToLWESwitchingKeyPrepared::alloc_from_infos(self, &infos.ks_infos()), } } + + fn prepare_bdd_key_tmp_bytes<A>(&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<DM, DR>(&self, res: &mut BDDKeyPrepared<DM, BRA, BE>, other: &BDDKey<DR, BRA>, scratch: &mut Scratch<BE>) + where + DM: DataMut, + DR: DataRef, + Scratch<BE>: ScratchTakeCore<BE>, + { + res.cbt.prepare(self, &other.cbt, scratch); + res.ks.prepare(self, &other.ks, scratch); + } +} +impl<BRA: BlindRotationAlgo, BE: Backend> BDDKeyPreparedFactory<BRA, BE> for Module<BE> where + Self: Sized + CircuitBootstrappingKeyPreparedFactory<BRA, BE> + GLWEToLWESwitchingKeyPreparedFactory<BE> +{ } -pub trait FheUintPrepare<BE: Backend, OUT, IN> { - fn prepare(&self, module: &Module<BE>, out: &mut OUT, bits: &IN, scratch: &mut Scratch<BE>); +impl<BRA: BlindRotationAlgo, BE: Backend> BDDKeyPrepared<Vec<u8>, BRA, BE> { + pub fn alloc_from_infos<M, A>(module: &M, infos: &A) -> Self + where + M: BDDKeyPreparedFactory<BRA, BE>, + A: BDDKeyInfos, + { + module.alloc_bdd_key_from_infos(infos) + } } -impl<CBT, OUT, IN, LWE, BRA, BE, T> FheUintPrepare<BE, FheUintBlocksPrep<OUT, BE, T>, FheUintBlocks<IN, T>> - for BDDKeyPrepared<CBT, LWE, BRA, BE> -where - T: UnsignedInteger, - CBT: DataRef, - OUT: DataMut, - IN: DataRef, - LWE: DataRef, - BRA: BlindRotationAlgo, - BE: Backend, - Module<BE>: VmpPrepare<BE> - + VecZnxRotate - + VecZnxDftBytesOf - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDft<BE> - + VmpApplyDftToDftAdd<BE> - + VecZnxDftApply<BE> - + VecZnxIdftApplyConsume<BE> - + VecZnxBigAddSmallInplace<BE> - + VecZnxBigNormalize<BE> - + VecZnxNormalize<BE> - + VecZnxNormalizeTmpBytes, - Scratch<BE>: ScratchAvailable + TakeVecZnxDft<BE> + TakeGLWE + TakeVecZnx + TakeGGSW, - CircuitBootstrappingKeyPrepared<CBT, BRA, BE>: CirtuitBootstrappingExecute<BE>, -{ - fn prepare( +impl<D: DataMut, BRA: BlindRotationAlgo, BE: Backend> BDDKeyPrepared<D, BRA, BE> { + pub fn prepare<DR, M>(&mut self, module: &M, other: &BDDKey<DR, BRA>, scratch: &mut Scratch<BE>) + where + DR: DataRef, + M: BDDKeyPreparedFactory<BRA, BE>, + Scratch<BE>: ScratchTakeCore<BE>, + { + module.prepare_bdd_key(self, other, scratch); + } +} + +pub trait FheUintBlocksPrepare<BRA: BlindRotationAlgo, T: UnsignedInteger, BE: Backend> { + fn fhe_uint_blocks_prepare_tmp_bytes<R, A>( &self, - module: &Module<BE>, - out: &mut FheUintBlocksPrep<OUT, BE, T>, - bits: &FheUintBlocks<IN, T>, + block_size: usize, + extension_factor: usize, + res_infos: &R, + infos: &A, + ) -> usize + where + R: GGSWInfos, + A: BDDKeyInfos; + fn fhe_uint_blocks_prepare<DM, DR0, DR1>( + &self, + res: &mut FheUintBlocksPrepared<DM, T, BE>, + bits: &FheUintBlocks<DR0, T>, + key: &BDDKeyPrepared<DR1, BRA, BE>, scratch: &mut Scratch<BE>, - ) { - #[cfg(debug_assertions)] - { - assert_eq!(out.blocks.len(), bits.blocks.len()); - } - let mut lwe: LWE<Vec<u8>> = LWE::alloc(&bits.blocks[0]); //TODO: add TakeLWE - let (mut tmp_ggsw, scratch_1) = scratch.take_ggsw(out); - for (dst, src) in out.blocks.iter_mut().zip(bits.blocks.iter()) { - lwe.from_glwe(module, src, &self.ks, scratch_1); - self.cbt - .execute_to_constant(module, &mut tmp_ggsw, &lwe, 1, 1, scratch_1); - dst.prepare(module, &tmp_ggsw, scratch_1); - } - } + ) where + DM: DataMut, + DR0: DataRef, + DR1: DataRef; } -#[cfg(test)] -impl<CBT, OUT, IN, LWE, BRA, BE, T> FheUintPrepare<BE, FheUintBlocksPrepDebug<OUT, T>, FheUintBlocks<IN, T>> - for BDDKeyPrepared<CBT, LWE, BRA, BE> +impl<BRA: BlindRotationAlgo, BE: Backend, T: UnsignedInteger> FheUintBlocksPrepare<BRA, T, BE> for Module<BE> where - T: UnsignedInteger, - CBT: DataRef, - OUT: DataMut, - IN: DataRef, - LWE: DataRef, - BRA: BlindRotationAlgo, - BE: Backend, - Module<BE>: VmpPrepare<BE> - + VecZnxRotate - + VecZnxDftBytesOf - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDft<BE> - + VmpApplyDftToDftAdd<BE> - + VecZnxDftApply<BE> - + VecZnxIdftApplyConsume<BE> - + VecZnxBigAddSmallInplace<BE> - + VecZnxBigNormalize<BE> - + VecZnxNormalize<BE> - + VecZnxNormalizeTmpBytes, + Self: LWEFromGLWE<BE> + CirtuitBootstrappingExecute<BRA, BE> + GGSWPreparedFactory<BE>, Scratch<BE>: ScratchTakeCore<BE>, - CircuitBootstrappingKeyPrepared<CBT, BRA, BE>: CirtuitBootstrappingExecute<BE>, { - fn prepare( + fn fhe_uint_blocks_prepare_tmp_bytes<R, A>( &self, - module: &Module<BE>, - out: &mut FheUintBlocksPrepDebug<OUT, T>, - bits: &FheUintBlocks<IN, T>, + 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<DM, DR0, DR1>( + &self, + res: &mut FheUintBlocksPrepared<DM, T, BE>, + bits: &FheUintBlocks<DR0, T>, + key: &BDDKeyPrepared<DR1, BRA, BE>, scratch: &mut Scratch<BE>, - ) { - #[cfg(debug_assertions)] - { - assert_eq!(out.blocks.len(), bits.blocks.len()); - } - let mut lwe: LWE<Vec<u8>> = LWE::alloc(&bits.blocks[0]); //TODO: add TakeLWE - for (dst, src) in out.blocks.iter_mut().zip(bits.blocks.iter()) { - lwe.from_glwe(module, src, &self.ks, scratch); - self.cbt - .execute_to_constant(module, dst, &lwe, 1, 1, scratch); + ) where + DM: DataMut, + DR0: DataRef, + DR1: DataRef, + { + assert_eq!(res.blocks.len(), bits.blocks.len()); + + let mut lwe: LWE<Vec<u8>> = 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<D: DataMut, T: UnsignedInteger, BE: Backend> FheUintBlocksPrepared<D, T, BE> { + pub fn prepare<BRA, M, O, K>( + &mut self, + module: &M, + other: &FheUintBlocks<O, T>, + key: &BDDKeyPrepared<K, BRA, BE>, + scratch: &mut Scratch<BE>, + ) where + BRA: BlindRotationAlgo, + O: DataRef, + K: DataRef, + M: FheUintBlocksPrepare<BRA, T, BE>, + Scratch<BE>: ScratchTakeCore<BE>, + { + module.fhe_uint_blocks_prepare(self, other, key, scratch); + } +} + +#[cfg(test)] +pub(crate) trait FheUintBlockDebugPrepare<BRA: BlindRotationAlgo, T: UnsignedInteger, BE: Backend> { + fn fhe_uint_block_debug_prepare<DM, DR0, DR1>( + &self, + res: &mut FheUintBlocksPreparedDebug<DM, T>, + bits: &FheUintBlocks<DR0, T>, + key: &BDDKeyPrepared<DR1, BRA, BE>, + scratch: &mut Scratch<BE>, + ) where + DM: DataMut, + DR0: DataRef, + DR1: DataRef; +}
M poulpy-schemes/src/tfhe/bdd_arithmetic/parameters.rs → poulpy-schemes/src/tfhe/bdd_arithmetic/parameters.rs

@@ -1,7 +1,7 @@

#[cfg(test)] use poulpy_core::layouts::{ - AutomorphismKeyLayout, Base2K, Degree, Dnum, Dsize, GGSWLayout, GLWELayout, GLWEToLWEKeyLayout, Rank, TensorKeyLayout, - TorusPrecision, + Base2K, Degree, Dnum, Dsize, GGSWLayout, GLWEAutomorphismKeyLayout, GLWELayout, GLWETensorKeyLayout, GLWEToLWEKeyLayout, + Rank, TorusPrecision, }; #[cfg(test)]

@@ -53,7 +53,7 @@ k: TorusPrecision(52),

dnum: Dnum(3), rank: Rank(TEST_RANK), }, - layout_atk: AutomorphismKeyLayout { + layout_atk: GLWEAutomorphismKeyLayout { n: Degree(TEST_N_GLWE), base2k: Base2K(TEST_BASE2K), k: TorusPrecision(52),

@@ -61,7 +61,7 @@ rank: Rank(TEST_RANK),

dnum: Dnum(3), dsize: Dsize(1), }, - layout_tsk: TensorKeyLayout { + layout_tsk: GLWETensorKeyLayout { n: Degree(TEST_N_GLWE), base2k: Base2K(TEST_BASE2K), k: TorusPrecision(52),
M poulpy-schemes/src/tfhe/bdd_arithmetic/test.rs → poulpy-schemes/src/tfhe/bdd_arithmetic/test.rs

@@ -2,43 +2,24 @@ use std::time::Instant;

use poulpy_backend::FFT64Ref; use poulpy_core::{ - TakeGGSW, TakeGLWEPlaintext, - layouts::{ - GGSWLayout, GLWELayout, GLWESecret, LWEInfos, LWESecret, - prepared::{GLWESecretPrepared, PrepareAlloc}, - }, + GGSWNoise, GLWEDecrypt, GLWENoise, ScratchTakeCore, + layouts::{GGSWLayout, GLWELayout, GLWESecret, GLWESecretPreparedFactory, LWEInfos, LWESecret, prepared::GLWESecretPrepared}, }; use poulpy_hal::{ - api::{ - ModuleNew, ScratchAvailable, ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, SvpApplyDftToDftInplace, - SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, TakeScalarZnx, TakeSlice, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, - VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, - VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigAutomorphismInplace, VecZnxBigBytesOf, - VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallNegateInplace, VecZnxCopy, VecZnxDftAddInplace, - VecZnxDftAlloc, VecZnxDftApply, VecZnxDftBytesOf, VecZnxDftCopy, VecZnxFillUniform, VecZnxIdftApplyConsume, - VecZnxIdftApplyTmpA, VecZnxNegateInplace, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, - VecZnxRotateInplace, VecZnxRotateInplaceTmpBytes, VecZnxRshInplace, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, - VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, ZnAddNormal, ZnFillUniform, - ZnNormalizeInplace, - }, + api::{ModuleNew, ScratchOwnedAlloc, ScratchOwnedBorrow}, layouts::{Backend, Module, Scratch, ScratchOwned}, - oep::{ - ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeMatZnxImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, - TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxDftSliceImpl, TakeVecZnxImpl, TakeVecZnxSliceImpl, - }, source::Source, }; use rand::RngCore; use crate::tfhe::{ bdd_arithmetic::{ - Add, BDDKey, BDDKeyLayout, BDDKeyPrepared, FheUintBlocks, FheUintBlocksPrep, FheUintBlocksPrepDebug, Sub, - TEST_BDD_KEY_LAYOUT, TEST_BLOCK_SIZE, TEST_GGSW_INFOS, TEST_GLWE_INFOS, TEST_N_LWE, + Add, BDDKey, BDDKeyEncryptSk, BDDKeyLayout, BDDKeyPrepared, BDDKeyPreparedFactory, ExecuteBDDCircuit2WTo1W, + FheUintBlockDebugPrepare, FheUintBlocks, FheUintBlocksPrepare, FheUintBlocksPrepared, FheUintBlocksPreparedDebug, + FheUintBlocksPreparedEncryptSk, FheUintBlocksPreparedFactory, Sub, TEST_BDD_KEY_LAYOUT, TEST_BLOCK_SIZE, TEST_GGSW_INFOS, + TEST_GLWE_INFOS, TEST_N_LWE, }, - blind_rotation::{ - BlincRotationExecute, BlindRotationAlgo, BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyEncryptSk, - BlindRotationKeyPrepared, CGGI, - }, + blind_rotation::{BlindRotationAlgo, BlindRotationKey, BlindRotationKeyFactory, CGGI}, }; #[test]

@@ -48,64 +29,21 @@ }

fn test_bdd_2w_to_1w<BE: Backend, BRA: BlindRotationAlgo>() where - Module<BE>: ModuleNew<BE> + SvpPPolAlloc<BE> + SvpPrepare<BE> + VmpPMatAlloc<BE>, + Module<BE>: ModuleNew<BE> + + GLWESecretPreparedFactory<BE> + + GLWEDecrypt<BE> + + GLWENoise<BE> + + FheUintBlocksPreparedFactory<u32, BE> + + FheUintBlocksPreparedEncryptSk<u32, BE> + + FheUintBlockDebugPrepare<BRA, u32, BE> + + BDDKeyEncryptSk<BRA, BE> + + BDDKeyPreparedFactory<BRA, BE> + + GGSWNoise<BE> + + FheUintBlocksPrepare<BRA, u32, BE> + + ExecuteBDDCircuit2WTo1W<u32, BE>, + BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyFactory<BRA>, ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>, - Module<BE>: VecZnxAddScalarInplace - + VecZnxDftBytesOf - + VecZnxBigNormalize<BE> - + VecZnxDftApply<BE> - + SvpApplyDftToDftInplace<BE> - + VecZnxIdftApplyConsume<BE> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<BE> - + VecZnxAddNormal - + VecZnxNormalize<BE> - + VecZnxSub - + VmpPrepare<BE>, - Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx + TakeGGSW + TakeScalarZnx + TakeSlice, - Module<BE>: VecZnxCopy + VecZnxNegateInplace + VmpApplyDftToDftTmpBytes + VmpApplyDftToDft<BE> + VmpApplyDftToDftAdd<BE>, - Module<BE>: VecZnxBigAddInplace<BE> + VecZnxBigAddSmallInplace<BE> + VecZnxBigNormalize<BE>, - Scratch<BE>: TakeVecZnxDft<BE> + TakeVecZnxBig<BE> + TakeGLWEPlaintext<BE>, - Module<BE>: VecZnxAutomorphism - + VecZnxSwitchRing - + VecZnxBigBytesOf - + VecZnxIdftApplyTmpA<BE> - + SvpApplyDftToDft<BE> - + VecZnxBigAlloc<BE> - + VecZnxDftAlloc<BE> - + VecZnxBigNormalizeTmpBytes - + SvpPPolBytesOf - + VecZnxRotateInplace<BE> - + VecZnxBigAutomorphismInplace<BE> - + VecZnxRshInplace<BE> - + VecZnxDftCopy<BE> - + VecZnxAutomorphismInplace<BE> - + VecZnxBigSubSmallNegateInplace<BE> - + VecZnxRotateInplaceTmpBytes - + VecZnxBigBytesOf - + VecZnxDftAddInplace<BE> - + VecZnxRotate - + ZnFillUniform - + ZnAddNormal - + ZnNormalizeInplace<BE>, - BE: Backend - + ScratchOwnedAllocImpl<BE> - + ScratchOwnedBorrowImpl<BE> - + TakeVecZnxDftImpl<BE> - + ScratchAvailableImpl<BE> - + TakeVecZnxImpl<BE> - + TakeScalarZnxImpl<BE> - + TakeSvpPPolImpl<BE> - + TakeVecZnxBigImpl<BE> - + TakeVecZnxDftSliceImpl<BE> - + TakeMatZnxImpl<BE> - + TakeVecZnxSliceImpl<BE>, - BlindRotationKey<Vec<u8>, BRA>: PrepareAlloc<BE, BlindRotationKeyPrepared<Vec<u8>, BRA, BE>>, - BlindRotationKeyPrepared<Vec<u8>, BRA, BE>: BlincRotationExecute<BE>, - BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyAlloc + BlindRotationKeyEncryptSk<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { let glwe_infos: GLWELayout = TEST_GLWE_INFOS; let ggsw_infos: GGSWLayout = TEST_GGSW_INFOS;

@@ -122,7 +60,8 @@ let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(1 << 22);

let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_infos); sk_glwe.fill_ternary_prob(0.5, &mut source_xs); - let sk_glwe_prep: GLWESecretPrepared<Vec<u8>, BE> = sk_glwe.prepare_alloc(&module, scratch.borrow()); + let mut sk_glwe_prep: GLWESecretPrepared<Vec<u8>, BE> = GLWESecretPrepared::alloc_from_infos(&module, &glwe_infos); + sk_glwe_prep.prepare(&module, &sk_glwe); let a: u32 = source.next_u32(); let b: u32 = source.next_u32();

@@ -130,12 +69,15 @@

println!("a: {a}"); println!("b: {b}"); - let mut a_enc_prep: FheUintBlocksPrep<Vec<u8>, BE, u32> = FheUintBlocksPrep::<Vec<u8>, BE, u32>::alloc(&module, &ggsw_infos); - let mut b_enc_prep: FheUintBlocksPrep<Vec<u8>, BE, u32> = FheUintBlocksPrep::<Vec<u8>, BE, u32>::alloc(&module, &ggsw_infos); + let mut a_enc_prep: FheUintBlocksPrepared<Vec<u8>, u32, BE> = + FheUintBlocksPrepared::<Vec<u8>, u32, BE>::alloc(&module, &ggsw_infos); + let mut b_enc_prep: FheUintBlocksPrepared<Vec<u8>, u32, BE> = + FheUintBlocksPrepared::<Vec<u8>, u32, BE>::alloc(&module, &ggsw_infos); let mut c_enc: FheUintBlocks<Vec<u8>, u32> = FheUintBlocks::<Vec<u8>, u32>::alloc(&module, &glwe_infos); - let mut c_enc_prep_debug: FheUintBlocksPrepDebug<Vec<u8>, u32> = - FheUintBlocksPrepDebug::<Vec<u8>, u32>::alloc(&module, &ggsw_infos); - let mut c_enc_prep: FheUintBlocksPrep<Vec<u8>, BE, u32> = FheUintBlocksPrep::<Vec<u8>, BE, u32>::alloc(&module, &ggsw_infos); + let mut c_enc_prep_debug: FheUintBlocksPreparedDebug<Vec<u8>, u32> = + FheUintBlocksPreparedDebug::<Vec<u8>, u32>::alloc(&module, &ggsw_infos); + let mut c_enc_prep: FheUintBlocksPrepared<Vec<u8>, u32, BE> = + FheUintBlocksPrepared::<Vec<u8>, u32, BE>::alloc(&module, &ggsw_infos); a_enc_prep.encrypt_sk( &module,

@@ -178,17 +120,19 @@ sk_lwe.fill_binary_block(block_size as usize, &mut source_xs);

let bdd_key_infos: BDDKeyLayout = TEST_BDD_KEY_LAYOUT; + let mut bdd_key: BDDKey<Vec<u8>, BRA> = BDDKey::alloc_from_infos(&bdd_key_infos); + let now: Instant = Instant::now(); - let bdd_key: BDDKey<Vec<u8>, Vec<u8>, BRA> = BDDKey::encrypt_sk( + bdd_key.encrypt_sk( &module, &sk_lwe, &sk_glwe, - &bdd_key_infos, &mut source_xa, &mut source_xe, scratch.borrow(), ); - let bdd_key_prepared: BDDKeyPrepared<Vec<u8>, Vec<u8>, BRA, BE> = bdd_key.prepare_alloc(&module, scratch.borrow()); + let mut bdd_key_prepared: BDDKeyPrepared<Vec<u8>, BRA, BE> = BDDKeyPrepared::alloc_from_infos(&module, &bdd_key_infos); + bdd_key_prepared.prepare(&module, &bdd_key, scratch.borrow()); println!("BDD-KGEN: {} ms", now.elapsed().as_millis()); let now: Instant = Instant::now();
M poulpy-schemes/src/tfhe/blind_rotation/algorithms/cggi/key_prepared.rs → poulpy-schemes/src/tfhe/blind_rotation/algorithms/cggi/key_prepared.rs

@@ -33,7 +33,14 @@ _phantom: PhantomData,

} } - fn blind_rotation_key_prepare<DM, DR>( + fn blind_rotation_key_prepare_tmp_bytes<A>(&self, infos: &A) -> usize + where + A: BlindRotationKeyInfos, + { + self.ggsw_prepare_tmp_bytes(infos) + } + + fn prepare_blind_rotation_key<DM, DR>( &self, res: &mut BlindRotationKeyPrepared<DM, CGGI, BE>, other: &BlindRotationKey<DR, CGGI>,
M poulpy-schemes/src/tfhe/blind_rotation/layouts/key_prepared.rs → poulpy-schemes/src/tfhe/blind_rotation/layouts/key_prepared.rs

@@ -14,7 +14,11 @@ fn blind_rotation_key_prepared_alloc<A>(&self, infos: &A) -> BlindRotationKeyPrepared<Vec<u8>, BRA, BE>

where A: BlindRotationKeyInfos; - fn blind_rotation_key_prepare<DM, DR>( + fn blind_rotation_key_prepare_tmp_bytes<A>(&self, infos: &A) -> usize + where + A: BlindRotationKeyInfos; + + fn prepare_blind_rotation_key<DM, DR>( &self, res: &mut BlindRotationKeyPrepared<DM, BRA, BE>, other: &BlindRotationKey<DR, BRA>,

@@ -32,6 +36,14 @@ M: BlindRotationKeyPreparedFactory<BRA, BE>,

{ module.blind_rotation_key_prepared_alloc(infos) } + + pub fn prepare_tmp_bytes<M, A>(module: &M, infos: &A) -> usize + where + A: BlindRotationKeyInfos, + M: BlindRotationKeyPreparedFactory<BRA, BE>, + { + module.blind_rotation_key_prepare_tmp_bytes(infos) + } } impl<D: DataMut, BRA: BlindRotationAlgo, BE: Backend> BlindRotationKeyPrepared<D, BRA, BE> {

@@ -39,7 +51,7 @@ pub fn prepare<DR: DataRef, M>(&mut self, module: &M, other: &BlindRotationKey<DR, BRA>, scratch: &mut Scratch<BE>)

where M: BlindRotationKeyPreparedFactory<BRA, BE>, { - module.blind_rotation_key_prepare(self, other, scratch); + module.prepare_blind_rotation_key(self, other, scratch); } }
M poulpy-schemes/src/tfhe/circuit_bootstrapping/circuit.rs → poulpy-schemes/src/tfhe/circuit_bootstrapping/circuit.rs

@@ -18,10 +18,21 @@ use crate::tfhe::{

blind_rotation::{ BlindRotationAlgo, BlindRotationExecute, LookUpTableLayout, LookUpTableRotationDirection, LookupTable, LookupTableFactory, }, - circuit_bootstrapping::CircuitBootstrappingKeyPrepared, + circuit_bootstrapping::{CircuitBootstrappingKeyInfos, CircuitBootstrappingKeyPrepared}, }; pub trait CirtuitBootstrappingExecute<BRA: BlindRotationAlgo, BE: Backend> { + fn circuit_bootstrapping_execute_tmp_bytes<R, A>( + &self, + block_size: usize, + extension_factor: usize, + res_infos: &R, + cbt_infos: &A, + ) -> usize + where + R: GGSWInfos, + A: CircuitBootstrappingKeyInfos; + fn circuit_bootstrapping_execute_to_constant<R, L, D>( &self, res: &mut R,

@@ -68,6 +79,7 @@ {

module.circuit_bootstrapping_execute_to_constant(res, lwe, self, log_domain, extension_factor, scratch); } + #[allow(clippy::too_many_arguments)] pub fn execute_to_exponent<R, L, M>( &self, module: &M,

@@ -107,6 +119,27 @@ + GLWEDecrypt<BE>,

ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>, Scratch<BE>: ScratchTakeCore<BE>, { + fn circuit_bootstrapping_execute_tmp_bytes<R, A>( + &self, + block_size: usize, + extension_factor: usize, + res_infos: &R, + cbt_infos: &A, + ) -> usize + where + R: GGSWInfos, + A: CircuitBootstrappingKeyInfos, + { + self.blind_rotation_execute_tmp_bytes( + block_size, + extension_factor, + res_infos, + &cbt_infos.brk_infos(), + ) + .max(self.glwe_trace_tmp_bytes(res_infos, res_infos, &cbt_infos.atk_infos())) + .max(self.ggsw_from_gglwe_tmp_bytes(res_infos, &cbt_infos.tsk_infos())) + } + fn circuit_bootstrapping_execute_to_constant<R, L, D>( &self, res: &mut R,
M poulpy-schemes/src/tfhe/circuit_bootstrapping/key_prepared.rs → poulpy-schemes/src/tfhe/circuit_bootstrapping/key_prepared.rs

@@ -75,6 +75,16 @@ })

.collect(), } } + + fn circuit_bootstrapping_key_prepare_tmp_bytes<A>(&self, infos: &A) -> usize + where + A: CircuitBootstrappingKeyInfos, + { + self.blind_rotation_key_prepare_tmp_bytes(&infos.brk_infos()) + .max(self.prepare_tensor_key_tmp_bytes(&infos.tsk_infos())) + .max(self.prepare_glwe_automorphism_key_tmp_bytes(&infos.atk_infos())) + } + fn circuit_bootstrapping_key_prepare<DM, DR>( &self, res: &mut CircuitBootstrappingKeyPrepared<DM, BRA, BE>,
M poulpy-schemes/src/tfhe/mod.rs → poulpy-schemes/src/tfhe/mod.rs

@@ -1,3 +1,3 @@

-// pub mod bdd_arithmetic; +pub mod bdd_arithmetic; pub mod blind_rotation; pub mod circuit_bootstrapping;