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}