poulpy_core/default/noise/
gglwe.rs1use poulpy_hal::{
2 api::{
3 ModuleN, SvpApplyDftToDftAssign, VecZnxAddScalarAssignBackend, VecZnxBigAddAssign, VecZnxBigBytesOf,
4 VecZnxBigFromSmallBackend, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftApply, VecZnxDftBytesOf,
5 VecZnxIdftApplyTmpA, VecZnxSubAssignBackend,
6 },
7 layouts::{
8 Backend, HostBackend, HostDataMut, HostDataRef, Module, ScalarZnx, ScalarZnxToBackendRef, ScratchArena, Stats, ZnxZero,
9 },
10};
11
12use crate::noise::glwe::glwe_noise_backend_inner;
13use crate::{
14 GLWENormalize,
15 api::{GGLWENoise, GLWENoise},
16 decryption::GLWEDecrypt,
17 layouts::{
18 GGLWE, GGLWEInfos, GGLWEToBackendRef, GLWEInfos, GLWEToBackendMut, GLWEToBackendRef, GLWEViewRef,
19 prepared::GLWESecretPreparedToBackendRef,
20 },
21};
22use crate::{ScratchArenaTakeCore, layouts::GLWEPlaintext};
23
24impl<D: HostDataRef> GGLWE<D> {
25 pub fn noise<M, S, BE>(
26 &self,
27 module: &M,
28 row: usize,
29 col: usize,
30 pt_want: &ScalarZnx<&[u8]>,
31 sk_prepared: &S,
32 scratch: &mut ScratchArena<'_, BE>,
33 ) -> Stats
34 where
35 GGLWE<D>: GGLWEToBackendRef<BE>,
36 S: GLWESecretPreparedToBackendRef<BE> + GLWEInfos,
37 M: GGLWENoise<BE>,
38 BE: HostBackend,
39 for<'a> BE::BufRef<'a>: HostDataRef,
40 for<'a> BE::BufMut<'a>: HostDataMut,
41 {
42 module.gglwe_noise(self, row, col, pt_want, sk_prepared, scratch)
43 }
44}
45
46impl<BE: Backend + HostBackend> GGLWENoise<BE> for Module<BE>
47where
48 Module<BE>:
49 VecZnxAddScalarAssignBackend<BE> + VecZnxSubAssignBackend<BE> + GLWENoise<BE> + GLWEDecrypt<BE> + GLWENormalize<BE>,
50 Module<BE>: ModuleN
51 + VecZnxDftBytesOf
52 + VecZnxBigBytesOf
53 + VecZnxBigFromSmallBackend<BE>
54 + VecZnxDftApply<BE>
55 + SvpApplyDftToDftAssign<BE>
56 + VecZnxIdftApplyTmpA<BE>
57 + VecZnxBigAddAssign<BE>
58 + VecZnxBigNormalize<BE>
59 + VecZnxBigNormalizeTmpBytes,
60 for<'a> BE::BufRef<'a>: HostDataRef,
61 for<'a> BE::BufMut<'a>: HostDataMut,
62{
63 fn gglwe_noise_tmp_bytes<A>(&self, infos: &A) -> usize
64 where
65 A: GGLWEInfos,
66 {
67 let lvl_0: usize = GLWEPlaintext::<Vec<u8>>::bytes_of_from_infos(infos);
68 let lvl_1: usize = self.glwe_noise_tmp_bytes(infos);
69
70 lvl_0 + lvl_1
71 }
72
73 fn gglwe_noise<R, S>(
74 &self,
75 res: &R,
76 res_row: usize,
77 res_col: usize,
78 pt_want: &ScalarZnx<&[u8]>,
79 sk_prepared: &S,
80 scratch: &mut ScratchArena<'_, BE>,
81 ) -> Stats
82 where
83 R: GGLWEToBackendRef<BE> + GGLWEInfos,
84 S: GLWESecretPreparedToBackendRef<BE> + GLWEInfos,
85 BE: HostBackend,
86 for<'a> BE::BufRef<'a>: HostDataRef,
87 for<'a> BE::BufMut<'a>: HostDataMut,
88 {
89 assert!(
90 scratch.available() >= self.gglwe_noise_tmp_bytes(res),
91 "scratch.available(): {} < GGLWENoise::gglwe_noise_tmp_bytes: {}",
92 scratch.available(),
93 self.gglwe_noise_tmp_bytes(res)
94 );
95
96 let res_backend = res.to_backend_ref();
97 let sk_backend = sk_prepared.to_backend_ref();
98 let dsize: usize = res_backend.dsize().into();
99 let (mut pt, mut scratch_1) = scratch.borrow().take_glwe_plaintext_scratch(&res_backend);
100 pt.data_mut().zero();
101 let pt_want_backend: ScalarZnx<BE::OwnedBuf> =
102 ScalarZnx::from_data(BE::from_host_bytes(pt_want.data), pt_want.n(), pt_want.cols());
103 {
104 let mut pt_backend = pt.to_backend_mut();
105 self.vec_znx_add_scalar_assign_backend(
106 &mut pt_backend.data,
107 0,
108 (dsize - 1) + res_row * dsize,
109 &<ScalarZnx<BE::OwnedBuf> as ScalarZnxToBackendRef<BE>>::to_backend_ref(&pt_want_backend),
110 res_col,
111 );
112 }
113 let res_at_backend: GLWEViewRef<'_, BE> = res_backend.at_view(res_row, res_col);
114 let pt_backend = pt.to_backend_ref();
115 glwe_noise_backend_inner(self, &res_at_backend, &pt_backend, &sk_backend, &mut scratch_1)
116 }
117}