1#[macro_use]
31mod macros;
32
33mod gglwe;
34mod gglwe_to_ggsw_key;
35mod ggsw;
36mod glwe;
37mod glwe_automorphism_key;
38mod glwe_plaintext;
39mod glwe_public_key;
40mod glwe_secret;
41mod glwe_secret_tensor;
42mod glwe_switching_key;
43mod glwe_tensor;
44mod glwe_tensor_key;
45mod glwe_to_lwe_key;
46mod lwe;
47mod lwe_plaintext;
48mod lwe_secret;
49mod lwe_switching_key;
50mod lwe_to_glwe_key;
51mod scratch_views;
52
53pub mod compressed;
54pub mod prepared;
55
56pub use self::compressed::{
57 GGLWECompressed, GGLWECompressedSeed, GGLWECompressedSeedMut, GGLWECompressedToBackendMut, GGLWECompressedToBackendRef,
58 GGLWEDecompress, GGLWEToGGSWKeyCompressed, GGLWEToGGSWKeyCompressedToBackendMut, GGLWEToGGSWKeyCompressedToBackendRef,
59 GGLWEToGGSWKeyDecompress, GGSWCompressed, GGSWCompressedSeed, GGSWCompressedSeedMut, GGSWCompressedToBackendMut,
60 GGSWCompressedToBackendRef, GGSWDecompress, GLWEAutomorphismKeyCompressed, GLWEAutomorphismKeyDecompress, GLWECompressed,
61 GLWECompressedSeed, GLWECompressedSeedMut, GLWECompressedToBackendMut, GLWECompressedToBackendRef, GLWEDecompress,
62 GLWESwitchingKeyCompressed, GLWESwitchingKeyDecompress, GLWETensorKeyCompressed, GLWETensorKeyDecompress,
63 GLWEToLWESwitchingKeyCompressed, GLWEToLWESwitchingKeyDecompress, LWECompressed, LWECompressedToBackendMut,
64 LWECompressedToBackendRef, LWEDecompress, LWESwitchingKeyCompressed, LWESwitchingKeyDecompress, LWEToGLWEKeyCompressed,
65 LWEToGLWEKeyDecompress,
66};
67pub use gglwe::*;
68pub use gglwe_to_ggsw_key::*;
69pub use ggsw::*;
70pub use glwe::*;
71pub use glwe_automorphism_key::*;
72pub use glwe_plaintext::*;
73pub use glwe_public_key::*;
74pub use glwe_secret::*;
75pub use glwe_secret_tensor::*;
76pub use glwe_switching_key::*;
77pub use glwe_tensor::*;
78pub use glwe_tensor_key::*;
79pub use glwe_to_lwe_key::*;
80pub use lwe::*;
81pub use lwe_plaintext::*;
82pub use lwe_secret::*;
83pub use lwe_switching_key::*;
84pub use lwe_to_glwe_key::*;
85pub use prepared::*;
86pub use scratch_views::*;
87
88use crate::dist::Distribution;
89use poulpy_hal::layouts::{Backend, Data, MatZnx, Module, ScalarZnx, VecZnx};
90
91pub type BackendGLWE<BE> = GLWE<<BE as Backend>::OwnedBuf>;
98pub type BackendGGLWE<BE> = GGLWE<<BE as Backend>::OwnedBuf>;
99pub type BackendGGSW<BE> = GGSW<<BE as Backend>::OwnedBuf>;
100pub type BackendLWE<BE> = LWE<<BE as Backend>::OwnedBuf>;
101pub type BackendGLWESecret<BE> = GLWESecret<<BE as Backend>::OwnedBuf>;
102pub type BackendLWESecret<BE> = LWESecret<<BE as Backend>::OwnedBuf>;
103pub type BackendGLWEPlaintext<BE> = GLWEPlaintext<<BE as Backend>::OwnedBuf>;
104pub type BackendLWEPlaintext<BE> = LWEPlaintext<<BE as Backend>::OwnedBuf>;
105pub type BackendGLWEPrepared<BE> = GLWEPrepared<<BE as Backend>::OwnedBuf, BE>;
106pub type BackendGGLWEPrepared<BE> = GGLWEPrepared<<BE as Backend>::OwnedBuf, BE>;
107pub type BackendGGSWPrepared<BE> = GGSWPrepared<<BE as Backend>::OwnedBuf, BE>;
108pub type BackendGLWESecretPrepared<BE> = GLWESecretPrepared<<BE as Backend>::OwnedBuf, BE>;
109pub type BackendGLWEPublicKeyPrepared<BE> = GLWEPublicKeyPrepared<<BE as Backend>::OwnedBuf, BE>;
110pub type BackendGLWESecretTensorPrepared<BE> = GLWESecretTensorPrepared<<BE as Backend>::OwnedBuf, BE>;
111pub type BackendGLWESwitchingKeyPrepared<BE> = GLWESwitchingKeyPrepared<<BE as Backend>::OwnedBuf, BE>;
112pub type BackendGLWEAutomorphismKeyPrepared<BE> = GLWEAutomorphismKeyPrepared<<BE as Backend>::OwnedBuf, BE>;
113pub type BackendGLWETensorKeyPrepared<BE> = GLWETensorKeyPrepared<<BE as Backend>::OwnedBuf, BE>;
114pub type BackendGLWEToLWEKeyPrepared<BE> = GLWEToLWEKeyPrepared<<BE as Backend>::OwnedBuf, BE>;
115pub type BackendLWESwitchingKeyPrepared<BE> = LWESwitchingKeyPrepared<<BE as Backend>::OwnedBuf, BE>;
116pub type BackendLWEToGLWEKeyPrepared<BE> = LWEToGLWEKeyPrepared<<BE as Backend>::OwnedBuf, BE>;
117pub type BackendGGLWEToGGSWKeyPrepared<BE> = GGLWEToGGSWKeyPrepared<<BE as Backend>::OwnedBuf, BE>;
118
119pub trait GetDegree {
121 fn ring_degree(&self) -> Degree;
123}
124
125impl<B: Backend> GetDegree for Module<B> {
126 fn ring_degree(&self) -> Degree {
127 Self::n(self).into()
128 }
129}
130
131pub trait ModuleCoreAlloc {
136 type OwnedBuf: Data;
137
138 fn glwe_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWE<Self::OwnedBuf>;
139 fn glwe_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWE<Self::OwnedBuf>;
140
141 fn gglwe_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GGLWE<Self::OwnedBuf>;
142 fn gglwe_alloc(
143 &self,
144 base2k: Base2K,
145 k: TorusPrecision,
146 rank_in: Rank,
147 rank_out: Rank,
148 dnum: Dnum,
149 dsize: Dsize,
150 ) -> GGLWE<Self::OwnedBuf>;
151
152 fn ggsw_alloc_from_infos<A: GGSWInfos>(&self, infos: &A) -> GGSW<Self::OwnedBuf>;
153 fn ggsw_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> GGSW<Self::OwnedBuf>;
154
155 fn glwe_plaintext_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWEPlaintext<Self::OwnedBuf>;
156 fn glwe_plaintext_alloc(&self, base2k: Base2K, k: TorusPrecision) -> GLWEPlaintext<Self::OwnedBuf>;
157
158 fn glwe_secret_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWESecret<Self::OwnedBuf>;
159 fn glwe_secret_alloc(&self, rank: Rank) -> GLWESecret<Self::OwnedBuf>;
160
161 fn glwe_secret_tensor_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWESecretTensor<Self::OwnedBuf>;
162 fn glwe_secret_tensor_alloc(&self, rank: Rank) -> GLWESecretTensor<Self::OwnedBuf>;
163
164 fn glwe_tensor_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWETensor<Self::OwnedBuf>;
165 fn glwe_tensor_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWETensor<Self::OwnedBuf>;
166
167 fn glwe_public_key_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWEPublicKey<Self::OwnedBuf>;
168 fn glwe_public_key_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWEPublicKey<Self::OwnedBuf>;
169
170 fn glwe_switching_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWESwitchingKey<Self::OwnedBuf>;
171 fn glwe_switching_key_alloc(
172 &self,
173 base2k: Base2K,
174 k: TorusPrecision,
175 rank_in: Rank,
176 rank_out: Rank,
177 dnum: Dnum,
178 dsize: Dsize,
179 ) -> GLWESwitchingKey<Self::OwnedBuf>;
180
181 fn glwe_automorphism_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWEAutomorphismKey<Self::OwnedBuf>;
182 fn glwe_automorphism_key_alloc(
183 &self,
184 base2k: Base2K,
185 k: TorusPrecision,
186 rank: Rank,
187 dnum: Dnum,
188 dsize: Dsize,
189 ) -> GLWEAutomorphismKey<Self::OwnedBuf>;
190
191 fn glwe_tensor_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWETensorKey<Self::OwnedBuf>;
192 fn glwe_tensor_key_alloc(
193 &self,
194 base2k: Base2K,
195 k: TorusPrecision,
196 rank: Rank,
197 dnum: Dnum,
198 dsize: Dsize,
199 ) -> GLWETensorKey<Self::OwnedBuf>;
200
201 fn glwe_to_lwe_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWEToLWEKey<Self::OwnedBuf>;
202 fn glwe_to_lwe_key_alloc(&self, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum)
203 -> GLWEToLWEKey<Self::OwnedBuf>;
204
205 fn gglwe_to_ggsw_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GGLWEToGGSWKey<Self::OwnedBuf>;
206 fn gglwe_to_ggsw_key_alloc(
207 &self,
208 base2k: Base2K,
209 k: TorusPrecision,
210 rank: Rank,
211 dnum: Dnum,
212 dsize: Dsize,
213 ) -> GGLWEToGGSWKey<Self::OwnedBuf>;
214
215 fn lwe_alloc_from_infos<A: LWEInfos>(&self, infos: &A) -> LWE<Self::OwnedBuf>;
216 fn lwe_alloc(&self, n: Degree, base2k: Base2K, k: TorusPrecision) -> LWE<Self::OwnedBuf>;
217
218 fn lwe_plaintext_alloc_from_infos<A: LWEInfos>(&self, infos: &A) -> LWEPlaintext<Self::OwnedBuf>;
219 fn lwe_plaintext_alloc(&self, base2k: Base2K, k: TorusPrecision) -> LWEPlaintext<Self::OwnedBuf>;
220
221 fn lwe_secret_alloc(&self, n: Degree) -> LWESecret<Self::OwnedBuf>;
222
223 fn lwe_switching_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> LWESwitchingKey<Self::OwnedBuf>;
224 fn lwe_switching_key_alloc(
225 &self,
226 n: Degree,
227 base2k: Base2K,
228 k: TorusPrecision,
229 dnum: Dnum,
230 ) -> LWESwitchingKey<Self::OwnedBuf>;
231
232 fn lwe_to_glwe_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> LWEToGLWEKey<Self::OwnedBuf>;
233 fn lwe_to_glwe_key_alloc(
234 &self,
235 n: Degree,
236 base2k: Base2K,
237 k: TorusPrecision,
238 rank_out: Rank,
239 dnum: Dnum,
240 ) -> LWEToGLWEKey<Self::OwnedBuf>;
241}
242
243impl<B: Backend> ModuleCoreAlloc for Module<B> {
244 type OwnedBuf = B::OwnedBuf;
245
246 fn glwe_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWE<B::OwnedBuf> {
247 let size = infos.max_k().as_usize().div_ceil(infos.base2k().as_usize());
248 GLWE {
249 data: VecZnx::from_data(
250 B::alloc_zeroed_bytes(VecZnx::<Vec<u8>>::bytes_of(
251 infos.n().as_usize(),
252 (infos.rank() + 1).as_usize(),
253 size,
254 )),
255 infos.n().as_usize(),
256 (infos.rank() + 1).as_usize(),
257 size,
258 ),
259 base2k: infos.base2k(),
260 }
261 }
262 fn glwe_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWE<B::OwnedBuf> {
263 self.glwe_alloc_from_infos(&GLWELayout {
264 n: self.ring_degree(),
265 base2k,
266 k,
267 rank,
268 })
269 }
270
271 fn gglwe_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GGLWE<B::OwnedBuf> {
272 let size = infos.max_k().as_usize().div_ceil(infos.base2k().as_usize());
273 assert!(
274 size as u32 > infos.dsize().0,
275 "invalid gglwe: ceil(k/base2k): {size} <= dsize: {}",
276 infos.dsize().0
277 );
278 assert!(
279 infos.dnum().0 * infos.dsize().0 <= size as u32,
280 "invalid gglwe: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
281 infos.dnum().0,
282 infos.dsize().0,
283 );
284
285 GGLWE {
286 data: MatZnx::from_data(
287 B::alloc_zeroed_bytes(MatZnx::<Vec<u8>>::bytes_of(
288 infos.n().as_usize(),
289 infos.dnum().as_usize(),
290 infos.rank_in().as_usize(),
291 (infos.rank_out() + 1).as_usize(),
292 size,
293 )),
294 infos.n().as_usize(),
295 infos.dnum().as_usize(),
296 infos.rank_in().as_usize(),
297 (infos.rank_out() + 1).as_usize(),
298 size,
299 ),
300 base2k: infos.base2k(),
301 dsize: infos.dsize(),
302 }
303 }
304 fn gglwe_alloc(
305 &self,
306 base2k: Base2K,
307 k: TorusPrecision,
308 rank_in: Rank,
309 rank_out: Rank,
310 dnum: Dnum,
311 dsize: Dsize,
312 ) -> GGLWE<B::OwnedBuf> {
313 self.gglwe_alloc_from_infos(&GGLWELayout {
314 n: self.ring_degree(),
315 base2k,
316 k,
317 rank_in,
318 rank_out,
319 dnum,
320 dsize,
321 })
322 }
323
324 fn ggsw_alloc_from_infos<A: GGSWInfos>(&self, infos: &A) -> GGSW<B::OwnedBuf> {
325 let size = infos.max_k().as_usize().div_ceil(infos.base2k().as_usize());
326 assert!(
327 size as u32 > infos.dsize().0,
328 "invalid ggsw: ceil(k/base2k): {size} <= dsize: {}",
329 infos.dsize().0
330 );
331 assert!(
332 infos.dnum().0 * infos.dsize().0 <= size as u32,
333 "invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
334 infos.dnum().0,
335 infos.dsize().0,
336 );
337
338 GGSW {
339 data: MatZnx::from_data(
340 B::alloc_zeroed_bytes(MatZnx::<Vec<u8>>::bytes_of(
341 infos.n().as_usize(),
342 infos.dnum().as_usize(),
343 (infos.rank() + 1).as_usize(),
344 (infos.rank() + 1).as_usize(),
345 size,
346 )),
347 infos.n().as_usize(),
348 infos.dnum().as_usize(),
349 (infos.rank() + 1).as_usize(),
350 (infos.rank() + 1).as_usize(),
351 size,
352 ),
353 base2k: infos.base2k(),
354 dsize: infos.dsize(),
355 }
356 }
357 fn ggsw_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> GGSW<B::OwnedBuf> {
358 self.ggsw_alloc_from_infos(&GGSWLayout {
359 n: self.ring_degree(),
360 base2k,
361 k,
362 rank,
363 dnum,
364 dsize,
365 })
366 }
367
368 fn glwe_plaintext_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWEPlaintext<B::OwnedBuf> {
369 let size = infos.max_k().as_usize().div_ceil(infos.base2k().as_usize());
370 GLWEPlaintext {
371 data: VecZnx::from_data(
372 B::alloc_zeroed_bytes(VecZnx::<Vec<u8>>::bytes_of(infos.n().as_usize(), 1, size)),
373 infos.n().as_usize(),
374 1,
375 size,
376 ),
377 base2k: infos.base2k(),
378 }
379 }
380 fn glwe_plaintext_alloc(&self, base2k: Base2K, k: TorusPrecision) -> GLWEPlaintext<B::OwnedBuf> {
381 self.glwe_plaintext_alloc_from_infos(&GLWEPlaintextLayout {
382 n: self.ring_degree(),
383 base2k,
384 k,
385 })
386 }
387
388 fn glwe_secret_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWESecret<B::OwnedBuf> {
389 GLWESecret {
390 data: ScalarZnx::from_data(
391 B::alloc_zeroed_bytes(ScalarZnx::<Vec<u8>>::bytes_of(infos.n().as_usize(), infos.rank().as_usize())),
392 infos.n().as_usize(),
393 infos.rank().as_usize(),
394 ),
395 dist: Distribution::NONE,
396 }
397 }
398 fn glwe_secret_alloc(&self, rank: Rank) -> GLWESecret<B::OwnedBuf> {
399 self.glwe_secret_alloc_from_infos(&GLWESecretLayout {
400 n: self.ring_degree(),
401 rank,
402 })
403 }
404
405 fn glwe_secret_tensor_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWESecretTensor<B::OwnedBuf> {
406 let pairs = GLWESecretTensor::<Vec<u8>>::pairs(infos.rank().as_usize());
407 GLWESecretTensor {
408 data: ScalarZnx::from_data(
409 B::alloc_zeroed_bytes(ScalarZnx::<Vec<u8>>::bytes_of(infos.n().as_usize(), pairs)),
410 infos.n().as_usize(),
411 pairs,
412 ),
413 rank: infos.rank(),
414 dist: Distribution::NONE,
415 }
416 }
417 fn glwe_secret_tensor_alloc(&self, rank: Rank) -> GLWESecretTensor<B::OwnedBuf> {
418 self.glwe_secret_tensor_alloc_from_infos(&GLWESecretLayout {
419 n: self.ring_degree(),
420 rank,
421 })
422 }
423
424 fn glwe_tensor_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWETensor<B::OwnedBuf> {
425 let cols = infos.rank().as_usize() + 1;
426 let pairs = (((cols + 1) * cols) >> 1).max(1);
427 let size = infos.max_k().as_usize().div_ceil(infos.base2k().as_usize());
428 GLWETensor {
429 data: VecZnx::from_data(
430 B::alloc_zeroed_bytes(VecZnx::<Vec<u8>>::bytes_of(infos.n().as_usize(), pairs, size)),
431 infos.n().as_usize(),
432 pairs,
433 size,
434 ),
435 base2k: infos.base2k(),
436 rank: infos.rank(),
437 }
438 }
439 fn glwe_tensor_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWETensor<B::OwnedBuf> {
440 self.glwe_tensor_alloc_from_infos(&GLWELayout {
441 n: self.ring_degree(),
442 base2k,
443 k,
444 rank,
445 })
446 }
447
448 fn glwe_public_key_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWEPublicKey<B::OwnedBuf> {
449 GLWEPublicKey {
450 key: self.glwe_alloc_from_infos(infos),
451 dist: Distribution::NONE,
452 }
453 }
454 fn glwe_public_key_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWEPublicKey<B::OwnedBuf> {
455 self.glwe_public_key_alloc_from_infos(&GLWELayout {
456 n: self.ring_degree(),
457 base2k,
458 k,
459 rank,
460 })
461 }
462
463 fn glwe_switching_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWESwitchingKey<B::OwnedBuf> {
464 GLWESwitchingKey {
465 key: self.gglwe_alloc_from_infos(infos),
466 input_degree: Degree(0),
467 output_degree: Degree(0),
468 }
469 }
470 fn glwe_switching_key_alloc(
471 &self,
472 base2k: Base2K,
473 k: TorusPrecision,
474 rank_in: Rank,
475 rank_out: Rank,
476 dnum: Dnum,
477 dsize: Dsize,
478 ) -> GLWESwitchingKey<B::OwnedBuf> {
479 self.glwe_switching_key_alloc_from_infos(&GGLWELayout {
480 n: self.ring_degree(),
481 base2k,
482 k,
483 rank_in,
484 rank_out,
485 dnum,
486 dsize,
487 })
488 }
489
490 fn glwe_automorphism_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWEAutomorphismKey<B::OwnedBuf> {
491 GLWEAutomorphismKey {
492 key: self.gglwe_alloc_from_infos(infos),
493 p: 0,
494 }
495 }
496 fn glwe_automorphism_key_alloc(
497 &self,
498 base2k: Base2K,
499 k: TorusPrecision,
500 rank: Rank,
501 dnum: Dnum,
502 dsize: Dsize,
503 ) -> GLWEAutomorphismKey<B::OwnedBuf> {
504 self.glwe_automorphism_key_alloc_from_infos(&GGLWELayout {
505 n: self.ring_degree(),
506 base2k,
507 k,
508 rank_in: rank,
509 rank_out: rank,
510 dnum,
511 dsize,
512 })
513 }
514
515 fn glwe_tensor_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWETensorKey<B::OwnedBuf> {
516 GLWETensorKey(self.gglwe_alloc_from_infos(infos))
517 }
518 fn glwe_tensor_key_alloc(
519 &self,
520 base2k: Base2K,
521 k: TorusPrecision,
522 rank: Rank,
523 dnum: Dnum,
524 dsize: Dsize,
525 ) -> GLWETensorKey<B::OwnedBuf> {
526 let pairs = (((rank.0 + 1) * rank.0) >> 1).max(1);
527 self.glwe_tensor_key_alloc_from_infos(&GGLWELayout {
528 n: self.ring_degree(),
529 base2k,
530 k,
531 rank_in: Rank(pairs),
532 rank_out: rank,
533 dnum,
534 dsize,
535 })
536 }
537
538 fn glwe_to_lwe_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWEToLWEKey<B::OwnedBuf> {
539 assert_eq!(infos.rank_out().0, 1, "rank_out > 1 is not supported for GLWEToLWEKey");
540 assert_eq!(infos.dsize().0, 1, "dsize > 1 is not supported for GLWEToLWEKey");
541 GLWEToLWEKey(self.glwe_switching_key_alloc_from_infos(infos))
542 }
543 fn glwe_to_lwe_key_alloc(&self, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> GLWEToLWEKey<B::OwnedBuf> {
544 self.glwe_to_lwe_key_alloc_from_infos(&GGLWELayout {
545 n: self.ring_degree(),
546 base2k,
547 k,
548 rank_in,
549 rank_out: Rank(1),
550 dnum,
551 dsize: Dsize(1),
552 })
553 }
554
555 fn gglwe_to_ggsw_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GGLWEToGGSWKey<B::OwnedBuf> {
556 assert_eq!(
557 infos.rank_in(),
558 infos.rank_out(),
559 "rank_in != rank_out is not supported for GGLWEToGGSWKey"
560 );
561 GGLWEToGGSWKey {
562 keys: (0..infos.rank().as_usize())
563 .map(|_| self.gglwe_alloc_from_infos(infos))
564 .collect(),
565 }
566 }
567 fn gglwe_to_ggsw_key_alloc(
568 &self,
569 base2k: Base2K,
570 k: TorusPrecision,
571 rank: Rank,
572 dnum: Dnum,
573 dsize: Dsize,
574 ) -> GGLWEToGGSWKey<B::OwnedBuf> {
575 self.gglwe_to_ggsw_key_alloc_from_infos(&GGLWELayout {
576 n: self.ring_degree(),
577 base2k,
578 k,
579 rank_in: rank,
580 rank_out: rank,
581 dnum,
582 dsize,
583 })
584 }
585
586 fn lwe_alloc_from_infos<A: LWEInfos>(&self, infos: &A) -> LWE<B::OwnedBuf> {
587 let size = infos.max_k().as_usize().div_ceil(infos.base2k().as_usize());
588 let n = infos.n().as_usize();
589 LWE {
590 body: VecZnx::from_data(B::alloc_zeroed_bytes(VecZnx::<Vec<u8>>::bytes_of(1, 1, size)), 1, 1, size),
591 mask: VecZnx::from_data(B::alloc_zeroed_bytes(VecZnx::<Vec<u8>>::bytes_of(n, 1, size)), n, 1, size),
592 base2k: infos.base2k(),
593 }
594 }
595 fn lwe_alloc(&self, n: Degree, base2k: Base2K, k: TorusPrecision) -> LWE<B::OwnedBuf> {
596 self.lwe_alloc_from_infos(&LWELayout { n, base2k, k })
597 }
598
599 fn lwe_plaintext_alloc_from_infos<A: LWEInfos>(&self, infos: &A) -> LWEPlaintext<B::OwnedBuf> {
600 let size = infos.max_k().as_usize().div_ceil(infos.base2k().as_usize());
601 LWEPlaintext {
602 data: VecZnx::from_data(B::alloc_zeroed_bytes(VecZnx::<Vec<u8>>::bytes_of(1, 1, size)), 1, 1, size),
603 base2k: infos.base2k(),
604 }
605 }
606 fn lwe_plaintext_alloc(&self, base2k: Base2K, k: TorusPrecision) -> LWEPlaintext<B::OwnedBuf> {
607 let size = k.as_usize().div_ceil(base2k.as_usize());
608 LWEPlaintext {
609 data: VecZnx::from_data(B::alloc_zeroed_bytes(VecZnx::<Vec<u8>>::bytes_of(1, 1, size)), 1, 1, size),
610 base2k,
611 }
612 }
613
614 fn lwe_secret_alloc(&self, n: Degree) -> LWESecret<B::OwnedBuf> {
615 LWESecret {
616 data: ScalarZnx::from_data(
617 B::alloc_zeroed_bytes(ScalarZnx::<Vec<u8>>::bytes_of(n.as_usize(), 1)),
618 n.as_usize(),
619 1,
620 ),
621 dist: Distribution::NONE,
622 }
623 }
624
625 fn lwe_switching_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> LWESwitchingKey<B::OwnedBuf> {
626 assert_eq!(infos.dsize().0, 1, "dsize > 1 is not supported for LWESwitchingKey");
627 assert_eq!(infos.rank_in().0, 1, "rank_in > 1 is not supported for LWESwitchingKey");
628 assert_eq!(infos.rank_out().0, 1, "rank_out > 1 is not supported for LWESwitchingKey");
629 LWESwitchingKey(self.glwe_switching_key_alloc_from_infos(infos))
630 }
631 fn lwe_switching_key_alloc(&self, n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> LWESwitchingKey<B::OwnedBuf> {
632 self.lwe_switching_key_alloc_from_infos(&LWESwitchingKeyLayout { n, base2k, k, dnum })
633 }
634
635 fn lwe_to_glwe_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> LWEToGLWEKey<B::OwnedBuf> {
636 assert_eq!(infos.rank_in().0, 1, "rank_in > 1 is not supported for LWEToGLWEKey");
637 assert_eq!(infos.dsize().0, 1, "dsize > 1 is not supported for LWEToGLWEKey");
638 LWEToGLWEKey(self.glwe_switching_key_alloc_from_infos(infos))
639 }
640 fn lwe_to_glwe_key_alloc(
641 &self,
642 n: Degree,
643 base2k: Base2K,
644 k: TorusPrecision,
645 rank_out: Rank,
646 dnum: Dnum,
647 ) -> LWEToGLWEKey<B::OwnedBuf> {
648 self.lwe_to_glwe_key_alloc_from_infos(&GGLWELayout {
649 n,
650 base2k,
651 k,
652 rank_in: Rank(1),
653 rank_out,
654 dnum,
655 dsize: Dsize(1),
656 })
657 }
658}
659
660pub trait ModuleCoreCompressedAlloc {
665 fn glwe_compressed_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWECompressed<Vec<u8>>;
666 fn glwe_compressed_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWECompressed<Vec<u8>>;
667
668 fn lwe_compressed_alloc_from_infos<A: LWEInfos>(&self, infos: &A) -> LWECompressed<Vec<u8>>;
669 fn lwe_compressed_alloc(&self, base2k: Base2K, k: TorusPrecision) -> LWECompressed<Vec<u8>>;
670
671 fn gglwe_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GGLWECompressed<Vec<u8>>;
672 fn gglwe_compressed_alloc(
673 &self,
674 base2k: Base2K,
675 k: TorusPrecision,
676 rank_in: Rank,
677 rank_out: Rank,
678 dnum: Dnum,
679 dsize: Dsize,
680 ) -> GGLWECompressed<Vec<u8>>;
681
682 fn ggsw_compressed_alloc_from_infos<A: GGSWInfos>(&self, infos: &A) -> GGSWCompressed<Vec<u8>>;
683 fn ggsw_compressed_alloc(
684 &self,
685 base2k: Base2K,
686 k: TorusPrecision,
687 rank: Rank,
688 dnum: Dnum,
689 dsize: Dsize,
690 ) -> GGSWCompressed<Vec<u8>>;
691
692 fn glwe_switching_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWESwitchingKeyCompressed<Vec<u8>>;
693 fn glwe_switching_key_compressed_alloc(
694 &self,
695 base2k: Base2K,
696 k: TorusPrecision,
697 rank_in: Rank,
698 rank_out: Rank,
699 dnum: Dnum,
700 dsize: Dsize,
701 ) -> GLWESwitchingKeyCompressed<Vec<u8>>;
702
703 fn glwe_automorphism_key_compressed_alloc_from_infos<A: GGLWEInfos>(
704 &self,
705 infos: &A,
706 ) -> GLWEAutomorphismKeyCompressed<Vec<u8>>;
707 fn glwe_automorphism_key_compressed_alloc(
708 &self,
709 base2k: Base2K,
710 k: TorusPrecision,
711 rank: Rank,
712 dnum: Dnum,
713 dsize: Dsize,
714 ) -> GLWEAutomorphismKeyCompressed<Vec<u8>>;
715
716 fn glwe_tensor_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWETensorKeyCompressed<Vec<u8>>;
717 fn glwe_tensor_key_compressed_alloc(
718 &self,
719 base2k: Base2K,
720 k: TorusPrecision,
721 rank: Rank,
722 dnum: Dnum,
723 dsize: Dsize,
724 ) -> GLWETensorKeyCompressed<Vec<u8>>;
725
726 fn glwe_to_lwe_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWEToLWESwitchingKeyCompressed<Vec<u8>>;
727 fn glwe_to_lwe_key_compressed_alloc(
728 &self,
729 base2k: Base2K,
730 k: TorusPrecision,
731 rank_in: Rank,
732 dnum: Dnum,
733 ) -> GLWEToLWESwitchingKeyCompressed<Vec<u8>>;
734
735 fn lwe_to_glwe_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> LWEToGLWEKeyCompressed<Vec<u8>>;
736 fn lwe_to_glwe_key_compressed_alloc(
737 &self,
738 n: Degree,
739 base2k: Base2K,
740 k: TorusPrecision,
741 rank_out: Rank,
742 dnum: Dnum,
743 ) -> LWEToGLWEKeyCompressed<Vec<u8>>;
744
745 fn lwe_switching_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> LWESwitchingKeyCompressed<Vec<u8>>;
746 fn lwe_switching_key_compressed_alloc(
747 &self,
748 n: Degree,
749 base2k: Base2K,
750 k: TorusPrecision,
751 dnum: Dnum,
752 ) -> LWESwitchingKeyCompressed<Vec<u8>>;
753
754 fn gglwe_to_ggsw_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GGLWEToGGSWKeyCompressed<Vec<u8>>;
755 fn gglwe_to_ggsw_key_compressed_alloc(
756 &self,
757 base2k: Base2K,
758 k: TorusPrecision,
759 rank: Rank,
760 dnum: Dnum,
761 dsize: Dsize,
762 ) -> GGLWEToGGSWKeyCompressed<Vec<u8>>;
763}
764
765impl<B: Backend> ModuleCoreCompressedAlloc for Module<B> {
766 fn glwe_compressed_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWECompressed<Vec<u8>> {
767 GLWECompressed::alloc_from_infos(infos)
768 }
769 fn glwe_compressed_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWECompressed<Vec<u8>> {
770 GLWECompressed::alloc(self.ring_degree(), base2k, k, rank)
771 }
772
773 fn lwe_compressed_alloc_from_infos<A: LWEInfos>(&self, infos: &A) -> LWECompressed<Vec<u8>> {
774 LWECompressed::alloc_from_infos(infos)
775 }
776 fn lwe_compressed_alloc(&self, base2k: Base2K, k: TorusPrecision) -> LWECompressed<Vec<u8>> {
777 LWECompressed::alloc(base2k, k)
778 }
779
780 fn gglwe_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GGLWECompressed<Vec<u8>> {
781 GGLWECompressed::alloc_from_infos(infos)
782 }
783 fn gglwe_compressed_alloc(
784 &self,
785 base2k: Base2K,
786 k: TorusPrecision,
787 rank_in: Rank,
788 rank_out: Rank,
789 dnum: Dnum,
790 dsize: Dsize,
791 ) -> GGLWECompressed<Vec<u8>> {
792 GGLWECompressed::alloc(self.ring_degree(), base2k, k, rank_in, rank_out, dnum, dsize)
793 }
794
795 fn ggsw_compressed_alloc_from_infos<A: GGSWInfos>(&self, infos: &A) -> GGSWCompressed<Vec<u8>> {
796 GGSWCompressed::alloc_from_infos(infos)
797 }
798 fn ggsw_compressed_alloc(
799 &self,
800 base2k: Base2K,
801 k: TorusPrecision,
802 rank: Rank,
803 dnum: Dnum,
804 dsize: Dsize,
805 ) -> GGSWCompressed<Vec<u8>> {
806 GGSWCompressed::alloc(self.ring_degree(), base2k, k, rank, dnum, dsize)
807 }
808
809 fn glwe_switching_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWESwitchingKeyCompressed<Vec<u8>> {
810 GLWESwitchingKeyCompressed::alloc_from_infos(infos)
811 }
812 fn glwe_switching_key_compressed_alloc(
813 &self,
814 base2k: Base2K,
815 k: TorusPrecision,
816 rank_in: Rank,
817 rank_out: Rank,
818 dnum: Dnum,
819 dsize: Dsize,
820 ) -> GLWESwitchingKeyCompressed<Vec<u8>> {
821 GLWESwitchingKeyCompressed::alloc(self.ring_degree(), base2k, k, rank_in, rank_out, dnum, dsize)
822 }
823
824 fn glwe_automorphism_key_compressed_alloc_from_infos<A: GGLWEInfos>(
825 &self,
826 infos: &A,
827 ) -> GLWEAutomorphismKeyCompressed<Vec<u8>> {
828 GLWEAutomorphismKeyCompressed::alloc_from_infos(infos)
829 }
830 fn glwe_automorphism_key_compressed_alloc(
831 &self,
832 base2k: Base2K,
833 k: TorusPrecision,
834 rank: Rank,
835 dnum: Dnum,
836 dsize: Dsize,
837 ) -> GLWEAutomorphismKeyCompressed<Vec<u8>> {
838 GLWEAutomorphismKeyCompressed::alloc(self.ring_degree(), base2k, k, rank, dnum, dsize)
839 }
840
841 fn glwe_tensor_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWETensorKeyCompressed<Vec<u8>> {
842 GLWETensorKeyCompressed::alloc_from_infos(infos)
843 }
844 fn glwe_tensor_key_compressed_alloc(
845 &self,
846 base2k: Base2K,
847 k: TorusPrecision,
848 rank: Rank,
849 dnum: Dnum,
850 dsize: Dsize,
851 ) -> GLWETensorKeyCompressed<Vec<u8>> {
852 GLWETensorKeyCompressed::alloc(self.ring_degree(), base2k, k, rank, dnum, dsize)
853 }
854
855 fn glwe_to_lwe_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWEToLWESwitchingKeyCompressed<Vec<u8>> {
856 GLWEToLWESwitchingKeyCompressed::alloc_from_infos(infos)
857 }
858 fn glwe_to_lwe_key_compressed_alloc(
859 &self,
860 base2k: Base2K,
861 k: TorusPrecision,
862 rank_in: Rank,
863 dnum: Dnum,
864 ) -> GLWEToLWESwitchingKeyCompressed<Vec<u8>> {
865 GLWEToLWESwitchingKeyCompressed::alloc(self.ring_degree(), base2k, k, rank_in, dnum)
866 }
867
868 fn lwe_to_glwe_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> LWEToGLWEKeyCompressed<Vec<u8>> {
869 LWEToGLWEKeyCompressed::alloc_from_infos(infos)
870 }
871 fn lwe_to_glwe_key_compressed_alloc(
872 &self,
873 n: Degree,
874 base2k: Base2K,
875 k: TorusPrecision,
876 rank_out: Rank,
877 dnum: Dnum,
878 ) -> LWEToGLWEKeyCompressed<Vec<u8>> {
879 LWEToGLWEKeyCompressed::alloc(n, base2k, k, rank_out, dnum)
880 }
881
882 fn lwe_switching_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> LWESwitchingKeyCompressed<Vec<u8>> {
883 LWESwitchingKeyCompressed::alloc_from_infos(infos)
884 }
885 fn lwe_switching_key_compressed_alloc(
886 &self,
887 n: Degree,
888 base2k: Base2K,
889 k: TorusPrecision,
890 dnum: Dnum,
891 ) -> LWESwitchingKeyCompressed<Vec<u8>> {
892 LWESwitchingKeyCompressed::alloc(n, base2k, k, dnum)
893 }
894
895 fn gglwe_to_ggsw_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GGLWEToGGSWKeyCompressed<Vec<u8>> {
896 GGLWEToGGSWKeyCompressed::alloc_from_infos(infos)
897 }
898 fn gglwe_to_ggsw_key_compressed_alloc(
899 &self,
900 base2k: Base2K,
901 k: TorusPrecision,
902 rank: Rank,
903 dnum: Dnum,
904 dsize: Dsize,
905 ) -> GGLWEToGGSWKeyCompressed<Vec<u8>> {
906 GGLWEToGGSWKeyCompressed::alloc(self.ring_degree(), base2k, k, rank, dnum, dsize)
907 }
908}
909
910macro_rules! newtype_u32 {
913 ($(#[$meta:meta])* $name:ident) => {
914 $(#[$meta])*
915 #[repr(transparent)]
916 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
917 pub struct $name(pub u32);
918
919 impl From<$name> for u32 {
921 #[inline]
922 fn from(v: $name) -> u32 {
923 v.0
924 }
925 }
926 impl From<$name> for usize {
927 #[inline]
928 fn from(v: $name) -> usize {
929 v.0 as usize
930 }
931 }
932
933 impl From<u32> for $name {
934 #[inline]
935 fn from(v: u32) -> $name {
936 $name(v)
937 }
938 }
939 impl From<usize> for $name {
940 #[inline]
941 fn from(v: usize) -> $name {
942 debug_assert!(v <= u32::MAX as usize, "{} overflow: {v} > u32::MAX", stringify!($name));
943 $name(v as u32)
944 }
945 }
946
947 impl ::core::fmt::Display for $name {
949 #[inline]
950 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
951 write!(f, "{}", self.0)
952 }
953 }
954
955 impl ::core::ops::Add for $name {
957 type Output = $name;
958 #[inline]
959 fn add(self, rhs: $name) -> $name {
960 $name(self.0.saturating_add(rhs.0))
961 }
962 }
963 impl ::core::ops::Sub for $name {
964 type Output = $name;
965 #[inline]
966 fn sub(self, rhs: $name) -> $name {
967 $name(self.0.saturating_sub(rhs.0))
968 }
969 }
970 impl ::core::ops::Mul for $name {
971 type Output = $name;
972 #[inline]
973 fn mul(self, rhs: $name) -> $name {
974 $name(self.0.saturating_mul(rhs.0))
975 }
976 }
977
978 impl ::core::ops::Add<u32> for $name {
980 type Output = $name;
981 #[inline]
982 fn add(self, rhs: u32) -> $name {
983 $name(self.0.saturating_add(rhs))
984 }
985 }
986 impl ::core::ops::Sub<u32> for $name {
987 type Output = $name;
988 #[inline]
989 fn sub(self, rhs: u32) -> $name {
990 $name(self.0.saturating_sub(rhs))
991 }
992 }
993 impl ::core::ops::Mul<u32> for $name {
994 type Output = $name;
995 #[inline]
996 fn mul(self, rhs: u32) -> $name {
997 $name(self.0.saturating_mul(rhs))
998 }
999 }
1000
1001 impl $name {
1002 #[inline]
1003 pub const fn as_u32(self) -> u32 {
1004 self.0
1005 }
1006 #[inline]
1007 pub const fn as_usize(self) -> usize {
1008 self.0 as usize
1009 }
1010
1011 #[inline]
1012 pub fn div_ceil<T: Into<u32>>(self, rhs: T) -> u32 {
1013 self.0.div_ceil(rhs.into())
1014 }
1015 }
1016
1017 impl ::core::ops::Add<$name> for u32 {
1019 type Output = $name;
1020 #[inline]
1021 fn add(self, rhs: $name) -> $name {
1022 $name(self.saturating_add(rhs.0))
1023 }
1024 }
1025 impl ::core::ops::Sub<$name> for u32 {
1026 type Output = $name;
1027 #[inline]
1028 fn sub(self, rhs: $name) -> $name {
1029 $name(self.saturating_sub(rhs.0))
1030 }
1031 }
1032 impl ::core::ops::Mul<$name> for u32 {
1033 type Output = $name;
1034 #[inline]
1035 fn mul(self, rhs: $name) -> $name {
1036 $name(self.saturating_mul(rhs.0))
1037 }
1038 }
1039
1040 impl ::core::cmp::PartialEq<u32> for $name {
1042 #[inline]
1043 fn eq(&self, other: &u32) -> bool {
1044 self.0 == *other
1045 }
1046 }
1047 impl ::core::cmp::PartialEq<$name> for u32 {
1048 #[inline]
1049 fn eq(&self, other: &$name) -> bool {
1050 *self == other.0
1051 }
1052 }
1053
1054 impl ::core::cmp::PartialOrd<u32> for $name {
1055 #[inline]
1056 fn partial_cmp(&self, other: &u32) -> Option<::core::cmp::Ordering> {
1057 self.0.partial_cmp(other)
1058 }
1059 }
1060 impl ::core::cmp::PartialOrd<$name> for u32 {
1061 #[inline]
1062 fn partial_cmp(&self, other: &$name) -> Option<::core::cmp::Ordering> {
1063 self.partial_cmp(&other.0)
1064 }
1065 }
1066 };
1067}
1068
1069newtype_u32!(
1070 Degree
1074);
1075
1076newtype_u32!(
1077 TorusPrecision
1082);
1083
1084newtype_u32!(
1085 Base2K
1093);
1094
1095newtype_u32!(
1096 Dnum
1101);
1102
1103newtype_u32!(
1104 Rank
1110);
1111
1112newtype_u32!(
1113 Dsize
1117);
1118
1119impl Degree {
1120 pub fn log2(&self) -> usize {
1122 debug_assert!(
1123 self.0 > 0 && self.0.is_power_of_two(),
1124 "Degree::log2 requires a positive power of two, got {}",
1125 self.0
1126 );
1127 self.0.trailing_zeros() as usize
1128 }
1129}