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