poulpy_core/conversion/
lwe_to_glwe.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::LWEToGLWESwitchingKeyPrepared},
12};
13
14impl GLWECiphertext<Vec<u8>> {
15    pub fn from_lwe_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::keyswitch_scratch_space(module, basek, k_glwe, k_lwe, k_ksk, 1, 1, rank)
27            + GLWECiphertext::bytes_of(module.n(), basek, k_lwe, 1)
28    }
29}
30
31impl<D: DataMut> GLWECiphertext<D> {
32    pub fn from_lwe<DLwe, DKsk, B: Backend>(
33        &mut self,
34        module: &Module<B>,
35        lwe: &LWECiphertext<DLwe>,
36        ksk: &LWEToGLWESwitchingKeyPrepared<DKsk, B>,
37        scratch: &mut Scratch<B>,
38    ) where
39        DLwe: DataRef,
40        DKsk: DataRef,
41        Module<B>: VecZnxDftAllocBytes
42            + VmpApplyDftToDftTmpBytes
43            + VecZnxBigNormalizeTmpBytes
44            + VmpApplyDftToDft<B>
45            + VmpApplyDftToDftAdd<B>
46            + DFT<B>
47            + IDFTConsume<B>
48            + VecZnxBigAddSmallInplace<B>
49            + VecZnxBigNormalize<B>,
50        Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeGLWECt,
51    {
52        #[cfg(debug_assertions)]
53        {
54            assert!(lwe.n() <= self.n());
55            assert_eq!(self.basek(), self.basek());
56        }
57
58        let (mut glwe, scratch1) = scratch.take_glwe_ct(ksk.n(), lwe.basek(), lwe.k(), 1);
59        glwe.data.zero();
60
61        let n_lwe: usize = lwe.n();
62
63        (0..lwe.size()).for_each(|i| {
64            let data_lwe: &[i64] = lwe.data.at(0, i);
65            glwe.data.at_mut(0, i)[0] = data_lwe[0];
66            glwe.data.at_mut(1, i)[..n_lwe].copy_from_slice(&data_lwe[1..]);
67        });
68
69        self.keyswitch(module, &glwe, &ksk.0, scratch1);
70    }
71}