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