use poulpy_hal::{ api::{TakeMatZnx, TakeScalarZnx, TakeSvpPPol, TakeVecZnx, TakeVecZnxDft, TakeVmpPMat}, layouts::{Backend, Scratch}, }; use crate::{ dist::Distribution, layouts::{ AutomorphismKey, Degree, GGLWE, GGLWEInfos, GGSW, GGSWInfos, GLWE, GLWEInfos, GLWEPlaintext, GLWEPublicKey, GLWESecret, GLWESwitchingKey, Rank, TensorKey, prepared::{ AutomorphismKeyPrepared, GGLWEPrepared, GGSWPrepared, GLWEPublicKeyPrepared, GLWESecretPrepared, GLWESwitchingKeyPrepared, TensorKeyPrepared, }, }, }; pub trait TakeGLWECt { fn take_glwe_ct(&mut self, infos: &A) -> (GLWE<&mut [u8]>, &mut Self) where A: GLWEInfos; } pub trait TakeGLWECtSlice { fn take_glwe_ct_slice(&mut self, size: usize, infos: &A) -> (Vec>, &mut Self) where A: GLWEInfos; } pub trait TakeGLWEPt { fn take_glwe_pt(&mut self, infos: &A) -> (GLWEPlaintext<&mut [u8]>, &mut Self) where A: GLWEInfos; } pub trait TakeGGLWE { fn take_gglwe(&mut self, infos: &A) -> (GGLWE<&mut [u8]>, &mut Self) where A: GGLWEInfos; } pub trait TakeGGLWEPrepared { fn take_gglwe_prepared(&mut self, infos: &A) -> (GGLWEPrepared<&mut [u8], B>, &mut Self) where A: GGLWEInfos; } pub trait TakeGGSW { fn take_ggsw(&mut self, infos: &A) -> (GGSW<&mut [u8]>, &mut Self) where A: GGSWInfos; } pub trait TakeGGSWPrepared { fn take_ggsw_prepared(&mut self, infos: &A) -> (GGSWPrepared<&mut [u8], B>, &mut Self) where A: GGSWInfos; } pub trait TakeGGSWPreparedSlice { fn take_ggsw_prepared_slice(&mut self, size: usize, infos: &A) -> (Vec>, &mut Self) where A: GGSWInfos; } pub trait TakeGLWESecret { fn take_glwe_secret(&mut self, n: Degree, rank: Rank) -> (GLWESecret<&mut [u8]>, &mut Self); } pub trait TakeGLWESecretPrepared { fn take_glwe_secret_prepared(&mut self, n: Degree, rank: Rank) -> (GLWESecretPrepared<&mut [u8], B>, &mut Self); } pub trait TakeGLWEPk { fn take_glwe_pk(&mut self, infos: &A) -> (GLWEPublicKey<&mut [u8]>, &mut Self) where A: GLWEInfos; } pub trait TakeGLWEPkPrepared { fn take_glwe_pk_prepared(&mut self, infos: &A) -> (GLWEPublicKeyPrepared<&mut [u8], B>, &mut Self) where A: GLWEInfos; } pub trait TakeGLWESwitchingKey { fn take_glwe_switching_key(&mut self, infos: &A) -> (GLWESwitchingKey<&mut [u8]>, &mut Self) where A: GGLWEInfos; } pub trait TakeGGLWESwitchingKeyPrepared { fn take_gglwe_switching_key_prepared(&mut self, infos: &A) -> (GLWESwitchingKeyPrepared<&mut [u8], B>, &mut Self) where A: GGLWEInfos; } pub trait TakeTensorKey { fn take_tensor_key(&mut self, infos: &A) -> (TensorKey<&mut [u8]>, &mut Self) where A: GGLWEInfos; } pub trait TakeGGLWETensorKeyPrepared { fn take_gglwe_tensor_key_prepared(&mut self, infos: &A) -> (TensorKeyPrepared<&mut [u8], B>, &mut Self) where A: GGLWEInfos; } pub trait TakeGGLWEAutomorphismKey { fn take_gglwe_automorphism_key(&mut self, infos: &A) -> (AutomorphismKey<&mut [u8]>, &mut Self) where A: GGLWEInfos; } pub trait TakeGGLWEAutomorphismKeyPrepared { fn take_gglwe_automorphism_key_prepared(&mut self, infos: &A) -> (AutomorphismKeyPrepared<&mut [u8], B>, &mut Self) where A: GGLWEInfos; } impl TakeGLWECt for Scratch where Scratch: TakeVecZnx, { fn take_glwe_ct(&mut self, infos: &A) -> (GLWE<&mut [u8]>, &mut Self) where A: GLWEInfos, { let (data, scratch) = self.take_vec_znx(infos.n().into(), (infos.rank() + 1).into(), infos.size()); ( GLWE { k: infos.k(), base2k: infos.base2k(), data, }, scratch, ) } } impl TakeGLWECtSlice for Scratch where Scratch: TakeVecZnx, { fn take_glwe_ct_slice(&mut self, size: usize, infos: &A) -> (Vec>, &mut Self) where A: GLWEInfos, { 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(infos); scratch = new_scratch; cts.push(ct); } (cts, scratch) } } impl TakeGLWEPt for Scratch where Scratch: TakeVecZnx, { fn take_glwe_pt(&mut self, infos: &A) -> (GLWEPlaintext<&mut [u8]>, &mut Self) where A: GLWEInfos, { let (data, scratch) = self.take_vec_znx(infos.n().into(), 1, infos.size()); ( GLWEPlaintext { k: infos.k(), base2k: infos.base2k(), data, }, scratch, ) } } impl TakeGGLWE for Scratch where Scratch: TakeMatZnx, { fn take_gglwe(&mut self, infos: &A) -> (GGLWE<&mut [u8]>, &mut Self) where A: GGLWEInfos, { let (data, scratch) = self.take_mat_znx( infos.n().into(), infos.dnum().0.div_ceil(infos.dsize().0) as usize, infos.rank_in().into(), (infos.rank_out() + 1).into(), infos.size(), ); ( GGLWE { k: infos.k(), base2k: infos.base2k(), dsize: infos.dsize(), data, }, scratch, ) } } impl TakeGGLWEPrepared for Scratch where Scratch: TakeVmpPMat, { fn take_gglwe_prepared(&mut self, infos: &A) -> (GGLWEPrepared<&mut [u8], B>, &mut Self) where A: GGLWEInfos, { let (data, scratch) = self.take_vmp_pmat( infos.n().into(), infos.dnum().into(), infos.rank_in().into(), (infos.rank_out() + 1).into(), infos.size(), ); ( GGLWEPrepared { k: infos.k(), base2k: infos.base2k(), dsize: infos.dsize(), data, }, scratch, ) } } impl TakeGGSW for Scratch where Scratch: TakeMatZnx, { fn take_ggsw(&mut self, infos: &A) -> (GGSW<&mut [u8]>, &mut Self) where A: GGSWInfos, { let (data, scratch) = self.take_mat_znx( infos.n().into(), infos.dnum().into(), (infos.rank() + 1).into(), (infos.rank() + 1).into(), infos.size(), ); ( GGSW { k: infos.k(), base2k: infos.base2k(), dsize: infos.dsize(), data, }, scratch, ) } } impl TakeGGSWPrepared for Scratch where Scratch: TakeVmpPMat, { fn take_ggsw_prepared(&mut self, infos: &A) -> (GGSWPrepared<&mut [u8], B>, &mut Self) where A: GGSWInfos, { let (data, scratch) = self.take_vmp_pmat( infos.n().into(), infos.dnum().into(), (infos.rank() + 1).into(), (infos.rank() + 1).into(), infos.size(), ); ( GGSWPrepared { k: infos.k(), base2k: infos.base2k(), dsize: infos.dsize(), data, }, scratch, ) } } impl TakeGGSWPreparedSlice for Scratch where Scratch: TakeGGSWPrepared, { fn take_ggsw_prepared_slice(&mut self, size: usize, infos: &A) -> (Vec>, &mut Self) where A: GGSWInfos, { let mut scratch: &mut Scratch = self; let mut cts: Vec> = Vec::with_capacity(size); for _ in 0..size { let (ct, new_scratch) = scratch.take_ggsw_prepared(infos); scratch = new_scratch; cts.push(ct) } (cts, scratch) } } impl TakeGLWEPk for Scratch where Scratch: TakeVecZnx, { fn take_glwe_pk(&mut self, infos: &A) -> (GLWEPublicKey<&mut [u8]>, &mut Self) where A: GLWEInfos, { let (data, scratch) = self.take_vec_znx(infos.n().into(), (infos.rank() + 1).into(), infos.size()); ( GLWEPublicKey { k: infos.k(), dist: Distribution::NONE, base2k: infos.base2k(), data, }, scratch, ) } } impl TakeGLWEPkPrepared for Scratch where Scratch: TakeVecZnxDft, { fn take_glwe_pk_prepared(&mut self, infos: &A) -> (GLWEPublicKeyPrepared<&mut [u8], B>, &mut Self) where A: GLWEInfos, { let (data, scratch) = self.take_vec_znx_dft(infos.n().into(), (infos.rank() + 1).into(), infos.size()); ( GLWEPublicKeyPrepared { k: infos.k(), dist: Distribution::NONE, base2k: infos.base2k(), data, }, scratch, ) } } impl TakeGLWESecret for Scratch where Scratch: TakeScalarZnx, { fn take_glwe_secret(&mut self, n: Degree, rank: Rank) -> (GLWESecret<&mut [u8]>, &mut Self) { let (data, scratch) = self.take_scalar_znx(n.into(), rank.into()); ( GLWESecret { data, dist: Distribution::NONE, }, scratch, ) } } impl TakeGLWESecretPrepared for Scratch where Scratch: TakeSvpPPol, { fn take_glwe_secret_prepared(&mut self, n: Degree, rank: Rank) -> (GLWESecretPrepared<&mut [u8], B>, &mut Self) { let (data, scratch) = self.take_svp_ppol(n.into(), rank.into()); ( GLWESecretPrepared { data, dist: Distribution::NONE, }, scratch, ) } } impl TakeGLWESwitchingKey for Scratch where Scratch: TakeMatZnx, { fn take_glwe_switching_key(&mut self, infos: &A) -> (GLWESwitchingKey<&mut [u8]>, &mut Self) where A: GGLWEInfos, { let (data, scratch) = self.take_gglwe(infos); ( GLWESwitchingKey { key: data, sk_in_n: 0, sk_out_n: 0, }, scratch, ) } } impl TakeGGLWESwitchingKeyPrepared for Scratch where Scratch: TakeGGLWEPrepared, { fn take_gglwe_switching_key_prepared(&mut self, infos: &A) -> (GLWESwitchingKeyPrepared<&mut [u8], B>, &mut Self) where A: GGLWEInfos, { let (data, scratch) = self.take_gglwe_prepared(infos); ( GLWESwitchingKeyPrepared { key: data, sk_in_n: 0, sk_out_n: 0, }, scratch, ) } } impl TakeGGLWEAutomorphismKey for Scratch where Scratch: TakeMatZnx, { fn take_gglwe_automorphism_key(&mut self, infos: &A) -> (AutomorphismKey<&mut [u8]>, &mut Self) where A: GGLWEInfos, { let (data, scratch) = self.take_glwe_switching_key(infos); (AutomorphismKey { key: data, p: 0 }, scratch) } } impl TakeGGLWEAutomorphismKeyPrepared for Scratch where Scratch: TakeGGLWESwitchingKeyPrepared, { fn take_gglwe_automorphism_key_prepared(&mut self, infos: &A) -> (AutomorphismKeyPrepared<&mut [u8], B>, &mut Self) where A: GGLWEInfos, { let (data, scratch) = self.take_gglwe_switching_key_prepared(infos); (AutomorphismKeyPrepared { key: data, p: 0 }, scratch) } } impl TakeTensorKey for Scratch where Scratch: TakeMatZnx, { fn take_tensor_key(&mut self, infos: &A) -> (TensorKey<&mut [u8]>, &mut Self) where A: GGLWEInfos, { assert_eq!( infos.rank_in(), infos.rank_out(), "rank_in != rank_out is not supported for GGLWETensorKey" ); let mut keys: Vec> = Vec::new(); let pairs: usize = (((infos.rank_out().0 + 1) * infos.rank_out().0) >> 1).max(1) as usize; let mut scratch: &mut Scratch = self; let mut ksk_infos: crate::layouts::GGLWECiphertextLayout = infos.gglwe_layout(); ksk_infos.rank_in = Rank(1); if pairs != 0 { let (gglwe, s) = scratch.take_glwe_switching_key(&ksk_infos); scratch = s; keys.push(gglwe); } for _ in 1..pairs { let (gglwe, s) = scratch.take_glwe_switching_key(&ksk_infos); scratch = s; keys.push(gglwe); } (TensorKey { keys }, scratch) } } impl TakeGGLWETensorKeyPrepared for Scratch where Scratch: TakeVmpPMat, { fn take_gglwe_tensor_key_prepared(&mut self, infos: &A) -> (TensorKeyPrepared<&mut [u8], B>, &mut Self) where A: GGLWEInfos, { assert_eq!( infos.rank_in(), infos.rank_out(), "rank_in != rank_out is not supported for GGLWETensorKeyPrepared" ); let mut keys: Vec> = Vec::new(); let pairs: usize = (((infos.rank_out().0 + 1) * infos.rank_out().0) >> 1).max(1) as usize; let mut scratch: &mut Scratch = self; let mut ksk_infos: crate::layouts::GGLWECiphertextLayout = infos.gglwe_layout(); ksk_infos.rank_in = Rank(1); if pairs != 0 { let (gglwe, s) = scratch.take_gglwe_switching_key_prepared(&ksk_infos); scratch = s; keys.push(gglwe); } for _ in 1..pairs { let (gglwe, s) = scratch.take_gglwe_switching_key_prepared(&ksk_infos); scratch = s; keys.push(gglwe); } (TensorKeyPrepared { keys }, scratch) } }