arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-core/src/conversion/glwe_to_lwe.rs
poulpy-core/src/conversion/glwe_to_lwe.rsRaw
  1use poulpy_hal::{
  2    api::{
  3        VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftApply, VecZnxDftBytesOf,
  4        VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft, VmpApplyDftToDftAdd,
  5        VmpApplyDftToDftTmpBytes,
  6    },
  7    layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxView, ZnxViewMut, ZnxZero},
  8};
  9
 10use crate::layouts::{GGLWEInfos, GLWE, GLWEInfos, GLWELayout, LWE, LWEInfos, Rank, prepared::GLWEToLWESwitchingKeyPrepared};
 11
 12impl LWE<Vec<u8>> {
 13    pub fn from_glwe_scratch_space<B: Backend, OUT, IN, KEY>(
 14        module: &Module<B>,
 15        lwe_infos: &OUT,
 16        glwe_infos: &IN,
 17        key_infos: &KEY,
 18    ) -> usize
 19    where
 20        OUT: LWEInfos,
 21        IN: GLWEInfos,
 22        KEY: GGLWEInfos,
 23        Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
 24    {
 25        let glwe_layout: GLWELayout = GLWELayout {
 26            n: module.n().into(),
 27            base2k: lwe_infos.base2k(),
 28            k: lwe_infos.k(),
 29            rank: Rank(1),
 30        };
 31
 32        GLWE::bytes_of(
 33            module.n().into(),
 34            lwe_infos.base2k(),
 35            lwe_infos.k(),
 36            1u32.into(),
 37        ) + GLWE::keyswitch_scratch_space(module, &glwe_layout, glwe_infos, key_infos)
 38    }
 39}
 40
 41impl<DLwe: DataMut> LWE<DLwe> {
 42    pub fn sample_extract<DGlwe: DataRef>(&mut self, a: &GLWE<DGlwe>) {
 43        #[cfg(debug_assertions)]
 44        {
 45            assert!(self.n() <= a.n());
 46            assert!(self.base2k() == a.base2k());
 47        }
 48
 49        let min_size: usize = self.size().min(a.size());
 50        let n: usize = self.n().into();
 51
 52        self.data.zero();
 53        (0..min_size).for_each(|i| {
 54            let data_lwe: &mut [i64] = self.data.at_mut(0, i);
 55            data_lwe[0] = a.data.at(0, i)[0];
 56            data_lwe[1..].copy_from_slice(&a.data.at(1, i)[..n]);
 57        });
 58    }
 59
 60    pub fn from_glwe<DGlwe, DKs, B: Backend>(
 61        &mut self,
 62        module: &Module<B>,
 63        a: &GLWE<DGlwe>,
 64        ks: &GLWEToLWESwitchingKeyPrepared<DKs, B>,
 65        scratch: &mut Scratch<B>,
 66    ) where
 67        DGlwe: DataRef,
 68        DKs: DataRef,
 69        Module<B>: VecZnxDftBytesOf
 70            + VmpApplyDftToDftTmpBytes
 71            + VecZnxBigNormalizeTmpBytes
 72            + VmpApplyDftToDft<B>
 73            + VmpApplyDftToDftAdd<B>
 74            + VecZnxDftApply<B>
 75            + VecZnxIdftApplyConsume<B>
 76            + VecZnxBigAddSmallInplace<B>
 77            + VecZnxBigNormalize<B>
 78            + VecZnxNormalize<B>
 79            + VecZnxNormalizeTmpBytes,
 80        Scratch<B>:,
 81    {
 82        #[cfg(debug_assertions)]
 83        {
 84            assert_eq!(a.n(), module.n() as u32);
 85            assert_eq!(ks.n(), module.n() as u32);
 86            assert!(self.n() <= module.n() as u32);
 87        }
 88
 89        let glwe_layout: GLWELayout = GLWELayout {
 90            n: module.n().into(),
 91            base2k: self.base2k(),
 92            k: self.k(),
 93            rank: Rank(1),
 94        };
 95
 96        let (mut tmp_glwe, scratch_1) = scratch.take_glwe_ct(&glwe_layout);
 97        tmp_glwe.keyswitch(module, a, &ks.0, scratch_1);
 98        self.sample_extract(&tmp_glwe);
 99    }
100}