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(&GLWELayout {
 54            n: ksk.n(),
 55            base2k: ksk.base2k(),
 56            k: lwe.k(),
 57            rank: 1u32.into(),
 58        });
 59        glwe.data.zero();
 60
 61        let n_lwe: usize = lwe.n().into();
 62
 63        if lwe.base2k() == ksk.base2k() {
 64            for i in 0..lwe.size() {
 65                let data_lwe: &[i64] = lwe.data.at(0, i);
 66                glwe.data.at_mut(0, i)[0] = data_lwe[0];
 67                glwe.data.at_mut(1, i)[..n_lwe].copy_from_slice(&data_lwe[1..]);
 68            }
 69        } else {
 70            let (mut a_conv, scratch_2) = scratch_1.take_vec_znx(self.n(), 1, lwe.size());
 71            a_conv.zero();
 72            for j in 0..lwe.size() {
 73                let data_lwe: &[i64] = lwe.data.at(0, j);
 74                a_conv.at_mut(0, j)[0] = data_lwe[0]
 75            }
 76
 77            self.vec_znx_normalize(
 78                ksk.base2k().into(),
 79                &mut glwe.data,
 80                0,
 81                lwe.base2k().into(),
 82                &a_conv,
 83                0,
 84                scratch_2,
 85            );
 86
 87            a_conv.zero();
 88            for j in 0..lwe.size() {
 89                let data_lwe: &[i64] = lwe.data.at(0, j);
 90                a_conv.at_mut(0, j)[..n_lwe].copy_from_slice(&data_lwe[1..]);
 91            }
 92
 93            self.vec_znx_normalize(
 94                ksk.base2k().into(),
 95                &mut glwe.data,
 96                1,
 97                lwe.base2k().into(),
 98                &a_conv,
 99                0,
100                scratch_2,
101            );
102        }
103
104        self.glwe_keyswitch(res, &glwe, ksk, scratch_1);
105    }
106}
107
108impl GLWE<Vec<u8>> {
109    pub fn from_lwe_tmp_bytes<R, A, K, M, BE: Backend>(module: &M, glwe_infos: &R, lwe_infos: &A, key_infos: &K) -> usize
110    where
111        R: GLWEInfos,
112        A: LWEInfos,
113        K: GGLWEInfos,
114        M: GLWEFromLWE<BE>,
115    {
116        module.glwe_from_lwe_tmp_bytes(glwe_infos, lwe_infos, key_infos)
117    }
118}
119
120impl<D: DataMut> GLWE<D> {
121    pub fn from_lwe<A, K, M, BE: Backend>(&mut self, module: &M, lwe: &A, ksk: &K, scratch: &mut Scratch<BE>)
122    where
123        M: GLWEFromLWE<BE>,
124        A: LWEToRef,
125        K: GGLWEPreparedToRef<BE> + GGLWEInfos,
126        Scratch<BE>: ScratchTakeCore<BE>,
127    {
128        module.glwe_from_lwe(self, lwe, ksk, scratch);
129    }
130}