arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/test_fft64/rlwe_dft.rs
core/src/test_fft64/rlwe_dft.rsRaw
  1#[cfg(test)]
  2mod tests {
  3    use crate::{
  4        elem::{FromProdBy, FromProdByScratchSpace, Infos, ProdBy, ProdByScratchSpace},
  5        grlwe::GRLWECt,
  6        keys::{SecretKey, SecretKeyDft},
  7        rlwe::{RLWECt, RLWECtDft, RLWEPt},
  8        test_fft64::grlwe::noise_grlwe_rlwe_product,
  9    };
 10    use base2k::{FFT64, FillUniform, Module, ScratchOwned, Stats, VecZnxOps};
 11    use sampling::source::Source;
 12
 13    #[test]
 14    fn from_prod_by_grlwe() {
 15        let module: Module<FFT64> = Module::<FFT64>::new(2048);
 16        let log_base2k: usize = 12;
 17        let log_k_grlwe: usize = 60;
 18        let log_k_rlwe_in: usize = 45;
 19        let log_k_rlwe_out: usize = 60;
 20        let rows: usize = (log_k_rlwe_in + log_base2k - 1) / log_base2k;
 21
 22        let sigma: f64 = 3.2;
 23        let bound: f64 = sigma * 6.0;
 24
 25        let mut ct_grlwe: GRLWECt<Vec<u8>, FFT64> = GRLWECt::new(&module, log_base2k, log_k_grlwe, rows);
 26        let mut ct_rlwe_in: RLWECt<Vec<u8>> = RLWECt::new(&module, log_base2k, log_k_rlwe_in);
 27        let mut ct_rlwe_in_dft: RLWECtDft<Vec<u8>, FFT64> = RLWECtDft::new(&module, log_base2k, log_k_rlwe_in);
 28        let mut ct_rlwe_out: RLWECt<Vec<u8>> = RLWECt::new(&module, log_base2k, log_k_rlwe_out);
 29        let mut ct_rlwe_out_dft: RLWECtDft<Vec<u8>, FFT64> = RLWECtDft::new(&module, log_base2k, log_k_rlwe_out);
 30        let mut pt_want: RLWEPt<Vec<u8>> = RLWEPt::new(&module, log_base2k, log_k_rlwe_in);
 31        let mut pt_have: RLWEPt<Vec<u8>> = RLWEPt::new(&module, log_base2k, log_k_rlwe_out);
 32
 33        let mut source_xs: Source = Source::new([0u8; 32]);
 34        let mut source_xe: Source = Source::new([0u8; 32]);
 35        let mut source_xa: Source = Source::new([0u8; 32]);
 36
 37        // Random input plaintext
 38        pt_want
 39            .data
 40            .fill_uniform(log_base2k, 0, pt_want.size(), &mut source_xa);
 41
 42        let mut scratch: ScratchOwned = ScratchOwned::new(
 43            GRLWECt::encrypt_sk_scratch_space(&module, ct_grlwe.size())
 44                | RLWECt::decrypt_scratch_space(&module, ct_rlwe_out.size())
 45                | RLWECt::encrypt_sk_scratch_space(&module, ct_rlwe_in.size())
 46                | RLWECtDft::from_prod_by_grlwe_scratch_space(
 47                    &module,
 48                    ct_rlwe_out.size(),
 49                    ct_rlwe_in.size(),
 50                    ct_grlwe.size(),
 51                ),
 52        );
 53
 54        let mut sk0: SecretKey<Vec<u8>> = SecretKey::new(&module);
 55        sk0.fill_ternary_prob(0.5, &mut source_xs);
 56
 57        let mut sk0_dft: SecretKeyDft<Vec<u8>, FFT64> = SecretKeyDft::new(&module);
 58        sk0_dft.dft(&module, &sk0);
 59
 60        let mut sk1: SecretKey<Vec<u8>> = SecretKey::new(&module);
 61        sk1.fill_ternary_prob(0.5, &mut source_xs);
 62
 63        let mut sk1_dft: SecretKeyDft<Vec<u8>, FFT64> = SecretKeyDft::new(&module);
 64        sk1_dft.dft(&module, &sk1);
 65
 66        ct_grlwe.encrypt_sk(
 67            &module,
 68            &sk0.data,
 69            &sk1_dft,
 70            &mut source_xa,
 71            &mut source_xe,
 72            sigma,
 73            bound,
 74            scratch.borrow(),
 75        );
 76
 77        ct_rlwe_in.encrypt_sk(
 78            &module,
 79            Some(&pt_want),
 80            &sk0_dft,
 81            &mut source_xa,
 82            &mut source_xe,
 83            sigma,
 84            bound,
 85            scratch.borrow(),
 86        );
 87
 88        ct_rlwe_in.dft(&module, &mut ct_rlwe_in_dft);
 89        ct_rlwe_out_dft.from_prod_by_grlwe(&module, &ct_rlwe_in_dft, &ct_grlwe, scratch.borrow());
 90        ct_rlwe_out_dft.idft(&module, &mut ct_rlwe_out, scratch.borrow());
 91
 92        ct_rlwe_out.decrypt(&module, &mut pt_have, &sk1_dft, scratch.borrow());
 93
 94        module.vec_znx_sub_ab_inplace(&mut pt_have, 0, &pt_want, 0);
 95
 96        let noise_have: f64 = pt_have.data.std(0, log_base2k).log2();
 97        let noise_want: f64 = noise_grlwe_rlwe_product(
 98            module.n() as f64,
 99            log_base2k,
100            0.5,
101            0.5,
102            0f64,
103            sigma * sigma,
104            0f64,
105            log_k_rlwe_in,
106            log_k_grlwe,
107        );
108
109        assert!(
110            (noise_have - noise_want).abs() <= 0.1,
111            "{} {}",
112            noise_have,
113            noise_want
114        );
115
116        module.free();
117    }
118
119    #[test]
120    fn prod_by_grlwe() {
121        let module: Module<FFT64> = Module::<FFT64>::new(2048);
122        let log_base2k: usize = 12;
123        let log_k_grlwe: usize = 60;
124        let log_k_rlwe: usize = 45;
125        let rows: usize = (log_k_rlwe + log_base2k - 1) / log_base2k;
126
127        let sigma: f64 = 3.2;
128        let bound: f64 = sigma * 6.0;
129
130        let mut ct_grlwe: GRLWECt<Vec<u8>, FFT64> = GRLWECt::new(&module, log_base2k, log_k_grlwe, rows);
131        let mut ct_rlwe: RLWECt<Vec<u8>> = RLWECt::new(&module, log_base2k, log_k_rlwe);
132        let mut ct_rlwe_dft: RLWECtDft<Vec<u8>, FFT64> = RLWECtDft::new(&module, log_base2k, log_k_rlwe);
133        let mut pt_want: RLWEPt<Vec<u8>> = RLWEPt::new(&module, log_base2k, log_k_rlwe);
134        let mut pt_have: RLWEPt<Vec<u8>> = RLWEPt::new(&module, log_base2k, log_k_rlwe);
135
136        let mut source_xs: Source = Source::new([0u8; 32]);
137        let mut source_xe: Source = Source::new([0u8; 32]);
138        let mut source_xa: Source = Source::new([0u8; 32]);
139
140        // Random input plaintext
141        pt_want
142            .data
143            .fill_uniform(log_base2k, 0, pt_want.size(), &mut source_xa);
144
145        let mut scratch: ScratchOwned = ScratchOwned::new(
146            GRLWECt::encrypt_sk_scratch_space(&module, ct_grlwe.size())
147                | RLWECt::decrypt_scratch_space(&module, ct_rlwe.size())
148                | RLWECt::encrypt_sk_scratch_space(&module, ct_rlwe.size())
149                | RLWECtDft::prod_by_grlwe_scratch_space(&module, ct_rlwe_dft.size(), ct_grlwe.size()),
150        );
151
152        let mut sk0: SecretKey<Vec<u8>> = SecretKey::new(&module);
153        sk0.fill_ternary_prob(0.5, &mut source_xs);
154
155        let mut sk0_dft: SecretKeyDft<Vec<u8>, FFT64> = SecretKeyDft::new(&module);
156        sk0_dft.dft(&module, &sk0);
157
158        let mut sk1: SecretKey<Vec<u8>> = SecretKey::new(&module);
159        sk1.fill_ternary_prob(0.5, &mut source_xs);
160
161        let mut sk1_dft: SecretKeyDft<Vec<u8>, FFT64> = SecretKeyDft::new(&module);
162        sk1_dft.dft(&module, &sk1);
163
164        ct_grlwe.encrypt_sk(
165            &module,
166            &sk0.data,
167            &sk1_dft,
168            &mut source_xa,
169            &mut source_xe,
170            sigma,
171            bound,
172            scratch.borrow(),
173        );
174
175        ct_rlwe.encrypt_sk(
176            &module,
177            Some(&pt_want),
178            &sk0_dft,
179            &mut source_xa,
180            &mut source_xe,
181            sigma,
182            bound,
183            scratch.borrow(),
184        );
185
186        ct_rlwe.dft(&module, &mut ct_rlwe_dft);
187        ct_rlwe_dft.prod_by_grlwe(&module, &ct_grlwe, scratch.borrow());
188        ct_rlwe_dft.idft(&module, &mut ct_rlwe, scratch.borrow());
189
190        ct_rlwe.decrypt(&module, &mut pt_have, &sk1_dft, scratch.borrow());
191
192        module.vec_znx_sub_ab_inplace(&mut pt_have, 0, &pt_want, 0);
193
194        let noise_have: f64 = pt_have.data.std(0, log_base2k).log2();
195        let noise_want: f64 = noise_grlwe_rlwe_product(
196            module.n() as f64,
197            log_base2k,
198            0.5,
199            0.5,
200            0f64,
201            sigma * sigma,
202            0f64,
203            log_k_rlwe,
204            log_k_grlwe,
205        );
206
207        assert!(
208            (noise_have - noise_want).abs() <= 0.1,
209            "{} {}",
210            noise_have,
211            noise_want
212        );
213
214        module.free();
215    }
216}