arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/keyswitching/lwe_ct.rs
core/src/keyswitching/lwe_ct.rsRaw
 1use backend::hal::{
 2    api::{ScratchAvailable, TakeVecZnx, TakeVecZnxDft, ZnxView, ZnxViewMut, ZnxZero},
 3    layouts::{Backend, DataMut, DataRef, Module, Scratch},
 4};
 5
 6use crate::{
 7    TakeGLWECt,
 8    layouts::{GLWECiphertext, Infos, LWECiphertext, prepared::LWESwitchingKeyPrepared},
 9};
10
11use crate::trait_families::GLWEKeyswitchFamily;
12
13impl LWECiphertext<Vec<u8>> {
14    pub fn keyswitch_scratch_space<B: Backend>(
15        module: &Module<B>,
16        n: usize,
17        basek: usize,
18        k_lwe_out: usize,
19        k_lwe_in: usize,
20        k_ksk: usize,
21    ) -> usize
22    where
23        Module<B>: GLWEKeyswitchFamily<B>,
24    {
25        GLWECiphertext::bytes_of(n, basek, k_lwe_out.max(k_lwe_in), 1)
26            + GLWECiphertext::keyswitch_inplace_scratch_space(module, n, basek, k_lwe_out, k_ksk, 1, 1)
27    }
28}
29
30impl<DLwe: DataMut> LWECiphertext<DLwe> {
31    pub fn keyswitch<A, DKs, B: Backend>(
32        &mut self,
33        module: &Module<B>,
34        a: &LWECiphertext<A>,
35        ksk: &LWESwitchingKeyPrepared<DKs, B>,
36        scratch: &mut Scratch<B>,
37    ) where
38        A: DataRef,
39        DKs: DataRef,
40        Module<B>: GLWEKeyswitchFamily<B>,
41        Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx,
42    {
43        #[cfg(debug_assertions)]
44        {
45            assert!(self.n() <= module.n());
46            assert!(a.n() <= module.n());
47            assert_eq!(self.basek(), a.basek());
48        }
49
50        let max_k: usize = self.k().max(a.k());
51        let basek: usize = self.basek();
52
53        let (mut glwe, scratch1) = scratch.take_glwe_ct(ksk.n(), basek, max_k, 1);
54        glwe.data.zero();
55
56        let n_lwe: usize = a.n();
57
58        (0..a.size()).for_each(|i| {
59            let data_lwe: &[i64] = a.data.at(0, i);
60            glwe.data.at_mut(0, i)[0] = data_lwe[0];
61            glwe.data.at_mut(1, i)[..n_lwe].copy_from_slice(&data_lwe[1..]);
62        });
63
64        glwe.keyswitch_inplace(module, &ksk.0, scratch1);
65
66        self.sample_extract(&glwe);
67    }
68}