poulpy/core/src/conversion/glwe_to_lwe.rs
core/src/conversion/glwe_to_lwe.rsRaw
1use backend::hal::{
2 api::{ScratchAvailable, TakeVecZnx, TakeVecZnxDft, ZnxView, ZnxViewMut, ZnxZero},
3 layouts::{Backend, DataMut, DataRef, Module, Scratch},
4};
5
6use crate::{
7 TakeGLWECt,
8 layouts::{GLWECiphertext, Infos, LWECiphertext, prepared::GLWEToLWESwitchingKeyExec},
9};
10
11use crate::trait_families::GLWEKeyswitchFamily;
12
13impl LWECiphertext<Vec<u8>> {
14 pub fn from_glwe_scratch_space<B: Backend>(
15 module: &Module<B>,
16 n: usize,
17 basek: usize,
18 k_lwe: usize,
19 k_glwe: usize,
20 k_ksk: usize,
21 rank: usize,
22 ) -> usize
23 where
24 Module<B>: GLWEKeyswitchFamily<B>,
25 {
26 GLWECiphertext::bytes_of(n, basek, k_lwe, 1)
27 + GLWECiphertext::keyswitch_scratch_space(module, n, basek, k_lwe, k_glwe, k_ksk, 1, rank, 1)
28 }
29}
30
31impl<DLwe: DataMut> LWECiphertext<DLwe> {
32 pub fn sample_extract<DGlwe: DataRef>(&mut self, a: &GLWECiphertext<DGlwe>) {
33 #[cfg(debug_assertions)]
34 {
35 assert!(self.n() <= a.n());
36 }
37
38 let min_size: usize = self.size().min(a.size());
39 let n: usize = self.n();
40
41 self.data.zero();
42 (0..min_size).for_each(|i| {
43 let data_lwe: &mut [i64] = self.data.at_mut(0, i);
44 data_lwe[0] = a.data.at(0, i)[0];
45 data_lwe[1..].copy_from_slice(&a.data.at(1, i)[..n]);
46 });
47 }
48
49 pub fn from_glwe<DGlwe, DKs, B: Backend>(
50 &mut self,
51 module: &Module<B>,
52 a: &GLWECiphertext<DGlwe>,
53 ks: &GLWEToLWESwitchingKeyExec<DKs, B>,
54 scratch: &mut Scratch<B>,
55 ) where
56 DGlwe: DataRef,
57 DKs: DataRef,
58 Module<B>: GLWEKeyswitchFamily<B>,
59 Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx,
60 {
61 #[cfg(debug_assertions)]
62 {
63 assert_eq!(self.basek(), a.basek());
64 assert_eq!(a.n(), ks.n());
65 }
66 let (mut tmp_glwe, scratch1) = scratch.take_glwe_ct(a.n(), a.basek(), self.k(), 1);
67 tmp_glwe.keyswitch(module, a, &ks.0, scratch1);
68 self.sample_extract(&tmp_glwe);
69 }
70}