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