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