arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-core/src/conversion/lwe_to_glwe.rs
poulpy-core/src/conversion/lwe_to_glwe.rsRaw
  1use poulpy_hal::{
  2    api::{
  3        ScratchAvailable, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftApply,
  4        VecZnxDftBytesOf, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft,
  5        VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes,
  6    },
  7    layouts::{Backend, DataMut, DataRef, Module, Scratch, VecZnx, ZnxView, ZnxViewMut, ZnxZero},
  8};
  9
 10use crate::layouts::{GGLWEInfos, GLWE, GLWEInfos, GLWELayout, LWE, LWEInfos, prepared::LWEToGLWESwitchingKeyPrepared};
 11
 12impl GLWE<Vec<u8>> {
 13    pub fn from_lwe_scratch_space<B: Backend, OUT, IN, KEY>(
 14        module: &Module<B>,
 15        glwe_infos: &OUT,
 16        lwe_infos: &IN,
 17        key_infos: &KEY,
 18    ) -> usize
 19    where
 20        OUT: GLWEInfos,
 21        IN: LWEInfos,
 22        KEY: GGLWEInfos,
 23        Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
 24    {
 25        let ct: usize = GLWE::bytes_of(
 26            module.n().into(),
 27            key_infos.base2k(),
 28            lwe_infos.k().max(glwe_infos.k()),
 29            1u32.into(),
 30        );
 31        let ks: usize = GLWE::keyswitch_inplace_scratch_space(module, glwe_infos, key_infos);
 32        if lwe_infos.base2k() == key_infos.base2k() {
 33            ct + ks
 34        } else {
 35            let a_conv = VecZnx::bytes_of(module.n(), 1, lwe_infos.size()) + module.vec_znx_normalize_tmp_bytes();
 36            ct + a_conv + ks
 37        }
 38    }
 39}
 40
 41impl<D: DataMut> GLWE<D> {
 42    pub fn from_lwe<DLwe, DKsk, B: Backend>(
 43        &mut self,
 44        module: &Module<B>,
 45        lwe: &LWE<DLwe>,
 46        ksk: &LWEToGLWESwitchingKeyPrepared<DKsk, B>,
 47        scratch: &mut Scratch<B>,
 48    ) where
 49        DLwe: DataRef,
 50        DKsk: DataRef,
 51        Module<B>: VecZnxDftBytesOf
 52            + VmpApplyDftToDftTmpBytes
 53            + VecZnxBigNormalizeTmpBytes
 54            + VmpApplyDftToDft<B>
 55            + VmpApplyDftToDftAdd<B>
 56            + VecZnxDftApply<B>
 57            + VecZnxIdftApplyConsume<B>
 58            + VecZnxBigAddSmallInplace<B>
 59            + VecZnxBigNormalize<B>
 60            + VecZnxNormalize<B>
 61            + VecZnxNormalizeTmpBytes,
 62        Scratch<B>: ScratchAvailable,
 63    {
 64        #[cfg(debug_assertions)]
 65        {
 66            assert_eq!(self.n(), module.n() as u32);
 67            assert_eq!(ksk.n(), module.n() as u32);
 68            assert!(lwe.n() <= module.n() as u32);
 69        }
 70
 71        let (mut glwe, scratch_1) = scratch.take_glwe_ct(&GLWELayout {
 72            n: ksk.n(),
 73            base2k: ksk.base2k(),
 74            k: lwe.k(),
 75            rank: 1u32.into(),
 76        });
 77        glwe.data.zero();
 78
 79        let n_lwe: usize = lwe.n().into();
 80
 81        if lwe.base2k() == ksk.base2k() {
 82            for i in 0..lwe.size() {
 83                let data_lwe: &[i64] = lwe.data.at(0, i);
 84                glwe.data.at_mut(0, i)[0] = data_lwe[0];
 85                glwe.data.at_mut(1, i)[..n_lwe].copy_from_slice(&data_lwe[1..]);
 86            }
 87        } else {
 88            let (mut a_conv, scratch_2) = scratch_1.take_vec_znx(module.n(), 1, lwe.size());
 89            a_conv.zero();
 90            for j in 0..lwe.size() {
 91                let data_lwe: &[i64] = lwe.data.at(0, j);
 92                a_conv.at_mut(0, j)[0] = data_lwe[0]
 93            }
 94
 95            module.vec_znx_normalize(
 96                ksk.base2k().into(),
 97                &mut glwe.data,
 98                0,
 99                lwe.base2k().into(),
100                &a_conv,
101                0,
102                scratch_2,
103            );
104
105            a_conv.zero();
106            for j in 0..lwe.size() {
107                let data_lwe: &[i64] = lwe.data.at(0, j);
108                a_conv.at_mut(0, j)[..n_lwe].copy_from_slice(&data_lwe[1..]);
109            }
110
111            module.vec_znx_normalize(
112                ksk.base2k().into(),
113                &mut glwe.data,
114                1,
115                lwe.base2k().into(),
116                &a_conv,
117                0,
118                scratch_2,
119            );
120        }
121
122        self.keyswitch(module, &glwe, &ksk.0, scratch_1);
123    }
124}