poulpy_core/conversion/
glwe_to_lwe.rs1use poulpy_hal::{
2 api::{
3 ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes,
4 VecZnxDftAllocBytes, VecZnxDftApply, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft,
5 VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes,
6 },
7 layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxView, ZnxViewMut, ZnxZero},
8};
9
10use crate::{
11 TakeGLWECt,
12 layouts::{
13 GGLWELayoutInfos, GLWECiphertext, GLWECiphertextLayout, GLWEInfos, LWECiphertext, LWEInfos, Rank,
14 prepared::GLWEToLWESwitchingKeyPrepared,
15 },
16};
17
18impl LWECiphertext<Vec<u8>> {
19 pub fn from_glwe_scratch_space<B: Backend, OUT, IN, KEY>(
20 module: &Module<B>,
21 lwe_infos: &OUT,
22 glwe_infos: &IN,
23 key_infos: &KEY,
24 ) -> usize
25 where
26 OUT: LWEInfos,
27 IN: GLWEInfos,
28 KEY: GGLWELayoutInfos,
29 Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
30 {
31 let glwe_layout: GLWECiphertextLayout = GLWECiphertextLayout {
32 n: module.n().into(),
33 base2k: lwe_infos.base2k(),
34 k: lwe_infos.k(),
35 rank: Rank(1),
36 };
37
38 GLWECiphertext::alloc_bytes_with(
39 module.n().into(),
40 lwe_infos.base2k(),
41 lwe_infos.k(),
42 1u32.into(),
43 ) + GLWECiphertext::keyswitch_scratch_space(module, &glwe_layout, glwe_infos, key_infos)
44 }
45}
46
47impl<DLwe: DataMut> LWECiphertext<DLwe> {
48 pub fn sample_extract<DGlwe: DataRef>(&mut self, a: &GLWECiphertext<DGlwe>) {
49 #[cfg(debug_assertions)]
50 {
51 assert!(self.n() <= a.n());
52 assert!(self.base2k() == a.base2k());
53 }
54
55 let min_size: usize = self.size().min(a.size());
56 let n: usize = self.n().into();
57
58 self.data.zero();
59 (0..min_size).for_each(|i| {
60 let data_lwe: &mut [i64] = self.data.at_mut(0, i);
61 data_lwe[0] = a.data.at(0, i)[0];
62 data_lwe[1..].copy_from_slice(&a.data.at(1, i)[..n]);
63 });
64 }
65
66 pub fn from_glwe<DGlwe, DKs, B: Backend>(
67 &mut self,
68 module: &Module<B>,
69 a: &GLWECiphertext<DGlwe>,
70 ks: &GLWEToLWESwitchingKeyPrepared<DKs, B>,
71 scratch: &mut Scratch<B>,
72 ) where
73 DGlwe: DataRef,
74 DKs: DataRef,
75 Module<B>: VecZnxDftAllocBytes
76 + VmpApplyDftToDftTmpBytes
77 + VecZnxBigNormalizeTmpBytes
78 + VmpApplyDftToDft<B>
79 + VmpApplyDftToDftAdd<B>
80 + VecZnxDftApply<B>
81 + VecZnxIdftApplyConsume<B>
82 + VecZnxBigAddSmallInplace<B>
83 + VecZnxBigNormalize<B>
84 + VecZnxNormalize<B>
85 + VecZnxNormalizeTmpBytes,
86 Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeGLWECt + TakeVecZnx,
87 {
88 #[cfg(debug_assertions)]
89 {
90 assert_eq!(a.n(), module.n() as u32);
91 assert_eq!(ks.n(), module.n() as u32);
92 assert!(self.n() <= module.n() as u32);
93 }
94
95 let glwe_layout: GLWECiphertextLayout = GLWECiphertextLayout {
96 n: module.n().into(),
97 base2k: self.base2k(),
98 k: self.k(),
99 rank: Rank(1),
100 };
101
102 let (mut tmp_glwe, scratch_1) = scratch.take_glwe_ct(&glwe_layout);
103 tmp_glwe.keyswitch(module, a, &ks.0, scratch_1);
104 self.sample_extract(&tmp_glwe);
105 }
106}