poulpy_core/conversion/
glwe_to_lwe.rs

1use poulpy_hal::{
2    api::{
3        DFT, IDFTConsume, ScratchAvailable, TakeVecZnxDft, VecZnxBigAddSmallInplace, VecZnxBigNormalize,
4        VecZnxBigNormalizeTmpBytes, VecZnxDftAllocBytes, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes,
5    },
6    layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxView, ZnxViewMut, ZnxZero},
7};
8
9use crate::{
10    TakeGLWECt,
11    layouts::{GLWECiphertext, Infos, LWECiphertext, prepared::GLWEToLWESwitchingKeyPrepared},
12};
13
14impl LWECiphertext<Vec<u8>> {
15    pub fn from_glwe_scratch_space<B: Backend>(
16        module: &Module<B>,
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>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes,
25    {
26        GLWECiphertext::bytes_of(module.n(), basek, k_lwe, 1)
27            + GLWECiphertext::keyswitch_scratch_space(module, 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: &GLWEToLWESwitchingKeyPrepared<DKs, B>,
54        scratch: &mut Scratch<B>,
55    ) where
56        DGlwe: DataRef,
57        DKs: DataRef,
58        Module<B>: VecZnxDftAllocBytes
59            + VmpApplyDftToDftTmpBytes
60            + VecZnxBigNormalizeTmpBytes
61            + VmpApplyDftToDft<B>
62            + VmpApplyDftToDftAdd<B>
63            + DFT<B>
64            + IDFTConsume<B>
65            + VecZnxBigAddSmallInplace<B>
66            + VecZnxBigNormalize<B>,
67        Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeGLWECt,
68    {
69        #[cfg(debug_assertions)]
70        {
71            assert_eq!(self.basek(), a.basek());
72            assert_eq!(a.n(), ks.n());
73        }
74        let (mut tmp_glwe, scratch1) = scratch.take_glwe_ct(a.n(), a.basek(), self.k(), 1);
75        tmp_glwe.keyswitch(module, a, &ks.0, scratch1);
76        self.sample_extract(&tmp_glwe);
77    }
78}