poulpy/core/src/gglwe/tests/generics_tensor_key.rs
core/src/gglwe/tests/generics_tensor_key.rsRaw
1use backend::hal::{
2 api::{
3 ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxBigAlloc, VecZnxCopy, VecZnxDftAlloc, VecZnxStd,
4 VecZnxSubScalarInplace, VecZnxSwithcDegree,
5 },
6 layouts::{Backend, Module, ScratchOwned, VecZnxDft},
7 oep::{
8 ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
9 TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl,
10 },
11};
12use sampling::source::Source;
13
14use crate::{
15 GGLWEEncryptSkFamily, GGLWEExecLayoutFamily, GLWEDecryptFamily, GLWEPlaintext, GLWESecret, GLWESecretExec, GLWETensorKey,
16 GLWETensorKeyCompressed, GLWETensorKeyEncryptSkFamily, Infos,
17};
18
19pub(crate) trait TestModuleFamily<B: Backend> = GGLWEEncryptSkFamily<B>
20 + GLWEDecryptFamily<B>
21 + VecZnxSwithcDegree
22 + VecZnxAddScalarInplace
23 + VecZnxStd
24 + VecZnxSubScalarInplace;
25
26pub(crate) trait TestScratchFamily<B: Backend> = TakeVecZnxDftImpl<B>
27 + TakeVecZnxBigImpl<B>
28 + TakeSvpPPolImpl<B>
29 + ScratchOwnedAllocImpl<B>
30 + ScratchOwnedBorrowImpl<B>
31 + ScratchAvailableImpl<B>
32 + TakeScalarZnxImpl<B>
33 + TakeVecZnxImpl<B>
34 + VecZnxDftAllocBytesImpl<B>
35 + VecZnxBigAllocBytesImpl<B>
36 + TakeSvpPPolImpl<B>;
37
38pub(crate) fn test_tensor_key_encrypt_sk<B: Backend>(module: &Module<B>, basek: usize, k: usize, sigma: f64, rank: usize)
39where
40 Module<B>: TestModuleFamily<B>
41 + GGLWEExecLayoutFamily<B>
42 + GLWETensorKeyEncryptSkFamily<B>
43 + GLWEDecryptFamily<B>
44 + VecZnxDftAlloc<B>
45 + VecZnxBigAlloc<B>,
46 B: TestScratchFamily<B>,
47{
48 let n: usize = module.n();
49 let rows: usize = k / basek;
50
51 let mut tensor_key: GLWETensorKey<Vec<u8>> = GLWETensorKey::alloc(n, basek, k, rows, 1, rank);
52
53 let mut source_xs: Source = Source::new([0u8; 32]);
54 let mut source_xe: Source = Source::new([0u8; 32]);
55 let mut source_xa: Source = Source::new([0u8; 32]);
56
57 let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWETensorKey::encrypt_sk_scratch_space(
58 module,
59 n,
60 basek,
61 tensor_key.k(),
62 rank,
63 ));
64
65 let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
66 sk.fill_ternary_prob(0.5, &mut source_xs);
67 let mut sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk);
68 sk_exec.prepare(module, &sk);
69
70 tensor_key.encrypt_sk(
71 module,
72 &sk,
73 &mut source_xa,
74 &mut source_xe,
75 sigma,
76 scratch.borrow(),
77 );
78
79 let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k);
80
81 let mut sk_ij_dft = module.vec_znx_dft_alloc(n, 1, 1);
82 let mut sk_ij_big = module.vec_znx_big_alloc(n, 1, 1);
83 let mut sk_ij: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, 1);
84 let mut sk_dft: VecZnxDft<Vec<u8>, B> = module.vec_znx_dft_alloc(n, rank, 1);
85
86 (0..rank).for_each(|i| {
87 module.vec_znx_dft_from_vec_znx(1, 0, &mut sk_dft, i, &sk.data.as_vec_znx(), i);
88 });
89
90 (0..rank).for_each(|i| {
91 (0..rank).for_each(|j| {
92 module.svp_apply(&mut sk_ij_dft, 0, &sk_exec.data, j, &sk_dft, i);
93 module.vec_znx_dft_to_vec_znx_big_tmp_a(&mut sk_ij_big, 0, &mut sk_ij_dft, 0);
94 module.vec_znx_big_normalize(
95 basek,
96 &mut sk_ij.data.as_vec_znx_mut(),
97 0,
98 &sk_ij_big,
99 0,
100 scratch.borrow(),
101 );
102 (0..tensor_key.rank_in()).for_each(|col_i| {
103 (0..tensor_key.rows()).for_each(|row_i| {
104 tensor_key
105 .at(i, j)
106 .at(row_i, col_i)
107 .decrypt(module, &mut pt, &sk_exec, scratch.borrow());
108
109 module.vec_znx_sub_scalar_inplace(&mut pt.data, 0, row_i, &sk_ij.data, col_i);
110
111 let std_pt: f64 = module.vec_znx_std(basek, &pt.data, 0) * (k as f64).exp2();
112 assert!((sigma - std_pt).abs() <= 0.5, "{} {}", sigma, std_pt);
113 });
114 });
115 })
116 })
117}
118
119pub(crate) fn test_tensor_key_encrypt_sk_compressed<B: Backend>(
120 module: &Module<B>,
121 basek: usize,
122 k: usize,
123 sigma: f64,
124 rank: usize,
125) where
126 Module<B>: TestModuleFamily<B>
127 + GGLWEExecLayoutFamily<B>
128 + GLWETensorKeyEncryptSkFamily<B>
129 + GLWEDecryptFamily<B>
130 + VecZnxDftAlloc<B>
131 + VecZnxBigAlloc<B>
132 + VecZnxCopy,
133 B: TestScratchFamily<B>,
134{
135 let n: usize = module.n();
136 let rows: usize = k / basek;
137
138 let mut tensor_key_compressed: GLWETensorKeyCompressed<Vec<u8>> = GLWETensorKeyCompressed::alloc(n, basek, k, rows, 1, rank);
139
140 let mut source_xs: Source = Source::new([0u8; 32]);
141 let mut source_xe: Source = Source::new([0u8; 32]);
142
143 let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWETensorKeyCompressed::encrypt_sk_scratch_space(
144 module,
145 n,
146 basek,
147 tensor_key_compressed.k(),
148 rank,
149 ));
150
151 let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
152 sk.fill_ternary_prob(0.5, &mut source_xs);
153 let mut sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk);
154 sk_exec.prepare(module, &sk);
155
156 let seed_xa: [u8; 32] = [1u8; 32];
157
158 tensor_key_compressed.encrypt_sk(
159 module,
160 &sk,
161 seed_xa,
162 &mut source_xe,
163 sigma,
164 scratch.borrow(),
165 );
166
167 let mut tensor_key: GLWETensorKey<Vec<u8>> = GLWETensorKey::alloc(n, basek, k, rows, 1, rank);
168 tensor_key.decompress(module, &tensor_key_compressed);
169
170 let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k);
171
172 let mut sk_ij_dft = module.vec_znx_dft_alloc(n, 1, 1);
173 let mut sk_ij_big = module.vec_znx_big_alloc(n, 1, 1);
174 let mut sk_ij: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, 1);
175 let mut sk_dft: VecZnxDft<Vec<u8>, B> = module.vec_znx_dft_alloc(n, rank, 1);
176
177 (0..rank).for_each(|i| {
178 module.vec_znx_dft_from_vec_znx(1, 0, &mut sk_dft, i, &sk.data.as_vec_znx(), i);
179 });
180
181 (0..rank).for_each(|i| {
182 (0..rank).for_each(|j| {
183 module.svp_apply(&mut sk_ij_dft, 0, &sk_exec.data, j, &sk_dft, i);
184 module.vec_znx_dft_to_vec_znx_big_tmp_a(&mut sk_ij_big, 0, &mut sk_ij_dft, 0);
185 module.vec_znx_big_normalize(
186 basek,
187 &mut sk_ij.data.as_vec_znx_mut(),
188 0,
189 &sk_ij_big,
190 0,
191 scratch.borrow(),
192 );
193 (0..tensor_key.rank_in()).for_each(|col_i| {
194 (0..tensor_key.rows()).for_each(|row_i| {
195 tensor_key
196 .at(i, j)
197 .at(row_i, col_i)
198 .decrypt(module, &mut pt, &sk_exec, scratch.borrow());
199
200 module.vec_znx_sub_scalar_inplace(&mut pt.data, 0, row_i, &sk_ij.data, col_i);
201
202 let std_pt: f64 = module.vec_znx_std(basek, &pt.data, 0) * (k as f64).exp2();
203 assert!((sigma - std_pt).abs() <= 0.5, "{} {}", sigma, std_pt);
204 });
205 });
206 })
207 })
208}