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