poulpy_core/default/noise/
glwe.rs1use poulpy_hal::{
2 api::{
3 ModuleN, SvpApplyDftToDftAssign, VecZnxBigAddAssign, VecZnxBigBytesOf, VecZnxBigFromSmallBackend, VecZnxBigNormalize,
4 VecZnxBigNormalizeTmpBytes, VecZnxDftApply, VecZnxDftBytesOf, VecZnxIdftApplyTmpA, VecZnxSubAssignBackend,
5 },
6 layouts::{Backend, HostBackend, HostDataMut, Module, ScratchArena, Stats},
7};
8
9use crate::{
10 GLWENormalize, ScratchArenaTakeCore,
11 api::GLWENoise,
12 decryption::{GLWEDecrypt, glwe_decrypt_backend_inner},
13 layouts::{
14 GLWEBackendRef, GLWEInfos, GLWEPlaintext, GLWEToBackendMut, GLWEToBackendRef, LWEInfos,
15 prepared::{GLWESecretPreparedBackendRef, GLWESecretPreparedToBackendRef},
16 },
17};
18
19pub(crate) fn glwe_noise_backend_inner<M, BE>(
20 module: &M,
21 res_backend: &GLWEBackendRef<'_, BE>,
22 pt_want_backend: &GLWEBackendRef<'_, BE>,
23 sk_backend: &GLWESecretPreparedBackendRef<'_, BE>,
24 scratch: &mut ScratchArena<'_, BE>,
25) -> Stats
26where
27 M: GLWENoise<BE>
28 + GLWEDecrypt<BE>
29 + GLWENormalize<BE>
30 + VecZnxSubAssignBackend<BE>
31 + ModuleN
32 + VecZnxDftBytesOf
33 + VecZnxBigBytesOf
34 + VecZnxBigFromSmallBackend<BE>
35 + VecZnxDftApply<BE>
36 + SvpApplyDftToDftAssign<BE>
37 + VecZnxIdftApplyTmpA<BE>
38 + VecZnxBigAddAssign<BE>
39 + VecZnxBigNormalize<BE>
40 + VecZnxBigNormalizeTmpBytes,
41 BE: HostBackend,
42 for<'a> BE::BufMut<'a>: HostDataMut,
43{
44 assert!(
45 scratch.available() >= module.glwe_noise_tmp_bytes(res_backend),
46 "scratch.available(): {} < GLWENoise::glwe_noise_tmp_bytes: {}",
47 scratch.available(),
48 module.glwe_noise_tmp_bytes(res_backend)
49 );
50
51 let (mut pt_have, mut scratch_1) = scratch.borrow().take_glwe_plaintext_scratch(res_backend);
52 {
53 let mut pt_have_backend = pt_have.to_backend_mut();
54 glwe_decrypt_backend_inner(module, res_backend, &mut pt_have_backend, sk_backend, &mut scratch_1);
55 }
56 {
57 let mut pt_have_backend = pt_have.to_backend_mut();
58 module.vec_znx_sub_assign_backend(&mut pt_have_backend.data, 0, &pt_want_backend.data, 0);
59 }
60 let pt_base2k = pt_have.base2k();
61 module.glwe_normalize_assign(&mut pt_have, &mut scratch_1);
62 pt_have.data.stats(pt_base2k.into(), 0)
63}
64
65impl<BE: Backend + HostBackend> GLWENoise<BE> for Module<BE>
66where
67 Module<BE>: GLWEDecrypt<BE>
68 + GLWENormalize<BE>
69 + VecZnxSubAssignBackend<BE>
70 + ModuleN
71 + VecZnxDftBytesOf
72 + VecZnxBigBytesOf
73 + VecZnxBigFromSmallBackend<BE>
74 + VecZnxDftApply<BE>
75 + SvpApplyDftToDftAssign<BE>
76 + VecZnxIdftApplyTmpA<BE>
77 + VecZnxBigAddAssign<BE>
78 + VecZnxBigNormalize<BE>
79 + VecZnxBigNormalizeTmpBytes,
80 for<'a> BE::BufMut<'a>: HostDataMut,
81{
82 fn glwe_noise_tmp_bytes<A>(&self, infos: &A) -> usize
83 where
84 A: GLWEInfos,
85 {
86 let lvl_0: usize = GLWEPlaintext::<Vec<u8>>::bytes_of_from_infos(infos);
87 let lvl_1: usize = self.glwe_normalize_tmp_bytes().max(self.glwe_decrypt_tmp_bytes(infos));
88
89 lvl_0 + lvl_1
90 }
91
92 fn glwe_noise<R, P, S>(&self, res: &R, pt_want: &P, sk_prepared: &S, scratch: &mut ScratchArena<'_, BE>) -> Stats
93 where
94 R: GLWEToBackendRef<BE> + GLWEInfos,
95 P: GLWEToBackendRef<BE>,
96 S: GLWESecretPreparedToBackendRef<BE> + GLWEInfos,
97 BE: HostBackend,
98 for<'a> BE::BufMut<'a>: HostDataMut,
99 {
100 let res_backend = res.to_backend_ref();
101 let pt_want_backend = pt_want.to_backend_ref();
102 let sk_backend = sk_prepared.to_backend_ref();
103 glwe_noise_backend_inner(self, &res_backend, &pt_want_backend, &sk_backend, scratch)
104 }
105}