use backend::hal::{ api::{TakeMatZnx, TakeScalarZnx, TakeSvpPPol, TakeVecZnx, TakeVecZnxDft, TakeVmpPMat}, layouts::{Backend, DataRef, Module, Scratch}, oep::{TakeMatZnxImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, TakeVmpPMatImpl}, }; use crate::{ AutomorphismKey, AutomorphismKeyExec, GGLWECiphertext, GGLWECiphertextExec, GGSWCiphertext, GGSWCiphertextExec, GLWECiphertext, GLWEPlaintext, GLWEPublicKey, GLWEPublicKeyExec, GLWESecret, GLWESecretExec, GLWESwitchingKey, GLWESwitchingKeyExec, GLWETensorKey, GLWETensorKeyExec, Infos, dist::Distribution, }; pub trait TakeLike<'a, B: Backend, T> { type Output; fn take_like(&'a mut self, template: &T) -> (Self::Output, &'a mut Self); } pub trait TakeGLWECt { fn take_glwe_ct(&mut self, module: &Module, basek: usize, k: usize, rank: usize) -> (GLWECiphertext<&mut [u8]>, &mut Self); } pub trait TakeGLWECtSlice { fn take_glwe_ct_slice( &mut self, size: usize, module: &Module, basek: usize, k: usize, rank: usize, ) -> (Vec>, &mut Self); } pub trait TakeGLWEPt { fn take_glwe_pt(&mut self, module: &Module, basek: usize, k: usize) -> (GLWEPlaintext<&mut [u8]>, &mut Self); } pub trait TakeGGLWE { fn take_gglwe( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize, ) -> (GGLWECiphertext<&mut [u8]>, &mut Self); } pub trait TakeGGLWEExec { fn take_gglwe_exec( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize, ) -> (GGLWECiphertextExec<&mut [u8], B>, &mut Self); } pub trait TakeGGSW { fn take_ggsw( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank: usize, ) -> (GGSWCiphertext<&mut [u8]>, &mut Self); } pub trait TakeGGSWExec { fn take_ggsw_exec( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank: usize, ) -> (GGSWCiphertextExec<&mut [u8], B>, &mut Self); } pub trait TakeGLWESecret { fn take_glwe_secret(&mut self, module: &Module, rank: usize) -> (GLWESecret<&mut [u8]>, &mut Self); } pub trait TakeGLWESecretExec { fn take_glwe_secret_exec(&mut self, module: &Module, rank: usize) -> (GLWESecretExec<&mut [u8], B>, &mut Self); } pub trait TakeGLWEPk { fn take_glwe_pk(&mut self, module: &Module, basek: usize, k: usize, rank: usize) -> (GLWEPublicKey<&mut [u8]>, &mut Self); } pub trait TakeGLWEPkExec { fn take_glwe_pk_exec( &mut self, module: &Module, basek: usize, k: usize, rank: usize, ) -> (GLWEPublicKeyExec<&mut [u8], B>, &mut Self); } pub trait TakeGLWESwitchingKey { fn take_glwe_switching_key( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize, ) -> (GLWESwitchingKey<&mut [u8]>, &mut Self); } pub trait TakeGLWESwitchingKeyExec { fn take_glwe_switching_key_exec( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize, ) -> (GLWESwitchingKeyExec<&mut [u8], B>, &mut Self); } pub trait TakeTensorKey { fn take_tensor_key( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank: usize, ) -> (GLWETensorKey<&mut [u8]>, &mut Self); } pub trait TakeTensorKeyExec { fn take_tensor_key_exec( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank: usize, ) -> (GLWETensorKeyExec<&mut [u8], B>, &mut Self); } pub trait TakeAutomorphismKey { fn take_automorphism_key( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank: usize, ) -> (AutomorphismKey<&mut [u8]>, &mut Self); } pub trait TakeAutomorphismKeyExec { fn take_automorphism_key_exec( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank: usize, ) -> (AutomorphismKeyExec<&mut [u8], B>, &mut Self); } impl TakeGLWECt for Scratch where Scratch: TakeVecZnx, { fn take_glwe_ct( &mut self, module: &Module, basek: usize, k: usize, rank: usize, ) -> (GLWECiphertext<&mut [u8]>, &mut Self) { let (data, scratch) = self.take_vec_znx(module, rank + 1, k.div_ceil(basek)); (GLWECiphertext { data, basek, k }, scratch) } } impl<'a, B, D> TakeLike<'a, B, GLWECiphertext> for Scratch where B: Backend + TakeVecZnxImpl, D: DataRef, { type Output = GLWECiphertext<&'a mut [u8]>; fn take_like(&'a mut self, template: &GLWECiphertext) -> (Self::Output, &'a mut Self) { let (data, scratch) = B::take_vec_znx_impl(self, template.n(), template.cols(), template.size()); ( GLWECiphertext { data, basek: template.basek(), k: template.k(), }, scratch, ) } } impl TakeGLWECtSlice for Scratch where Scratch: TakeVecZnx, { fn take_glwe_ct_slice( &mut self, size: usize, module: &Module, basek: usize, k: usize, rank: usize, ) -> (Vec>, &mut Self) { let mut scratch: &mut Scratch = self; let mut cts: Vec> = Vec::with_capacity(size); for _ in 0..size { let (ct, new_scratch) = scratch.take_glwe_ct(module, basek, k, rank); scratch = new_scratch; cts.push(ct); } (cts, scratch) } } impl TakeGLWEPt for Scratch where Scratch: TakeVecZnx, { fn take_glwe_pt(&mut self, module: &Module, basek: usize, k: usize) -> (GLWEPlaintext<&mut [u8]>, &mut Self) { let (data, scratch) = self.take_vec_znx(module, 1, k.div_ceil(basek)); (GLWEPlaintext { data, basek, k }, scratch) } } impl<'a, B, D> TakeLike<'a, B, GLWEPlaintext> for Scratch where B: Backend + TakeVecZnxImpl, D: DataRef, { type Output = GLWEPlaintext<&'a mut [u8]>; fn take_like(&'a mut self, template: &GLWEPlaintext) -> (Self::Output, &'a mut Self) { let (data, scratch) = B::take_vec_znx_impl(self, template.n(), template.cols(), template.size()); ( GLWEPlaintext { data, basek: template.basek(), k: template.k(), }, scratch, ) } } impl TakeGGLWE for Scratch where Scratch: TakeMatZnx, { fn take_gglwe( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize, ) -> (GGLWECiphertext<&mut [u8]>, &mut Self) { let (data, scratch) = self.take_mat_znx( module, rows.div_ceil(digits), rank_in, rank_out + 1, k.div_ceil(basek), ); ( GGLWECiphertext { data: data, basek: basek, k, digits, }, scratch, ) } } impl<'a, B, D> TakeLike<'a, B, GGLWECiphertext> for Scratch where B: Backend + TakeMatZnxImpl, D: DataRef, { type Output = GGLWECiphertext<&'a mut [u8]>; fn take_like(&'a mut self, template: &GGLWECiphertext) -> (Self::Output, &'a mut Self) { let (data, scratch) = B::take_mat_znx_impl( self, template.n(), template.rows(), template.data.cols_in(), template.data.cols_out(), template.size(), ); ( GGLWECiphertext { data, basek: template.basek(), k: template.k(), digits: template.digits(), }, scratch, ) } } impl TakeGGLWEExec for Scratch where Scratch: TakeVmpPMat, { fn take_gglwe_exec( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize, ) -> (GGLWECiphertextExec<&mut [u8], B>, &mut Self) { let (data, scratch) = self.take_vmp_pmat( module, rows.div_ceil(digits), rank_in, rank_out + 1, k.div_ceil(basek), ); ( GGLWECiphertextExec { data: data, basek: basek, k, digits, }, scratch, ) } } impl<'a, B, D> TakeLike<'a, B, GGLWECiphertextExec> for Scratch where B: Backend + TakeVmpPMatImpl, D: DataRef, { type Output = GGLWECiphertextExec<&'a mut [u8], B>; fn take_like(&'a mut self, template: &GGLWECiphertextExec) -> (Self::Output, &'a mut Self) { let (data, scratch) = B::take_vmp_pmat_impl( self, template.n(), template.rows(), template.data.cols_in(), template.data.cols_out(), template.size(), ); ( GGLWECiphertextExec { data, basek: template.basek(), k: template.k(), digits: template.digits(), }, scratch, ) } } impl TakeGGSW for Scratch where Scratch: TakeMatZnx, { fn take_ggsw( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank: usize, ) -> (GGSWCiphertext<&mut [u8]>, &mut Self) { let (data, scratch) = self.take_mat_znx( module, rows.div_ceil(digits), rank + 1, rank + 1, k.div_ceil(basek), ); ( GGSWCiphertext { data, basek, k, digits, }, scratch, ) } } impl<'a, B, D> TakeLike<'a, B, GGSWCiphertext> for Scratch where B: Backend + TakeMatZnxImpl, D: DataRef, { type Output = GGSWCiphertext<&'a mut [u8]>; fn take_like(&'a mut self, template: &GGSWCiphertext) -> (Self::Output, &'a mut Self) { let (data, scratch) = B::take_mat_znx_impl( self, template.n(), template.rows(), template.data.cols_in(), template.data.cols_out(), template.size(), ); ( GGSWCiphertext { data, basek: template.basek(), k: template.k(), digits: template.digits(), }, scratch, ) } } impl TakeGGSWExec for Scratch where Scratch: TakeVmpPMat, { fn take_ggsw_exec( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank: usize, ) -> (GGSWCiphertextExec<&mut [u8], B>, &mut Self) { let (data, scratch) = self.take_vmp_pmat( module, rows.div_ceil(digits), rank + 1, rank + 1, k.div_ceil(basek), ); ( GGSWCiphertextExec { data, basek, k, digits, }, scratch, ) } } impl<'a, B, D> TakeLike<'a, B, GGSWCiphertextExec> for Scratch where B: Backend + TakeVmpPMatImpl, D: DataRef, { type Output = GGSWCiphertextExec<&'a mut [u8], B>; fn take_like(&'a mut self, template: &GGSWCiphertextExec) -> (Self::Output, &'a mut Self) { let (data, scratch) = B::take_vmp_pmat_impl( self, template.n(), template.rows(), template.data.cols_in(), template.data.cols_out(), template.size(), ); ( GGSWCiphertextExec { data, basek: template.basek(), k: template.k(), digits: template.digits(), }, scratch, ) } } impl TakeGLWEPk for Scratch where Scratch: TakeVecZnx, { fn take_glwe_pk(&mut self, module: &Module, basek: usize, k: usize, rank: usize) -> (GLWEPublicKey<&mut [u8]>, &mut Self) { let (data, scratch) = self.take_vec_znx(module, rank + 1, k.div_ceil(basek)); ( GLWEPublicKey { data, k, basek, dist: Distribution::NONE, }, scratch, ) } } impl<'a, B, D> TakeLike<'a, B, GLWEPublicKey> for Scratch where B: Backend + TakeVecZnxImpl, D: DataRef, { type Output = GLWEPublicKey<&'a mut [u8]>; fn take_like(&'a mut self, template: &GLWEPublicKey) -> (Self::Output, &'a mut Self) { let (data, scratch) = B::take_vec_znx_impl(self, template.n(), template.cols(), template.size()); ( GLWEPublicKey { data, basek: template.basek(), k: template.k(), dist: template.dist, }, scratch, ) } } impl TakeGLWEPkExec for Scratch where Scratch: TakeVecZnxDft, { fn take_glwe_pk_exec( &mut self, module: &Module, basek: usize, k: usize, rank: usize, ) -> (GLWEPublicKeyExec<&mut [u8], B>, &mut Self) { let (data, scratch) = self.take_vec_znx_dft(module, rank + 1, k.div_ceil(basek)); ( GLWEPublicKeyExec { data, k, basek, dist: Distribution::NONE, }, scratch, ) } } impl<'a, B, D> TakeLike<'a, B, GLWEPublicKeyExec> for Scratch where B: Backend + TakeVecZnxDftImpl, D: DataRef, { type Output = GLWEPublicKeyExec<&'a mut [u8], B>; fn take_like(&'a mut self, template: &GLWEPublicKeyExec) -> (Self::Output, &'a mut Self) { let (data, scratch) = B::take_vec_znx_dft_impl(self, template.n(), template.cols(), template.size()); ( GLWEPublicKeyExec { data, basek: template.basek(), k: template.k(), dist: template.dist, }, scratch, ) } } impl TakeGLWESecret for Scratch where Scratch: TakeScalarZnx, { fn take_glwe_secret(&mut self, module: &Module, rank: usize) -> (GLWESecret<&mut [u8]>, &mut Self) { let (data, scratch) = self.take_scalar_znx(module, rank); ( GLWESecret { data, dist: Distribution::NONE, }, scratch, ) } } impl<'a, B, D> TakeLike<'a, B, GLWESecret> for Scratch where B: Backend + TakeScalarZnxImpl, D: DataRef, { type Output = GLWESecret<&'a mut [u8]>; fn take_like(&'a mut self, template: &GLWESecret) -> (Self::Output, &'a mut Self) { let (data, scratch) = B::take_scalar_znx_impl(self, template.n(), template.rank()); ( GLWESecret { data, dist: template.dist, }, scratch, ) } } impl TakeGLWESecretExec for Scratch where Scratch: TakeSvpPPol, { fn take_glwe_secret_exec(&mut self, module: &Module, rank: usize) -> (GLWESecretExec<&mut [u8], B>, &mut Self) { let (data, scratch) = self.take_svp_ppol(module, rank); ( GLWESecretExec { data, dist: Distribution::NONE, }, scratch, ) } } impl<'a, B, D> TakeLike<'a, B, GLWESecretExec> for Scratch where B: Backend + TakeSvpPPolImpl, D: DataRef, { type Output = GLWESecretExec<&'a mut [u8], B>; fn take_like(&'a mut self, template: &GLWESecretExec) -> (Self::Output, &'a mut Self) { let (data, scratch) = B::take_svp_ppol_impl(self, template.n(), template.rank()); ( GLWESecretExec { data, dist: template.dist, }, scratch, ) } } impl TakeGLWESwitchingKey for Scratch where Scratch: TakeMatZnx, { fn take_glwe_switching_key( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize, ) -> (GLWESwitchingKey<&mut [u8]>, &mut Self) { let (data, scratch) = self.take_gglwe(module, basek, k, rows, digits, rank_in, rank_out); ( GLWESwitchingKey { key: data, sk_in_n: 0, sk_out_n: 0, }, scratch, ) } } impl<'a, B, D> TakeLike<'a, B, GLWESwitchingKey> for Scratch where Scratch: TakeLike<'a, B, GGLWECiphertext, Output = GGLWECiphertext<&'a mut [u8]>>, B: Backend + TakeMatZnxImpl, D: DataRef, { type Output = GLWESwitchingKey<&'a mut [u8]>; fn take_like(&'a mut self, template: &GLWESwitchingKey) -> (Self::Output, &'a mut Self) { let (key, scratch) = self.take_like(&template.key); ( GLWESwitchingKey { key, sk_in_n: template.sk_in_n, sk_out_n: template.sk_out_n, }, scratch, ) } } impl TakeGLWESwitchingKeyExec for Scratch where Scratch: TakeGGLWEExec, { fn take_glwe_switching_key_exec( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize, ) -> (GLWESwitchingKeyExec<&mut [u8], B>, &mut Self) { let (data, scratch) = self.take_gglwe_exec(module, basek, k, rows, digits, rank_in, rank_out); ( GLWESwitchingKeyExec { key: data, sk_in_n: 0, sk_out_n: 0, }, scratch, ) } } impl<'a, B, D> TakeLike<'a, B, GLWESwitchingKeyExec> for Scratch where Scratch: TakeLike<'a, B, GGLWECiphertextExec, Output = GGLWECiphertextExec<&'a mut [u8], B>>, B: Backend + TakeMatZnxImpl, D: DataRef, { type Output = GLWESwitchingKeyExec<&'a mut [u8], B>; fn take_like(&'a mut self, template: &GLWESwitchingKeyExec) -> (Self::Output, &'a mut Self) { let (key, scratch) = self.take_like(&template.key); ( GLWESwitchingKeyExec { key, sk_in_n: template.sk_in_n, sk_out_n: template.sk_out_n, }, scratch, ) } } impl TakeAutomorphismKey for Scratch where Scratch: TakeMatZnx, { fn take_automorphism_key( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank: usize, ) -> (AutomorphismKey<&mut [u8]>, &mut Self) { let (data, scratch) = self.take_glwe_switching_key(module, basek, k, rows, digits, rank, rank); (AutomorphismKey { key: data, p: 0 }, scratch) } } impl<'a, B, D> TakeLike<'a, B, AutomorphismKey> for Scratch where Scratch: TakeLike<'a, B, GLWESwitchingKey, Output = GLWESwitchingKey<&'a mut [u8]>>, B: Backend + TakeMatZnxImpl, D: DataRef, { type Output = AutomorphismKey<&'a mut [u8]>; fn take_like(&'a mut self, template: &AutomorphismKey) -> (Self::Output, &'a mut Self) { let (key, scratch) = self.take_like(&template.key); (AutomorphismKey { key, p: template.p }, scratch) } } impl TakeAutomorphismKeyExec for Scratch where Scratch: TakeGLWESwitchingKeyExec, { fn take_automorphism_key_exec( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank: usize, ) -> (AutomorphismKeyExec<&mut [u8], B>, &mut Self) { let (data, scratch) = self.take_glwe_switching_key_exec(module, basek, k, rows, digits, rank, rank); (AutomorphismKeyExec { key: data, p: 0 }, scratch) } } impl<'a, B, D> TakeLike<'a, B, AutomorphismKeyExec> for Scratch where Scratch: TakeLike<'a, B, GLWESwitchingKeyExec, Output = GLWESwitchingKeyExec<&'a mut [u8], B>>, B: Backend + TakeMatZnxImpl, D: DataRef, { type Output = AutomorphismKeyExec<&'a mut [u8], B>; fn take_like(&'a mut self, template: &AutomorphismKeyExec) -> (Self::Output, &'a mut Self) { let (key, scratch) = self.take_like(&template.key); (AutomorphismKeyExec { key, p: template.p }, scratch) } } impl TakeTensorKey for Scratch where Scratch: TakeMatZnx, { fn take_tensor_key( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank: usize, ) -> (GLWETensorKey<&mut [u8]>, &mut Self) { let mut keys: Vec> = Vec::new(); let pairs: usize = (((rank + 1) * rank) >> 1).max(1); let mut scratch: &mut Scratch = self; if pairs != 0 { let (gglwe, s) = scratch.take_glwe_switching_key(module, basek, k, rows, digits, 1, rank); scratch = s; keys.push(gglwe); } for _ in 1..pairs { let (gglwe, s) = scratch.take_glwe_switching_key(module, basek, k, rows, digits, 1, rank); scratch = s; keys.push(gglwe); } (GLWETensorKey { keys }, scratch) } } impl<'a, B, D> TakeLike<'a, B, GLWETensorKey> for Scratch where Scratch: TakeLike<'a, B, GLWESwitchingKey, Output = GLWESwitchingKey<&'a mut [u8]>>, B: Backend + TakeMatZnxImpl, D: DataRef, { type Output = GLWETensorKey<&'a mut [u8]>; fn take_like(&'a mut self, template: &GLWETensorKey) -> (Self::Output, &'a mut Self) { let mut keys: Vec> = Vec::new(); let pairs: usize = template.keys.len(); let mut scratch: &mut Scratch = self; if pairs != 0 { let (gglwe, s) = scratch.take_like(template.at(0, 0)); scratch = s; keys.push(gglwe); } for _ in 1..pairs { let (gglwe, s) = scratch.take_like(template.at(0, 0)); scratch = s; keys.push(gglwe); } (GLWETensorKey { keys }, scratch) } } impl TakeTensorKeyExec for Scratch where Scratch: TakeVmpPMat, { fn take_tensor_key_exec( &mut self, module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank: usize, ) -> (GLWETensorKeyExec<&mut [u8], B>, &mut Self) { let mut keys: Vec> = Vec::new(); let pairs: usize = (((rank + 1) * rank) >> 1).max(1); let mut scratch: &mut Scratch = self; if pairs != 0 { let (gglwe, s) = scratch.take_glwe_switching_key_exec(module, basek, k, rows, digits, 1, rank); scratch = s; keys.push(gglwe); } for _ in 1..pairs { let (gglwe, s) = scratch.take_glwe_switching_key_exec(module, basek, k, rows, digits, 1, rank); scratch = s; keys.push(gglwe); } (GLWETensorKeyExec { keys }, scratch) } } impl<'a, B, D> TakeLike<'a, B, GLWETensorKeyExec> for Scratch where Scratch: TakeLike<'a, B, GLWESwitchingKeyExec, Output = GLWESwitchingKeyExec<&'a mut [u8], B>>, B: Backend + TakeMatZnxImpl, D: DataRef, { type Output = GLWETensorKeyExec<&'a mut [u8], B>; fn take_like(&'a mut self, template: &GLWETensorKeyExec) -> (Self::Output, &'a mut Self) { let mut keys: Vec> = Vec::new(); let pairs: usize = template.keys.len(); let mut scratch: &mut Scratch = self; if pairs != 0 { let (gglwe, s) = scratch.take_like(template.at(0, 0)); scratch = s; keys.push(gglwe); } for _ in 1..pairs { let (gglwe, s) = scratch.take_like(template.at(0, 0)); scratch = s; keys.push(gglwe); } (GLWETensorKeyExec { keys }, scratch) } }