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::ScratchTakeBasic,
  3    layouts::{Backend, DataMut, Module, Scratch, VecZnx, ZnxView, ZnxViewMut, ZnxZero},
  4};
  5
  6use crate::{
  7    GLWEKeyswitch, ScratchTakeCore,
  8    layouts::{GGLWEInfos, GGLWEPreparedToRef, GLWE, GLWEInfos, GLWELayout, GLWEToMut, LWE, LWEInfos, LWEToRef},
  9};
 10
 11impl<BE: Backend> GLWEFromLWE<BE> for Module<BE> where Self: GLWEKeyswitch<BE> {}
 12
 13pub trait GLWEFromLWE<BE: Backend>
 14where
 15    Self: GLWEKeyswitch<BE>,
 16{
 17    fn glwe_from_lwe_tmp_bytes<R, A, K>(&self, glwe_infos: &R, lwe_infos: &A, key_infos: &K) -> usize
 18    where
 19        R: GLWEInfos,
 20        A: LWEInfos,
 21        K: GGLWEInfos,
 22    {
 23        let ct: usize = GLWE::bytes_of(
 24            self.n().into(),
 25            key_infos.base2k(),
 26            lwe_infos.k().max(glwe_infos.k()),
 27            1u32.into(),
 28        );
 29
 30        let ks: usize = self.glwe_keyswitch_tmp_bytes(glwe_infos, glwe_infos, key_infos);
 31        if lwe_infos.base2k() == key_infos.base2k() {
 32            ct + ks
 33        } else {
 34            let a_conv = VecZnx::bytes_of(self.n(), 1, lwe_infos.size()) + self.vec_znx_normalize_tmp_bytes();
 35            ct + a_conv + ks
 36        }
 37    }
 38
 39    fn glwe_from_lwe<R, A, K>(&self, res: &mut R, lwe: &A, ksk: &K, scratch: &mut Scratch<BE>)
 40    where
 41        R: GLWEToMut,
 42        A: LWEToRef,
 43        K: GGLWEPreparedToRef<BE> + GGLWEInfos,
 44        Scratch<BE>: ScratchTakeCore<BE>,
 45    {
 46        let res: &mut GLWE<&mut [u8]> = &mut res.to_mut();
 47        let lwe: &LWE<&[u8]> = &lwe.to_ref();
 48
 49        assert_eq!(res.n(), self.n() as u32);
 50        assert_eq!(ksk.n(), self.n() as u32);
 51        assert!(lwe.n() <= self.n() as u32);
 52
 53        let (mut glwe, scratch_1) = scratch.take_glwe_ct(
 54            self,
 55            &GLWELayout {
 56                n: ksk.n(),
 57                base2k: ksk.base2k(),
 58                k: lwe.k(),
 59                rank: 1u32.into(),
 60            },
 61        );
 62        glwe.data.zero();
 63
 64        let n_lwe: usize = lwe.n().into();
 65
 66        if lwe.base2k() == ksk.base2k() {
 67            for i in 0..lwe.size() {
 68                let data_lwe: &[i64] = lwe.data.at(0, i);
 69                glwe.data.at_mut(0, i)[0] = data_lwe[0];
 70                glwe.data.at_mut(1, i)[..n_lwe].copy_from_slice(&data_lwe[1..]);
 71            }
 72        } else {
 73            let (mut a_conv, scratch_2) = scratch_1.take_vec_znx(self, 1, lwe.size());
 74            a_conv.zero();
 75            for j in 0..lwe.size() {
 76                let data_lwe: &[i64] = lwe.data.at(0, j);
 77                a_conv.at_mut(0, j)[0] = data_lwe[0]
 78            }
 79
 80            self.vec_znx_normalize(
 81                ksk.base2k().into(),
 82                &mut glwe.data,
 83                0,
 84                lwe.base2k().into(),
 85                &a_conv,
 86                0,
 87                scratch_2,
 88            );
 89
 90            a_conv.zero();
 91            for j in 0..lwe.size() {
 92                let data_lwe: &[i64] = lwe.data.at(0, j);
 93                a_conv.at_mut(0, j)[..n_lwe].copy_from_slice(&data_lwe[1..]);
 94            }
 95
 96            self.vec_znx_normalize(
 97                ksk.base2k().into(),
 98                &mut glwe.data,
 99                1,
100                lwe.base2k().into(),
101                &a_conv,
102                0,
103                scratch_2,
104            );
105        }
106
107        self.glwe_keyswitch(res, &glwe, ksk, scratch_1);
108    }
109}
110
111impl GLWE<Vec<u8>> {
112    pub fn from_lwe_tmp_bytes<R, A, K, M, BE: Backend>(module: &M, glwe_infos: &R, lwe_infos: &A, key_infos: &K) -> usize
113    where
114        R: GLWEInfos,
115        A: LWEInfos,
116        K: GGLWEInfos,
117        M: GLWEFromLWE<BE>,
118    {
119        module.glwe_from_lwe_tmp_bytes(glwe_infos, lwe_infos, key_infos)
120    }
121}
122
123impl<D: DataMut> GLWE<D> {
124    pub fn from_lwe<A, K, M, BE: Backend>(&mut self, module: &M, lwe: &A, ksk: &K, scratch: &mut Scratch<BE>)
125    where
126        M: GLWEFromLWE<BE>,
127        A: LWEToRef,
128        K: GGLWEPreparedToRef<BE> + GGLWEInfos,
129        Scratch<BE>: ScratchTakeCore<BE>,
130    {
131        module.glwe_from_lwe(self, lwe, ksk, scratch);
132    }
133}