arnaucube
arnaucube/poulpyPublic Self-hosted repository
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    logq: 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 = (logq 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}