poulpy/core/src/test_fft64/mod.rs
core/src/test_fft64/mod.rsRaw
1mod automorphism_key;
2mod gglwe;
3mod ggsw;
4mod glwe;
5mod glwe_fourier;
6mod glwe_packing;
7mod tensor_key;
8mod trace;
9
10pub(crate) fn var_noise_gglwe_product(
11 n: f64,
12 basek: usize,
13 var_xs: f64,
14 var_msg: f64,
15 var_a_err: f64,
16 var_gct_err_lhs: f64,
17 var_gct_err_rhs: f64,
18 rank_in: f64,
19 a_logq: usize,
20 b_logq: usize,
21) -> f64 {
22 let a_logq: usize = a_logq.min(b_logq);
23 let a_cols: usize = (a_logq + basek - 1) / basek;
24
25 let b_scale: f64 = (b_logq as f64).exp2();
26 let a_scale: f64 = ((b_logq - a_logq) as f64).exp2();
27
28 let base: f64 = (basek as f64).exp2();
29 let var_base: f64 = base * base / 12f64;
30
31 // lhs = a_cols * n * (var_base * var_gct_err_lhs + var_e_a * var_msg * p^2)
32 // rhs = a_cols * n * var_base * var_gct_err_rhs * var_xs
33 let mut noise: f64 = (a_cols as f64) * n * var_base * (var_gct_err_lhs + var_xs * var_gct_err_rhs);
34 noise += var_msg * var_a_err * a_scale * a_scale * n;
35 noise *= rank_in;
36 noise /= b_scale * b_scale;
37 noise
38}
39
40pub(crate) fn log2_std_noise_gglwe_product(
41 n: f64,
42 basek: usize,
43 var_xs: f64,
44 var_msg: f64,
45 var_a_err: f64,
46 var_gct_err_lhs: f64,
47 var_gct_err_rhs: f64,
48 rank_in: f64,
49 a_logq: usize,
50 b_logq: usize,
51) -> f64 {
52 let mut noise: f64 = var_noise_gglwe_product(
53 n,
54 basek,
55 var_xs,
56 var_msg,
57 var_a_err,
58 var_gct_err_lhs,
59 var_gct_err_rhs,
60 rank_in,
61 a_logq,
62 b_logq,
63 );
64 noise = noise.sqrt();
65 noise.log2().min(-1.0) // max noise is [-2^{-1}, 2^{-1}]
66}
67
68pub(crate) fn noise_ggsw_product(
69 n: f64,
70 basek: usize,
71 var_xs: f64,
72 var_msg: f64,
73 var_a0_err: f64,
74 var_a1_err: f64,
75 var_gct_err_lhs: f64,
76 var_gct_err_rhs: f64,
77 rank: f64,
78 k_in: usize,
79 k_ggsw: usize,
80) -> f64 {
81 let a_logq: usize = k_in.min(k_ggsw);
82 let a_cols: usize = (a_logq + basek - 1) / basek;
83
84 let b_scale: f64 = (k_ggsw as f64).exp2();
85 let a_scale: f64 = ((k_ggsw - a_logq) as f64).exp2();
86
87 let base: f64 = (basek as f64).exp2();
88 let var_base: f64 = base * base / 12f64;
89
90 // lhs = a_cols * n * (var_base * var_gct_err_lhs + var_e_a * var_msg * p^2)
91 // rhs = a_cols * n * var_base * var_gct_err_rhs * var_xs
92 let mut noise: f64 = (rank + 1.0) * (a_cols as f64) * n * var_base * (var_gct_err_lhs + var_xs * var_gct_err_rhs);
93 noise += var_msg * var_a0_err * a_scale * a_scale * n;
94 noise += var_msg * var_a1_err * a_scale * a_scale * n * var_xs * rank;
95 noise = noise.sqrt();
96 noise /= b_scale;
97 noise.log2().min(-1.0) // max noise is [-2^{-1}, 2^{-1}]
98}
99
100pub(crate) fn noise_ggsw_keyswitch(
101 n: f64,
102 basek: usize,
103 col: usize,
104 var_xs: f64,
105 var_a_err: f64,
106 var_gct_err_lhs: f64,
107 var_gct_err_rhs: f64,
108 rank: f64,
109 k_ct: usize,
110 k_ksk: usize,
111 k_tsk: usize,
112) -> f64 {
113 let var_si_x_sj: f64 = n * var_xs * var_xs;
114
115 // Initial KS for col = 0
116 let mut noise: f64 = var_noise_gglwe_product(
117 n,
118 basek,
119 var_xs,
120 var_xs,
121 var_a_err,
122 var_gct_err_lhs,
123 var_gct_err_rhs,
124 rank,
125 k_ct,
126 k_ksk,
127 );
128
129 // Other GGSW reconstruction for col > 0
130 if col > 0 {
131 noise += var_noise_gglwe_product(
132 n,
133 basek,
134 var_xs,
135 var_si_x_sj,
136 var_a_err + 1f64 / 12.0,
137 var_gct_err_lhs,
138 var_gct_err_rhs,
139 rank,
140 k_ct,
141 k_tsk,
142 );
143 noise += n * noise * var_xs * 0.5;
144 }
145
146 noise = noise.sqrt();
147 noise.log2().min(-1.0) // max noise is [-2^{-1}, 2^{-1}]
148}