Skip to main content

poulpy_core/default/noise/
glwe.rs

1use 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}