arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/glwe/test_fft64/automorphism.rs
core/src/glwe/test_fft64/automorphism.rsRaw
  1use backend::{
  2    hal::{
  3        api::{
  4            MatZnxAlloc, ModuleNew, ScalarZnxAlloc, ScalarZnxAllocBytes, ScalarZnxAutomorphism, ScratchOwnedAlloc,
  5            ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAlloc, VecZnxAllocBytes, VecZnxAutomorphismInplace,
  6            VecZnxFillUniform, VecZnxStd, VecZnxSwithcDegree,
  7        },
  8        layouts::{Backend, Module, ScratchOwned},
  9        oep::{
 10            ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
 11            TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
 12        },
 13    },
 14    implementation::cpu_spqlios::FFT64,
 15};
 16use sampling::source::Source;
 17
 18use crate::{
 19    AutomorphismKey, AutomorphismKeyEncryptSkFamily, AutomorphismKeyExec, GGLWEExecLayoutFamily, GLWECiphertext,
 20    GLWEDecryptFamily, GLWEKeyswitchFamily, GLWEPlaintext, GLWESecret, GLWESecretExec, Infos,
 21    noise::log2_std_noise_gglwe_product,
 22};
 23
 24#[test]
 25fn apply_inplace() {
 26    let log_n: usize = 8;
 27    let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
 28    let basek: usize = 12;
 29    let k_ct: usize = 60;
 30    let digits: usize = k_ct.div_ceil(basek);
 31    (1..4).for_each(|rank| {
 32        (1..digits + 1).for_each(|di| {
 33            let k_ksk: usize = k_ct + basek * di;
 34            println!("test automorphism_inplace digits: {} rank: {}", di, rank);
 35            test_automorphism_inplace(&module, basek, -5, k_ct, k_ksk, di, rank, 3.2);
 36        });
 37    });
 38}
 39
 40#[test]
 41fn apply() {
 42    let log_n: usize = 8;
 43    let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
 44    let basek: usize = 12;
 45    let k_in: usize = 60;
 46    let digits: usize = k_in.div_ceil(basek);
 47    (1..4).for_each(|rank| {
 48        (1..digits + 1).for_each(|di| {
 49            let k_ksk: usize = k_in + basek * di;
 50            let k_out: usize = k_ksk; // Better capture noise.
 51            println!("test automorphism digits: {} rank: {}", di, rank);
 52            test_automorphism(&module, basek, -5, k_out, k_in, k_ksk, di, rank, 3.2);
 53        })
 54    });
 55}
 56
 57pub(crate) trait AutomorphismTestModuleFamily<B: Backend> = AutomorphismKeyEncryptSkFamily<B>
 58    + GLWEDecryptFamily<B>
 59    + GGLWEExecLayoutFamily<B>
 60    + GLWEKeyswitchFamily<B>
 61    + MatZnxAlloc
 62    + VecZnxAlloc
 63    + ScalarZnxAllocBytes
 64    + VecZnxAllocBytes
 65    + ScalarZnxAutomorphism
 66    + VecZnxSwithcDegree
 67    + ScalarZnxAlloc
 68    + VecZnxAddScalarInplace
 69    + VecZnxAutomorphismInplace
 70    + VecZnxStd;
 71pub(crate) trait AutomorphismTestScratchFamily<B: Backend> = TakeVecZnxDftImpl<B>
 72    + TakeVecZnxBigImpl<B>
 73    + TakeSvpPPolImpl<B>
 74    + ScratchOwnedAllocImpl<B>
 75    + ScratchOwnedBorrowImpl<B>
 76    + ScratchAvailableImpl<B>
 77    + TakeScalarZnxImpl<B>
 78    + TakeVecZnxImpl<B>;
 79
 80fn test_automorphism<B: Backend>(
 81    module: &Module<B>,
 82    basek: usize,
 83    p: i64,
 84    k_out: usize,
 85    k_in: usize,
 86    k_ksk: usize,
 87    digits: usize,
 88    rank: usize,
 89    sigma: f64,
 90) where
 91    Module<B>: AutomorphismTestModuleFamily<B>,
 92    B: AutomorphismTestScratchFamily<B>,
 93{
 94    let rows: usize = k_in.div_ceil(basek * digits);
 95
 96    let mut autokey: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(module, basek, k_ksk, rows, digits, rank);
 97    let mut ct_in: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(module, basek, k_in, rank);
 98    let mut ct_out: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(module, basek, k_out, rank);
 99    let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(module, basek, k_in);
100
101    let mut source_xs: Source = Source::new([0u8; 32]);
102    let mut source_xe: Source = Source::new([0u8; 32]);
103    let mut source_xa: Source = Source::new([0u8; 32]);
104
105    module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_in, &mut source_xa);
106
107    let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
108        AutomorphismKey::encrypt_sk_scratch_space(module, basek, autokey.k(), rank)
109            | GLWECiphertext::decrypt_scratch_space(module, basek, ct_out.k())
110            | GLWECiphertext::encrypt_sk_scratch_space(module, basek, ct_in.k())
111            | GLWECiphertext::automorphism_scratch_space(
112                module,
113                basek,
114                ct_out.k(),
115                ct_in.k(),
116                autokey.k(),
117                digits,
118                rank,
119            ),
120    );
121
122    let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank);
123    sk.fill_ternary_prob(0.5, &mut source_xs);
124    let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk);
125
126    autokey.encrypt_sk(
127        module,
128        p,
129        &sk,
130        &mut source_xa,
131        &mut source_xe,
132        sigma,
133        scratch.borrow(),
134    );
135
136    ct_in.encrypt_sk(
137        module,
138        &pt_want,
139        &sk_exec,
140        &mut source_xa,
141        &mut source_xe,
142        sigma,
143        scratch.borrow(),
144    );
145
146    let mut autokey_exec: AutomorphismKeyExec<Vec<u8>, B> = AutomorphismKeyExec::alloc(module, basek, k_ksk, rows, digits, rank);
147    autokey_exec.prepare(module, &autokey, scratch.borrow());
148
149    ct_out.automorphism(module, &ct_in, &autokey_exec, scratch.borrow());
150
151    let max_noise: f64 = log2_std_noise_gglwe_product(
152        module.n() as f64,
153        basek * digits,
154        0.5,
155        0.5,
156        0f64,
157        sigma * sigma,
158        0f64,
159        rank as f64,
160        k_in,
161        k_ksk,
162    );
163
164    module.vec_znx_automorphism_inplace(p, &mut pt_want.data, 0);
165
166    ct_out.assert_noise(module, &sk_exec, &pt_want, max_noise + 1.0);
167}
168
169fn test_automorphism_inplace<B: Backend>(
170    module: &Module<B>,
171    basek: usize,
172    p: i64,
173    k_ct: usize,
174    k_ksk: usize,
175    digits: usize,
176    rank: usize,
177    sigma: f64,
178) where
179    Module<B>: AutomorphismTestModuleFamily<B>,
180    B: AutomorphismTestScratchFamily<B>,
181{
182    let rows: usize = k_ct.div_ceil(basek * digits);
183
184    let mut autokey: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(module, basek, k_ksk, rows, digits, rank);
185    let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(module, basek, k_ct, rank);
186    let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(module, basek, k_ct);
187
188    let mut source_xs: Source = Source::new([0u8; 32]);
189    let mut source_xe: Source = Source::new([0u8; 32]);
190    let mut source_xa: Source = Source::new([0u8; 32]);
191
192    module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_ct, &mut source_xa);
193
194    let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
195        AutomorphismKey::encrypt_sk_scratch_space(module, basek, autokey.k(), rank)
196            | GLWECiphertext::decrypt_scratch_space(module, basek, ct.k())
197            | GLWECiphertext::encrypt_sk_scratch_space(module, basek, ct.k())
198            | GLWECiphertext::automorphism_inplace_scratch_space(module, basek, ct.k(), autokey.k(), digits, rank),
199    );
200
201    let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank);
202    sk.fill_ternary_prob(0.5, &mut source_xs);
203    let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk);
204
205    autokey.encrypt_sk(
206        module,
207        p,
208        &sk,
209        &mut source_xa,
210        &mut source_xe,
211        sigma,
212        scratch.borrow(),
213    );
214
215    ct.encrypt_sk(
216        module,
217        &pt_want,
218        &sk_exec,
219        &mut source_xa,
220        &mut source_xe,
221        sigma,
222        scratch.borrow(),
223    );
224
225    let mut autokey_exec: AutomorphismKeyExec<Vec<u8>, B> = AutomorphismKeyExec::alloc(module, basek, k_ksk, rows, digits, rank);
226    autokey_exec.prepare(module, &autokey, scratch.borrow());
227
228    ct.automorphism_inplace(module, &autokey_exec, scratch.borrow());
229
230    let max_noise: f64 = log2_std_noise_gglwe_product(
231        module.n() as f64,
232        basek * digits,
233        0.5,
234        0.5,
235        0f64,
236        sigma * sigma,
237        0f64,
238        rank as f64,
239        k_ct,
240        k_ksk,
241    );
242
243    module.vec_znx_automorphism_inplace(p, &mut pt_want.data, 0);
244
245    ct.assert_noise(module, &sk_exec, &pt_want, max_noise + 1.0);
246}