poulpy/core/src/gglwe/layouts_exec.rs
core/src/gglwe/layouts_exec.rsRaw
1use backend::hal::{
2 api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare},
3 layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat},
4};
5
6use crate::{AutomorphismKey, GGLWECiphertext, GGLWEExecLayoutFamily, GLWESwitchingKey, GLWETensorKey, Infos};
7
8#[derive(PartialEq, Eq)]
9pub struct GGLWECiphertextExec<D: Data, B: Backend> {
10 pub(crate) data: VmpPMat<D, B>,
11 pub(crate) basek: usize,
12 pub(crate) k: usize,
13 pub(crate) digits: usize,
14}
15
16impl<B: Backend> GGLWECiphertextExec<Vec<u8>, B> {
17 pub fn alloc(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self
18 where
19 Module<B>: GGLWEExecLayoutFamily<B>,
20 {
21 let size: usize = k.div_ceil(basek);
22 debug_assert!(
23 size > digits,
24 "invalid gglwe: ceil(k/basek): {} <= digits: {}",
25 size,
26 digits
27 );
28
29 assert!(
30 rows * digits <= size,
31 "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}",
32 rows,
33 digits,
34 size
35 );
36
37 Self {
38 data: module.vmp_pmat_alloc(rows, rank_in, rank_out + 1, size),
39 basek: basek,
40 k,
41 digits,
42 }
43 }
44
45 pub fn bytes_of(
46 module: &Module<B>,
47 basek: usize,
48 k: usize,
49 rows: usize,
50 digits: usize,
51 rank_in: usize,
52 rank_out: usize,
53 ) -> usize
54 where
55 Module<B>: GGLWEExecLayoutFamily<B>,
56 {
57 let size: usize = k.div_ceil(basek);
58 debug_assert!(
59 size > digits,
60 "invalid gglwe: ceil(k/basek): {} <= digits: {}",
61 size,
62 digits
63 );
64
65 assert!(
66 rows * digits <= size,
67 "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}",
68 rows,
69 digits,
70 size
71 );
72
73 module.vmp_pmat_alloc_bytes(rows, rank_in, rank_out + 1, rows)
74 }
75}
76
77impl<D: Data, B: Backend> Infos for GGLWECiphertextExec<D, B> {
78 type Inner = VmpPMat<D, B>;
79
80 fn inner(&self) -> &Self::Inner {
81 &self.data
82 }
83
84 fn basek(&self) -> usize {
85 self.basek
86 }
87
88 fn k(&self) -> usize {
89 self.k
90 }
91}
92
93impl<D: Data, B: Backend> GGLWECiphertextExec<D, B> {
94 pub fn rank(&self) -> usize {
95 self.data.cols_out() - 1
96 }
97
98 pub fn digits(&self) -> usize {
99 self.digits
100 }
101
102 pub fn rank_in(&self) -> usize {
103 self.data.cols_in()
104 }
105
106 pub fn rank_out(&self) -> usize {
107 self.data.cols_out() - 1
108 }
109}
110
111impl<D: DataMut, B: Backend> GGLWECiphertextExec<D, B> {
112 pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGLWECiphertext<DataOther>, scratch: &mut Scratch<B>)
113 where
114 DataOther: DataRef,
115 Module<B>: GGLWEExecLayoutFamily<B>,
116 {
117 module.vmp_prepare(&mut self.data, &other.data, scratch);
118 self.basek = other.basek;
119 self.k = other.k;
120 self.digits = other.digits;
121 }
122}
123
124#[derive(PartialEq, Eq)]
125pub struct GLWESwitchingKeyExec<D: Data, B: Backend> {
126 pub(crate) key: GGLWECiphertextExec<D, B>,
127 pub(crate) sk_in_n: usize, // Degree of sk_in
128 pub(crate) sk_out_n: usize, // Degree of sk_out
129}
130
131impl<B: Backend> GLWESwitchingKeyExec<Vec<u8>, B> {
132 pub fn alloc(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self
133 where
134 Module<B>: GGLWEExecLayoutFamily<B>,
135 {
136 GLWESwitchingKeyExec::<Vec<u8>, B> {
137 key: GGLWECiphertextExec::alloc(module, basek, k, rows, digits, rank_in, rank_out),
138 sk_in_n: 0,
139 sk_out_n: 0,
140 }
141 }
142
143 pub fn bytes_of(
144 module: &Module<B>,
145 basek: usize,
146 k: usize,
147 rows: usize,
148 digits: usize,
149 rank_in: usize,
150 rank_out: usize,
151 ) -> usize
152 where
153 Module<B>: GGLWEExecLayoutFamily<B>,
154 {
155 GGLWECiphertextExec::bytes_of(module, basek, k, rows, digits, rank_in, rank_out)
156 }
157
158 pub fn from<DataOther: DataRef>(module: &Module<B>, other: &GLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) -> Self
159 where
160 Module<B>: GGLWEExecLayoutFamily<B>,
161 {
162 let mut ksk_exec: GLWESwitchingKeyExec<Vec<u8>, B> = Self::alloc(
163 module,
164 other.basek(),
165 other.k(),
166 other.rows(),
167 other.digits(),
168 other.rank_in(),
169 other.rank_out(),
170 );
171 ksk_exec.prepare(module, other, scratch);
172 ksk_exec
173 }
174}
175
176impl<D: Data, B: Backend> Infos for GLWESwitchingKeyExec<D, B> {
177 type Inner = VmpPMat<D, B>;
178
179 fn inner(&self) -> &Self::Inner {
180 self.key.inner()
181 }
182
183 fn basek(&self) -> usize {
184 self.key.basek()
185 }
186
187 fn k(&self) -> usize {
188 self.key.k()
189 }
190}
191
192impl<D: Data, B: Backend> GLWESwitchingKeyExec<D, B> {
193 pub fn rank(&self) -> usize {
194 self.key.data.cols_out() - 1
195 }
196
197 pub fn rank_in(&self) -> usize {
198 self.key.data.cols_in()
199 }
200
201 pub fn rank_out(&self) -> usize {
202 self.key.data.cols_out() - 1
203 }
204
205 pub fn digits(&self) -> usize {
206 self.key.digits()
207 }
208
209 pub fn sk_degree_in(&self) -> usize {
210 self.sk_in_n
211 }
212
213 pub fn sk_degree_out(&self) -> usize {
214 self.sk_out_n
215 }
216}
217
218impl<D: DataMut, B: Backend> GLWESwitchingKeyExec<D, B> {
219 pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>)
220 where
221 DataOther: DataRef,
222 Module<B>: GGLWEExecLayoutFamily<B>,
223 {
224 self.key.prepare(module, &other.key, scratch);
225 self.sk_in_n = other.sk_in_n;
226 self.sk_out_n = other.sk_out_n;
227 }
228}
229
230#[derive(PartialEq, Eq)]
231pub struct AutomorphismKeyExec<D: Data, B: Backend> {
232 pub(crate) key: GLWESwitchingKeyExec<D, B>,
233 pub(crate) p: i64,
234}
235
236impl<B: Backend> AutomorphismKeyExec<Vec<u8>, B> {
237 pub fn alloc(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
238 where
239 Module<B>: GGLWEExecLayoutFamily<B>,
240 {
241 AutomorphismKeyExec::<Vec<u8>, B> {
242 key: GLWESwitchingKeyExec::alloc(module, basek, k, rows, digits, rank, rank),
243 p: 0,
244 }
245 }
246
247 pub fn bytes_of(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
248 where
249 Module<B>: GGLWEExecLayoutFamily<B>,
250 {
251 GLWESwitchingKeyExec::<Vec<u8>, B>::bytes_of(module, basek, k, rows, digits, rank, rank)
252 }
253
254 pub fn from<DataOther: DataRef>(module: &Module<B>, other: &AutomorphismKey<DataOther>, scratch: &mut Scratch<B>) -> Self
255 where
256 Module<B>: GGLWEExecLayoutFamily<B>,
257 {
258 let mut atk_exec: AutomorphismKeyExec<Vec<u8>, B> = Self::alloc(
259 module,
260 other.basek(),
261 other.k(),
262 other.rows(),
263 other.digits(),
264 other.rank(),
265 );
266 atk_exec.prepare(module, other, scratch);
267 atk_exec
268 }
269}
270
271impl<D: DataMut, B: Backend> AutomorphismKeyExec<D, B> {
272 pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &AutomorphismKey<DataOther>, scratch: &mut Scratch<B>)
273 where
274 DataOther: DataRef,
275 Module<B>: GGLWEExecLayoutFamily<B>,
276 {
277 self.key.prepare(module, &other.key, scratch);
278 self.p = other.p;
279 }
280}
281
282impl<D: Data, B: Backend> Infos for AutomorphismKeyExec<D, B> {
283 type Inner = VmpPMat<D, B>;
284
285 fn inner(&self) -> &Self::Inner {
286 &self.key.inner()
287 }
288
289 fn basek(&self) -> usize {
290 self.key.basek()
291 }
292
293 fn k(&self) -> usize {
294 self.key.k()
295 }
296}
297
298impl<D: Data, B: Backend> AutomorphismKeyExec<D, B> {
299 pub fn p(&self) -> i64 {
300 self.p
301 }
302
303 pub fn digits(&self) -> usize {
304 self.key.digits()
305 }
306
307 pub fn rank(&self) -> usize {
308 self.key.rank()
309 }
310
311 pub fn rank_in(&self) -> usize {
312 self.key.rank_in()
313 }
314
315 pub fn rank_out(&self) -> usize {
316 self.key.rank_out()
317 }
318}
319
320#[derive(PartialEq, Eq)]
321pub struct GLWETensorKeyExec<D: Data, B: Backend> {
322 pub(crate) keys: Vec<GLWESwitchingKeyExec<D, B>>,
323}
324
325impl<B: Backend> GLWETensorKeyExec<Vec<u8>, B> {
326 pub fn alloc(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
327 where
328 Module<B>: GGLWEExecLayoutFamily<B>,
329 {
330 let mut keys: Vec<GLWESwitchingKeyExec<Vec<u8>, B>> = Vec::new();
331 let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
332 (0..pairs).for_each(|_| {
333 keys.push(GLWESwitchingKeyExec::alloc(
334 module, basek, k, rows, digits, 1, rank,
335 ));
336 });
337 Self { keys }
338 }
339
340 pub fn bytes_of(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
341 where
342 Module<B>: GGLWEExecLayoutFamily<B>,
343 {
344 let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
345 pairs * GLWESwitchingKeyExec::<Vec<u8>, B>::bytes_of(module, basek, k, rows, digits, 1, rank)
346 }
347}
348
349impl<D: Data, B: Backend> Infos for GLWETensorKeyExec<D, B> {
350 type Inner = VmpPMat<D, B>;
351
352 fn inner(&self) -> &Self::Inner {
353 &self.keys[0].inner()
354 }
355
356 fn basek(&self) -> usize {
357 self.keys[0].basek()
358 }
359
360 fn k(&self) -> usize {
361 self.keys[0].k()
362 }
363}
364
365impl<D: Data, B: Backend> GLWETensorKeyExec<D, B> {
366 pub fn rank(&self) -> usize {
367 self.keys[0].rank()
368 }
369
370 pub fn rank_in(&self) -> usize {
371 self.keys[0].rank_in()
372 }
373
374 pub fn rank_out(&self) -> usize {
375 self.keys[0].rank_out()
376 }
377
378 pub fn digits(&self) -> usize {
379 self.keys[0].digits()
380 }
381}
382
383impl<D: DataMut, B: Backend> GLWETensorKeyExec<D, B> {
384 // Returns a mutable reference to GLWESwitchingKey_{s}(s[i] * s[j])
385 pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GLWESwitchingKeyExec<D, B> {
386 if i > j {
387 std::mem::swap(&mut i, &mut j);
388 };
389 let rank: usize = self.rank();
390 &mut self.keys[i * rank + j - (i * (i + 1) / 2)]
391 }
392}
393
394impl<D: DataRef, B: Backend> GLWETensorKeyExec<D, B> {
395 // Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j])
396 pub fn at(&self, mut i: usize, mut j: usize) -> &GLWESwitchingKeyExec<D, B> {
397 if i > j {
398 std::mem::swap(&mut i, &mut j);
399 };
400 let rank: usize = self.rank();
401 &self.keys[i * rank + j - (i * (i + 1) / 2)]
402 }
403}
404
405impl<D: DataMut, B: Backend> GLWETensorKeyExec<D, B> {
406 pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GLWETensorKey<DataOther>, scratch: &mut Scratch<B>)
407 where
408 DataOther: DataRef,
409 Module<B>: GGLWEExecLayoutFamily<B>,
410 {
411 #[cfg(debug_assertions)]
412 {
413 assert_eq!(self.keys.len(), other.keys.len());
414 }
415 self.keys
416 .iter_mut()
417 .zip(other.keys.iter())
418 .for_each(|(a, b)| {
419 a.prepare(module, b, scratch);
420 });
421 }
422}