poulpy/poulpy-core/src/conversion/glwe_to_lwe.rs
poulpy-core/src/conversion/glwe_to_lwe.rsRaw
1use poulpy_hal::{
2 api::ModuleN,
3 layouts::{Backend, DataMut, Module, Scratch, ZnxView, ZnxViewMut, ZnxZero},
4};
5
6use crate::{
7 GLWEKeyswitch, GLWERotate, ScratchTakeCore,
8 layouts::{GGLWEInfos, GGLWEPreparedToRef, GLWE, GLWEInfos, GLWELayout, GLWEToRef, LWE, LWEInfos, LWEToMut, Rank},
9};
10
11pub trait LWESampleExtract
12where
13 Self: ModuleN,
14{
15 fn lwe_sample_extract<R, A>(&self, res: &mut R, a: &A)
16 where
17 R: LWEToMut,
18 A: GLWEToRef,
19 {
20 let res: &mut LWE<&mut [u8]> = &mut res.to_mut();
21 let a: &GLWE<&[u8]> = &a.to_ref();
22
23 assert!(res.n() <= a.n());
24 assert_eq!(a.n(), self.n() as u32);
25 assert!(res.base2k() == a.base2k());
26
27 let min_size: usize = res.size().min(a.size());
28 let n: usize = res.n().into();
29
30 res.data.zero();
31 (0..min_size).for_each(|i| {
32 let data_lwe: &mut [i64] = res.data.at_mut(0, i);
33 data_lwe[0] = a.data.at(0, i)[0];
34 data_lwe[1..].copy_from_slice(&a.data.at(1, i)[..n]);
35 });
36 }
37}
38
39impl<BE: Backend> LWESampleExtract for Module<BE> where Self: ModuleN {}
40impl<BE: Backend> LWEFromGLWE<BE> for Module<BE> where Self: GLWEKeyswitch<BE> + LWESampleExtract + GLWERotate<BE> {}
41
42pub trait LWEFromGLWE<BE: Backend>
43where
44 Self: GLWEKeyswitch<BE> + LWESampleExtract + GLWERotate<BE>,
45{
46 fn lwe_from_glwe_tmp_bytes<R, A, K>(&self, lwe_infos: &R, glwe_infos: &A, key_infos: &K) -> usize
47 where
48 R: LWEInfos,
49 A: GLWEInfos,
50 K: GGLWEInfos,
51 {
52 let res_infos: GLWELayout = GLWELayout {
53 n: self.n().into(),
54 base2k: lwe_infos.base2k(),
55 k: lwe_infos.k(),
56 rank: Rank(1),
57 };
58
59 GLWE::bytes_of(
60 self.n().into(),
61 lwe_infos.base2k(),
62 lwe_infos.k(),
63 1u32.into(),
64 ) + GLWE::bytes_of_from_infos(glwe_infos)
65 + self.glwe_keyswitch_tmp_bytes(&res_infos, glwe_infos, key_infos)
66 }
67
68 fn lwe_from_glwe<R, A, K>(&self, res: &mut R, a: &A, a_idx: usize, key: &K, scratch: &mut Scratch<BE>)
69 where
70 R: LWEToMut,
71 A: GLWEToRef,
72 K: GGLWEPreparedToRef<BE> + GGLWEInfos,
73 Scratch<BE>: ScratchTakeCore<BE>,
74 {
75 let res: &mut LWE<&mut [u8]> = &mut res.to_mut();
76 let a: &GLWE<&[u8]> = &a.to_ref();
77
78 assert_eq!(a.n(), self.n() as u32);
79 assert_eq!(key.n(), self.n() as u32);
80 assert!(res.n() <= self.n() as u32);
81
82 let glwe_layout: GLWELayout = GLWELayout {
83 n: self.n().into(),
84 base2k: res.base2k(),
85 k: res.k(),
86 rank: Rank(1),
87 };
88
89 let (mut tmp_glwe_rank_1, scratch_1) = scratch.take_glwe(&glwe_layout);
90
91 match a_idx {
92 0 => {
93 self.glwe_keyswitch(&mut tmp_glwe_rank_1, a, key, scratch_1);
94 }
95 _ => {
96 let (mut tmp_glwe_in, scratch_2) = scratch_1.take_glwe(a);
97 self.glwe_rotate(-(a_idx as i64), &mut tmp_glwe_in, a);
98 self.glwe_keyswitch(&mut tmp_glwe_rank_1, &tmp_glwe_in, key, scratch_2);
99 }
100 }
101
102 self.lwe_sample_extract(res, &tmp_glwe_rank_1);
103 }
104}
105
106impl LWE<Vec<u8>> {
107 pub fn from_glwe_tmp_bytes<R, A, K, M, BE: Backend>(module: &M, lwe_infos: &R, glwe_infos: &A, key_infos: &K) -> usize
108 where
109 R: LWEInfos,
110 A: GLWEInfos,
111 K: GGLWEInfos,
112 M: LWEFromGLWE<BE>,
113 {
114 module.lwe_from_glwe_tmp_bytes(lwe_infos, glwe_infos, key_infos)
115 }
116}
117
118impl<D: DataMut> LWE<D> {
119 pub fn sample_extract<A, M>(&mut self, module: &M, a: &A)
120 where
121 A: GLWEToRef,
122 M: LWESampleExtract,
123 {
124 module.lwe_sample_extract(self, a);
125 }
126
127 pub fn from_glwe<A, K, M, BE: Backend>(&mut self, module: &M, a: &A, a_idx: usize, key: &K, scratch: &mut Scratch<BE>)
128 where
129 A: GLWEToRef,
130 K: GGLWEPreparedToRef<BE> + GGLWEInfos,
131 M: LWEFromGLWE<BE>,
132 Scratch<BE>: ScratchTakeCore<BE>,
133 {
134 module.lwe_from_glwe(self, a, a_idx, key, scratch);
135 }
136}