poulpy/rlwe/examples/gadget_product.rs
rlwe/examples/gadget_product.rsRaw
1use base2k::{Encoding, FFT64, SvpPPolOps, VecZnx, VecZnxApi, VmpPMat};
2use rlwe::{
3 ciphertext::{Ciphertext, new_gadget_ciphertext},
4 decryptor::decrypt_rlwe_thread_safe,
5 encryptor::{encrypt_grlwe_sk_thread_safe, encrypt_grlwe_sk_tmp_bytes},
6 evaluator::{gadget_product_inplace, gadget_product_tmp_bytes},
7 key_generator::gen_switching_key_thread_safe_tmp_bytes,
8 keys::SecretKey,
9 parameters::{Parameters, ParametersLiteral},
10 plaintext::Plaintext,
11};
12use sampling::source::Source;
13
14fn main() {
15 let params_lit: ParametersLiteral = ParametersLiteral {
16 log_n: 4,
17 log_q: 68,
18 log_p: 17,
19 log_base2k: 17,
20 log_scale: 20,
21 xe: 3.2,
22 xs: 8,
23 };
24
25 let params: Parameters = Parameters::new::<FFT64>(¶ms_lit);
26
27 let mut tmp_bytes: Vec<u8> = vec![
28 0u8;
29 params.decrypt_rlwe_thread_safe_tmp_byte(params.log_q())
30 | params.encrypt_rlwe_sk_tmp_bytes(params.log_q())
31 | gen_switching_key_thread_safe_tmp_bytes(
32 params.module(),
33 params.log_base2k(),
34 params.limbs_q(),
35 params.log_q()
36 )
37 | gadget_product_tmp_bytes(
38 params.module(),
39 params.log_base2k(),
40 params.log_q(),
41 params.log_q(),
42 params.limbs_q(),
43 params.log_qp()
44 )
45 | encrypt_grlwe_sk_tmp_bytes(
46 params.module(),
47 params.log_base2k(),
48 params.limbs_qp(),
49 params.log_qp()
50 )
51 ];
52
53 let mut source: Source = Source::new([3; 32]);
54
55 let mut sk0: SecretKey = SecretKey::new(params.module());
56 let mut sk1: SecretKey = SecretKey::new(params.module());
57
58 sk0.fill_ternary_hw(params.xs(), &mut source);
59 sk1.fill_ternary_hw(params.xs(), &mut source);
60
61 let mut want = vec![i64::default(); params.n()];
62
63 want.iter_mut().enumerate().for_each(|(i, x)| *x = i as i64);
64
65 let log_base2k = params.log_base2k();
66
67 let log_k: usize = params.log_q() - 2 * log_base2k;
68
69 let mut source_xe: Source = Source::new([4; 32]);
70 let mut source_xa: Source = Source::new([5; 32]);
71
72 let mut sk0_svp_ppol: base2k::SvpPPol = params.module().new_svp_ppol();
73 params.module().svp_prepare(&mut sk0_svp_ppol, &sk0.0);
74
75 let mut sk1_svp_ppol: base2k::SvpPPol = params.module().new_svp_ppol();
76 params.module().svp_prepare(&mut sk1_svp_ppol, &sk1.0);
77
78 let mut gadget_ct: Ciphertext<VmpPMat> = new_gadget_ciphertext(
79 params.module(),
80 log_base2k,
81 params.limbs_q(),
82 params.log_qp(),
83 );
84
85 encrypt_grlwe_sk_thread_safe(
86 params.module(),
87 &mut gadget_ct,
88 &sk0.0,
89 &sk1_svp_ppol,
90 &mut source_xa,
91 &mut source_xe,
92 params.xe(),
93 &mut tmp_bytes,
94 );
95
96 let mut pt: Plaintext<VecZnx> =
97 Plaintext::<VecZnx>::new(params.module(), params.log_base2k(), params.log_q());
98
99 let mut want = vec![i64::default(); params.n()];
100 want.iter_mut().enumerate().for_each(|(i, x)| *x = i as i64);
101 pt.0.value[0].encode_vec_i64(log_base2k, log_k, &want, 32);
102 pt.0.value[0].normalize(log_base2k, &mut tmp_bytes);
103
104 let mut ct: Ciphertext<VecZnx> = params.new_ciphertext(params.log_q());
105
106 params.encrypt_rlwe_sk_thread_safe(
107 &mut ct,
108 Some(&pt),
109 &sk0_svp_ppol,
110 &mut source_xa,
111 &mut source_xe,
112 &mut tmp_bytes,
113 );
114
115 gadget_product_inplace::<true, _>(params.module(), &mut ct.0, &gadget_ct, &mut tmp_bytes);
116
117 println!("ct.limbs()={}", ct.cols());
118 println!("gadget_ct.rows()={}", gadget_ct.rows());
119 println!("gadget_ct.cols()={}", gadget_ct.cols());
120 println!("res.limbs()={}", ct.cols());
121 println!();
122
123 decrypt_rlwe_thread_safe(
124 params.module(),
125 &mut pt.0,
126 &ct.0,
127 &sk1_svp_ppol,
128 &mut tmp_bytes,
129 );
130
131 pt.0.value[0].print(pt.cols(), 16);
132
133 let mut have: Vec<i64> = vec![i64::default(); params.n()];
134
135 println!("pt: {}", log_k);
136 pt.0.value[0].decode_vec_i64(pt.log_base2k(), log_k, &mut have);
137
138 println!("want: {:?}", &want[..16]);
139 println!("have: {:?}", &have[..16]);
140}