arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/lwe/tests/generic_conversion.rs
core/src/lwe/tests/generic_conversion.rsRaw
  1use backend::hal::{
  2    api::{
  3        ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxEncodeCoeffsi64,
  4        VecZnxSwithcDegree, ZnxView,
  5    },
  6    layouts::{Backend, Module, ScratchOwned},
  7    oep::{
  8        ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
  9        TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
 10    },
 11};
 12use sampling::source::Source;
 13
 14use crate::{
 15    GGLWEEncryptSkFamily, GGLWEExecLayoutFamily, GLWECiphertext, GLWEDecryptFamily, GLWEKeyswitchFamily, GLWEPlaintext,
 16    GLWESecret, GLWESecretExec, GLWEToLWESwitchingKey, GLWEToLWESwitchingKeyExec, Infos, LWECiphertext, LWEPlaintext, LWESecret,
 17    LWESwitchingKey, LWESwitchingKeyExec, LWEToGLWESwitchingKey, LWEToGLWESwitchingKeyExec,
 18};
 19
 20pub(crate) trait LWETestModuleFamily<B: Backend> = GGLWEEncryptSkFamily<B>
 21    + GLWEDecryptFamily<B>
 22    + VecZnxSwithcDegree
 23    + VecZnxAddScalarInplace
 24    + GGLWEExecLayoutFamily<B>
 25    + GLWEKeyswitchFamily<B>
 26    + VecZnxEncodeCoeffsi64
 27    + VecZnxAutomorphismInplace;
 28
 29pub(crate) trait LWETestScratchFamily<B: Backend> = TakeScalarZnxImpl<B>
 30    + TakeVecZnxDftImpl<B>
 31    + ScratchAvailableImpl<B>
 32    + TakeVecZnxImpl<B>
 33    + TakeVecZnxBigImpl<B>
 34    + TakeSvpPPolImpl<B>
 35    + ScratchOwnedAllocImpl<B>
 36    + ScratchOwnedBorrowImpl<B>;
 37
 38pub(crate) fn test_lwe_to_glwe<B: Backend>(module: &Module<B>)
 39where
 40    Module<B>: LWETestModuleFamily<B>,
 41    B: LWETestScratchFamily<B>,
 42{
 43    let n: usize = module.n();
 44    let basek: usize = 17;
 45    let sigma: f64 = 3.2;
 46
 47    let rank: usize = 2;
 48
 49    let n_lwe: usize = 22;
 50    let k_lwe_ct: usize = 2 * basek;
 51    let k_lwe_pt: usize = 8;
 52
 53    let k_glwe_ct: usize = 3 * basek;
 54
 55    let k_ksk: usize = k_lwe_ct + basek;
 56
 57    let mut source_xs: Source = Source::new([0u8; 32]);
 58    let mut source_xa: Source = Source::new([0u8; 32]);
 59    let mut source_xe: Source = Source::new([0u8; 32]);
 60
 61    let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
 62        LWEToGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank)
 63            | GLWECiphertext::from_lwe_scratch_space(module, n, basek, k_lwe_ct, k_glwe_ct, k_ksk, rank)
 64            | GLWECiphertext::decrypt_scratch_space(module, n, basek, k_glwe_ct),
 65    );
 66
 67    let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
 68    sk_glwe.fill_ternary_prob(0.5, &mut source_xs);
 69
 70    let sk_glwe_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_glwe);
 71
 72    let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe);
 73    sk_lwe.fill_ternary_prob(0.5, &mut source_xs);
 74
 75    let data: i64 = 17;
 76
 77    let mut lwe_pt: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_pt);
 78    module.encode_coeff_i64(basek, &mut lwe_pt.data, 0, k_lwe_pt, 0, data, k_lwe_pt);
 79
 80    let mut lwe_ct: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe, basek, k_lwe_ct);
 81    lwe_ct.encrypt_sk(
 82        module,
 83        &lwe_pt,
 84        &sk_lwe,
 85        &mut source_xa,
 86        &mut source_xe,
 87        sigma,
 88    );
 89
 90    let mut ksk: LWEToGLWESwitchingKey<Vec<u8>> = LWEToGLWESwitchingKey::alloc(n, basek, k_ksk, lwe_ct.size(), rank);
 91
 92    ksk.encrypt_sk(
 93        module,
 94        &sk_lwe,
 95        &sk_glwe,
 96        &mut source_xa,
 97        &mut source_xe,
 98        sigma,
 99        scratch.borrow(),
100    );
101
102    let mut glwe_ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_glwe_ct, rank);
103
104    let ksk_exec: LWEToGLWESwitchingKeyExec<Vec<u8>, B> = LWEToGLWESwitchingKeyExec::from(module, &ksk, scratch.borrow());
105
106    glwe_ct.from_lwe(module, &lwe_ct, &ksk_exec, scratch.borrow());
107
108    let mut glwe_pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_glwe_ct);
109    glwe_ct.decrypt(module, &mut glwe_pt, &sk_glwe_exec, scratch.borrow());
110
111    assert_eq!(glwe_pt.data.at(0, 0)[0], lwe_pt.data.at(0, 0)[0]);
112}
113
114pub(crate) fn test_glwe_to_lwe<B: Backend>(module: &Module<B>)
115where
116    Module<B>: LWETestModuleFamily<B>,
117    B: LWETestScratchFamily<B>,
118{
119    let n: usize = module.n();
120    let basek: usize = 17;
121    let sigma: f64 = 3.2;
122
123    let rank: usize = 2;
124
125    let n_lwe: usize = 22;
126    let k_lwe_ct: usize = 2 * basek;
127    let k_lwe_pt: usize = 8;
128
129    let k_glwe_ct: usize = 3 * basek;
130
131    let k_ksk: usize = k_lwe_ct + basek;
132
133    let mut source_xs: Source = Source::new([0u8; 32]);
134    let mut source_xa: Source = Source::new([0u8; 32]);
135    let mut source_xe: Source = Source::new([0u8; 32]);
136
137    let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
138        LWEToGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank)
139            | LWECiphertext::from_glwe_scratch_space(module, n, basek, k_lwe_ct, k_glwe_ct, k_ksk, rank)
140            | GLWECiphertext::decrypt_scratch_space(module, n, basek, k_glwe_ct),
141    );
142
143    let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
144    sk_glwe.fill_ternary_prob(0.5, &mut source_xs);
145
146    let sk_glwe_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_glwe);
147
148    let mut sk_lwe = LWESecret::alloc(n_lwe);
149    sk_lwe.fill_ternary_prob(0.5, &mut source_xs);
150
151    let data: i64 = 17;
152    let mut glwe_pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_glwe_ct);
153    module.encode_coeff_i64(basek, &mut glwe_pt.data, 0, k_lwe_pt, 0, data, k_lwe_pt);
154
155    let mut glwe_ct = GLWECiphertext::alloc(n, basek, k_glwe_ct, rank);
156    glwe_ct.encrypt_sk(
157        module,
158        &glwe_pt,
159        &sk_glwe_exec,
160        &mut source_xa,
161        &mut source_xe,
162        sigma,
163        scratch.borrow(),
164    );
165
166    let mut ksk: GLWEToLWESwitchingKey<Vec<u8>> = GLWEToLWESwitchingKey::alloc(n, basek, k_ksk, glwe_ct.size(), rank);
167
168    ksk.encrypt_sk(
169        module,
170        &sk_lwe,
171        &sk_glwe,
172        &mut source_xa,
173        &mut source_xe,
174        sigma,
175        scratch.borrow(),
176    );
177
178    let mut lwe_ct: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe, basek, k_lwe_ct);
179
180    let ksk_exec: GLWEToLWESwitchingKeyExec<Vec<u8>, B> = GLWEToLWESwitchingKeyExec::from(module, &ksk, scratch.borrow());
181
182    lwe_ct.from_glwe(module, &glwe_ct, &ksk_exec, scratch.borrow());
183
184    let mut lwe_pt: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_ct);
185    lwe_ct.decrypt(module, &mut lwe_pt, &sk_lwe);
186
187    assert_eq!(glwe_pt.data.at(0, 0)[0], lwe_pt.data.at(0, 0)[0]);
188}
189
190pub(crate) fn test_keyswitch<B: Backend>(module: &Module<B>)
191where
192    Module<B>: LWETestModuleFamily<B>,
193    B: LWETestScratchFamily<B>,
194{
195    let n: usize = module.n();
196    let basek: usize = 17;
197    let sigma: f64 = 3.2;
198
199    let n_lwe_in: usize = 22;
200    let n_lwe_out: usize = 30;
201    let k_lwe_ct: usize = 2 * basek;
202    let k_lwe_pt: usize = 8;
203
204    let k_ksk: usize = k_lwe_ct + basek;
205
206    let mut source_xs: Source = Source::new([0u8; 32]);
207    let mut source_xa: Source = Source::new([0u8; 32]);
208    let mut source_xe: Source = Source::new([0u8; 32]);
209
210    let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
211        LWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk)
212            | LWECiphertext::keyswitch_scratch_space(module, n, basek, k_lwe_ct, k_lwe_ct, k_ksk),
213    );
214
215    let mut sk_lwe_in: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe_in);
216    sk_lwe_in.fill_ternary_prob(0.5, &mut source_xs);
217
218    let mut sk_lwe_out: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe_out);
219    sk_lwe_out.fill_ternary_prob(0.5, &mut source_xs);
220
221    let data: i64 = 17;
222
223    let mut lwe_pt_in: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_pt);
224    module.encode_coeff_i64(basek, &mut lwe_pt_in.data, 0, k_lwe_pt, 0, data, k_lwe_pt);
225
226    let mut lwe_ct_in: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe_in, basek, k_lwe_ct);
227    lwe_ct_in.encrypt_sk(
228        module,
229        &lwe_pt_in,
230        &sk_lwe_in,
231        &mut source_xa,
232        &mut source_xe,
233        sigma,
234    );
235
236    let mut ksk: LWESwitchingKey<Vec<u8>> = LWESwitchingKey::alloc(n, basek, k_ksk, lwe_ct_in.size());
237
238    ksk.encrypt_sk(
239        module,
240        &sk_lwe_in,
241        &sk_lwe_out,
242        &mut source_xa,
243        &mut source_xe,
244        sigma,
245        scratch.borrow(),
246    );
247
248    let mut lwe_ct_out: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe_out, basek, k_lwe_ct);
249
250    let ksk_exec: LWESwitchingKeyExec<Vec<u8>, B> = LWESwitchingKeyExec::from(module, &ksk, scratch.borrow());
251
252    lwe_ct_out.keyswitch(module, &lwe_ct_in, &ksk_exec, scratch.borrow());
253
254    let mut lwe_pt_out: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_ct);
255    lwe_ct_out.decrypt(module, &mut lwe_pt_out, &sk_lwe_out);
256
257    assert_eq!(lwe_pt_in.data.at(0, 0)[0], lwe_pt_out.data.at(0, 0)[0]);
258}