poulpy_core/conversion/
glwe_to_lwe.rs

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