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