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