poulpy_core/conversion/
lwe_to_glwe.rs

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