poulpy/poulpy-core/src/tests/generics/keyswitch/lwe_ct.rs
poulpy-core/src/tests/generics/keyswitch/lwe_ct.rsRaw
1use poulpy_hal::{
2 api::{
3 ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, VecZnxAddInplace,
4 VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace,
5 VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAllocBytes, VecZnxDftFromVecZnx,
6 VecZnxDftToVecZnxBigConsume, VecZnxFillUniform, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes,
7 VecZnxSub, VecZnxSubABInplace, VecZnxSwithcDegree, VmpApply, VmpApplyAdd, VmpApplyTmpBytes, VmpPMatAlloc, VmpPrepare,
8 ZnxView,
9 },
10 layouts::{Backend, Module, ScratchOwned},
11 oep::{
12 ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
13 TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
14 },
15 source::Source,
16};
17
18use crate::layouts::{
19 Infos, LWECiphertext, LWEPlaintext, LWESecret, LWESwitchingKey,
20 prepared::{LWESwitchingKeyPrepared, PrepareAlloc},
21};
22
23pub fn test_lwe_keyswitch<B>(module: &Module<B>)
24where
25 Module<B>: VecZnxDftAllocBytes
26 + VecZnxBigNormalize<B>
27 + VecZnxDftFromVecZnx<B>
28 + SvpApplyInplace<B>
29 + VecZnxDftToVecZnxBigConsume<B>
30 + VecZnxFillUniform
31 + VecZnxSubABInplace
32 + VecZnxAddInplace
33 + VecZnxNormalizeInplace<B>
34 + VecZnxAddNormal
35 + VecZnxNormalize<B>
36 + VecZnxSub
37 + SvpPrepare<B>
38 + SvpPPolAllocBytes
39 + SvpPPolAlloc<B>
40 + VecZnxBigAllocBytes
41 + VecZnxBigAddInplace<B>
42 + VecZnxBigAddSmallInplace<B>
43 + VecZnxNormalizeTmpBytes
44 + VecZnxAddScalarInplace
45 + VmpPMatAlloc<B>
46 + VmpPrepare<B>
47 + VmpApplyTmpBytes
48 + VmpApply<B>
49 + VmpApplyAdd<B>
50 + VecZnxBigNormalizeTmpBytes
51 + VecZnxSwithcDegree
52 + VecZnxAutomorphismInplace,
53 B: Backend
54 + TakeVecZnxDftImpl<B>
55 + TakeVecZnxBigImpl<B>
56 + TakeSvpPPolImpl<B>
57 + ScratchOwnedAllocImpl<B>
58 + ScratchOwnedBorrowImpl<B>
59 + ScratchAvailableImpl<B>
60 + TakeScalarZnxImpl<B>
61 + TakeVecZnxImpl<B>,
62{
63 let n: usize = module.n();
64 let basek: usize = 17;
65 let sigma: f64 = 3.2;
66
67 let n_lwe_in: usize = 22;
68 let n_lwe_out: usize = 30;
69 let k_lwe_ct: usize = 2 * basek;
70 let k_lwe_pt: usize = 8;
71
72 let k_ksk: usize = k_lwe_ct + basek;
73
74 let mut source_xs: Source = Source::new([0u8; 32]);
75 let mut source_xa: Source = Source::new([0u8; 32]);
76 let mut source_xe: Source = Source::new([0u8; 32]);
77
78 let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
79 LWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk)
80 | LWECiphertext::keyswitch_scratch_space(module, n, basek, k_lwe_ct, k_lwe_ct, k_ksk),
81 );
82
83 let mut sk_lwe_in: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe_in);
84 sk_lwe_in.fill_ternary_prob(0.5, &mut source_xs);
85
86 let mut sk_lwe_out: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe_out);
87 sk_lwe_out.fill_ternary_prob(0.5, &mut source_xs);
88
89 let data: i64 = 17;
90
91 let mut lwe_pt_in: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_pt);
92
93 lwe_pt_in.encode_i64(data, k_lwe_pt);
94
95 let mut lwe_ct_in: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe_in, basek, k_lwe_ct);
96 lwe_ct_in.encrypt_sk(
97 module,
98 &lwe_pt_in,
99 &sk_lwe_in,
100 &mut source_xa,
101 &mut source_xe,
102 sigma,
103 );
104
105 let mut ksk: LWESwitchingKey<Vec<u8>> = LWESwitchingKey::alloc(n, basek, k_ksk, lwe_ct_in.size());
106
107 ksk.encrypt_sk(
108 module,
109 &sk_lwe_in,
110 &sk_lwe_out,
111 &mut source_xa,
112 &mut source_xe,
113 sigma,
114 scratch.borrow(),
115 );
116
117 let mut lwe_ct_out: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe_out, basek, k_lwe_ct);
118
119 let ksk_prepared: LWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow());
120
121 lwe_ct_out.keyswitch(module, &lwe_ct_in, &ksk_prepared, scratch.borrow());
122
123 let mut lwe_pt_out: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_ct);
124 lwe_ct_out.decrypt(module, &mut lwe_pt_out, &sk_lwe_out);
125
126 assert_eq!(lwe_pt_in.data.at(0, 0)[0], lwe_pt_out.data.at(0, 0)[0]);
127}