poulpy/core/src/tests/generics/packing.rs
core/src/tests/generics/packing.rsRaw
1use std::collections::HashMap;
2
3use backend::hal::{
4 api::{
5 ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, VecZnxAddInplace,
6 VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxBigAddInplace,
7 VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, VecZnxBigAutomorphismInplace, VecZnxBigNormalize,
8 VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallBInplace, VecZnxCopy, VecZnxDftAllocBytes, VecZnxDftFromVecZnx,
9 VecZnxDftToVecZnxBigConsume, VecZnxFillUniform, VecZnxNegateInplace, VecZnxNormalize, VecZnxNormalizeInplace,
10 VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxRshInplace, VecZnxSub, VecZnxSubABInplace,
11 VecZnxSwithcDegree, VmpApply, VmpApplyAdd, VmpApplyTmpBytes, VmpPMatAlloc, VmpPrepare,
12 },
13 layouts::{Backend, Module, ScratchOwned},
14 oep::{
15 ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
16 TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
17 },
18};
19use sampling::source::Source;
20
21use crate::{
22 GLWEOperations, GLWEPacker,
23 layouts::{
24 GGLWEAutomorphismKey, GLWECiphertext, GLWEPlaintext, GLWESecret,
25 prepared::{GGLWEAutomorphismKeyPrepared, GLWESecretPrepared, PrepareAlloc},
26 },
27};
28
29pub fn test_glwe_packing<B>(module: &Module<B>)
30where
31 Module<B>: VecZnxDftAllocBytes
32 + VecZnxAutomorphism
33 + VecZnxBigAutomorphismInplace<B>
34 + VecZnxBigSubSmallBInplace<B>
35 + VecZnxNegateInplace
36 + VecZnxRshInplace
37 + VecZnxRotateInplace
38 + VecZnxBigNormalize<B>
39 + VecZnxDftFromVecZnx<B>
40 + VecZnxRotate
41 + SvpApplyInplace<B>
42 + VecZnxDftToVecZnxBigConsume<B>
43 + VecZnxFillUniform
44 + VecZnxSubABInplace
45 + VecZnxAddInplace
46 + VecZnxNormalizeInplace<B>
47 + VecZnxAddNormal
48 + VecZnxNormalize<B>
49 + VecZnxSub
50 + SvpPrepare<B>
51 + SvpPPolAllocBytes
52 + SvpPPolAlloc<B>
53 + VecZnxBigAllocBytes
54 + VecZnxBigAddInplace<B>
55 + VecZnxBigAddSmallInplace<B>
56 + VecZnxNormalizeTmpBytes
57 + VecZnxAddScalarInplace
58 + VmpPMatAlloc<B>
59 + VmpPrepare<B>
60 + VmpApplyTmpBytes
61 + VmpApply<B>
62 + VmpApplyAdd<B>
63 + VecZnxBigNormalizeTmpBytes
64 + VecZnxSwithcDegree
65 + VecZnxAutomorphismInplace
66 + VecZnxCopy,
67 B: Backend
68 + TakeVecZnxDftImpl<B>
69 + TakeVecZnxBigImpl<B>
70 + TakeSvpPPolImpl<B>
71 + ScratchOwnedAllocImpl<B>
72 + ScratchOwnedBorrowImpl<B>
73 + ScratchAvailableImpl<B>
74 + TakeScalarZnxImpl<B>
75 + TakeVecZnxImpl<B>,
76{
77 let mut source_xs: Source = Source::new([0u8; 32]);
78 let mut source_xe: Source = Source::new([0u8; 32]);
79 let mut source_xa: Source = Source::new([0u8; 32]);
80
81 let n: usize = module.n();
82 let basek: usize = 18;
83 let k_ct: usize = 36;
84 let pt_k: usize = 18;
85 let rank: usize = 3;
86 let sigma: f64 = 3.2;
87 let digits: usize = 1;
88 let k_ksk: usize = k_ct + basek * digits;
89
90 let rows: usize = k_ct.div_ceil(basek * digits);
91
92 let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
93 GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k_ct)
94 | GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank)
95 | GLWEPacker::scratch_space(module, n, basek, k_ct, k_ksk, digits, rank),
96 );
97
98 let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
99 sk.fill_ternary_prob(0.5, &mut source_xs);
100 let sk_dft: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
101
102 let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_ct);
103 let mut data: Vec<i64> = vec![0i64; n];
104 data.iter_mut().enumerate().for_each(|(i, x)| {
105 *x = i as i64;
106 });
107
108 pt.encode_vec_i64(&data, pt_k);
109
110 let gal_els: Vec<i64> = GLWEPacker::galois_elements(module);
111
112 let mut auto_keys: HashMap<i64, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>> = HashMap::new();
113 let mut tmp: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank);
114 gal_els.iter().for_each(|gal_el| {
115 tmp.encrypt_sk(
116 module,
117 *gal_el,
118 &sk,
119 &mut source_xa,
120 &mut source_xe,
121 sigma,
122 scratch.borrow(),
123 );
124 let atk_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = tmp.prepare_alloc(module, scratch.borrow());
125 auto_keys.insert(*gal_el, atk_prepared);
126 });
127
128 let log_batch: usize = 0;
129
130 let mut packer: GLWEPacker = GLWEPacker::new(n, log_batch, basek, k_ct, rank);
131
132 let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank);
133
134 ct.encrypt_sk(
135 module,
136 &pt,
137 &sk_dft,
138 &mut source_xa,
139 &mut source_xe,
140 sigma,
141 scratch.borrow(),
142 );
143
144 let log_n: usize = module.log_n();
145
146 (0..n >> log_batch).for_each(|i| {
147 ct.encrypt_sk(
148 module,
149 &pt,
150 &sk_dft,
151 &mut source_xa,
152 &mut source_xe,
153 sigma,
154 scratch.borrow(),
155 );
156
157 pt.rotate_inplace(module, -(1 << log_batch)); // X^-batch * pt
158
159 if reverse_bits_msb(i, log_n as u32).is_multiple_of(5) {
160 packer.add(module, Some(&ct), &auto_keys, scratch.borrow());
161 } else {
162 packer.add(
163 module,
164 None::<&GLWECiphertext<Vec<u8>>>,
165 &auto_keys,
166 scratch.borrow(),
167 )
168 }
169 });
170
171 let mut res = GLWECiphertext::alloc(n, basek, k_ct, rank);
172 packer.flush(module, &mut res);
173
174 let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_ct);
175 let mut data: Vec<i64> = vec![0i64; n];
176 data.iter_mut().enumerate().for_each(|(i, x)| {
177 if i.is_multiple_of(5) {
178 *x = reverse_bits_msb(i, log_n as u32) as i64;
179 }
180 });
181
182 pt_want.encode_vec_i64(&data, pt_k);
183
184 res.decrypt(module, &mut pt, &sk_dft, scratch.borrow());
185
186 pt.sub_inplace_ab(module, &pt_want);
187
188 let noise_have: f64 = pt.std().log2();
189 // println!("noise_have: {}", noise_have);
190 assert!(
191 noise_have < -((k_ct - basek) as f64),
192 "noise: {}",
193 noise_have
194 );
195}
196
197#[inline(always)]
198fn reverse_bits_msb(x: usize, n: u32) -> usize {
199 x.reverse_bits() >> (usize::BITS - n)
200}