poulpy_core/noise/
glwe.rs

1use poulpy_hal::{
2    api::{ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxNormalizeInplace, VecZnxSubInplace},
3    layouts::{Backend, DataRef, Module, Scratch, ScratchOwned},
4};
5
6use crate::{
7    ScratchTakeCore,
8    decryption::GLWEDecrypt,
9    layouts::{GLWE, GLWEPlaintext, GLWEPlaintextToRef, GLWEToRef, LWEInfos, prepared::GLWESecretPreparedToRef},
10};
11
12impl<D: DataRef> GLWE<D> {
13    pub fn noise<M, S, P, BE: Backend>(&self, module: &M, sk_prepared: &S, pt_want: &P, scratch: &mut Scratch<BE>) -> f64
14    where
15        M: GLWENoise<BE>,
16        S: GLWESecretPreparedToRef<BE>,
17        P: GLWEPlaintextToRef,
18    {
19        module.glwe_noise(self, sk_prepared, pt_want, scratch)
20    }
21
22    pub fn assert_noise<M, BE: Backend, S, P>(&self, module: &M, sk_prepared: &S, pt_want: &P, max_noise: f64)
23    where
24        S: GLWESecretPreparedToRef<BE>,
25        P: GLWEPlaintextToRef,
26        M: GLWENoise<BE>,
27    {
28        module.glwe_assert_noise(self, sk_prepared, pt_want, max_noise);
29    }
30}
31
32pub trait GLWENoise<BE: Backend> {
33    fn glwe_noise<R, S, P>(&self, res: &R, sk_prepared: &S, pt_want: &P, scratch: &mut Scratch<BE>) -> f64
34    where
35        R: GLWEToRef,
36        S: GLWESecretPreparedToRef<BE>,
37        P: GLWEPlaintextToRef;
38
39    fn glwe_assert_noise<R, S, P>(&self, res: &R, sk_prepared: &S, pt_want: &P, max_noise: f64)
40    where
41        R: GLWEToRef,
42        S: GLWESecretPreparedToRef<BE>,
43        P: GLWEPlaintextToRef;
44}
45
46impl<BE: Backend> GLWENoise<BE> for Module<BE>
47where
48    Module<BE>: GLWEDecrypt<BE> + VecZnxSubInplace + VecZnxNormalizeInplace<BE>,
49    ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
50    Scratch<BE>: ScratchTakeCore<BE>,
51{
52    fn glwe_noise<R, S, P>(&self, res: &R, sk_prepared: &S, pt_want: &P, scratch: &mut Scratch<BE>) -> f64
53    where
54        R: GLWEToRef,
55        S: GLWESecretPreparedToRef<BE>,
56        P: GLWEPlaintextToRef,
57    {
58        let res_ref: &GLWE<&[u8]> = &res.to_ref();
59
60        let pt_want: &GLWEPlaintext<&[u8]> = &pt_want.to_ref();
61
62        let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(res_ref);
63        self.glwe_decrypt(res, &mut pt_have, sk_prepared, scratch);
64        self.vec_znx_sub_inplace(&mut pt_have.data, 0, &pt_want.data, 0);
65        self.vec_znx_normalize_inplace(res_ref.base2k().into(), &mut pt_have.data, 0, scratch);
66        pt_have.data.std(res_ref.base2k().into(), 0).log2()
67    }
68
69    fn glwe_assert_noise<R, S, P>(&self, res: &R, sk_prepared: &S, pt_want: &P, max_noise: f64)
70    where
71        R: GLWEToRef,
72        S: GLWESecretPreparedToRef<BE>,
73        P: GLWEPlaintextToRef,
74    {
75        let res: &GLWE<&[u8]> = &res.to_ref();
76        let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(self.glwe_decrypt_tmp_bytes(res));
77        let noise_have: f64 = self.glwe_noise(res, sk_prepared, pt_want, scratch.borrow());
78        assert!(noise_have <= max_noise, "{noise_have} {max_noise}");
79    }
80}