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