mirror of
https://github.com/arnaucube/poulpy.git
synced 2026-02-10 05:06:44 +01:00
fixed automorphism on gglwe for k_out < k_in
This commit is contained in:
@@ -249,24 +249,33 @@ impl<DataSelf: AsMut<[u8]> + AsRef<[u8]>> AutomorphismKey<DataSelf, FFT64> {
|
|||||||
self.rank_out(),
|
self.rank_out(),
|
||||||
rhs.rank_out()
|
rhs.rank_out()
|
||||||
);
|
);
|
||||||
|
assert!(
|
||||||
|
self.k() <= lhs.k(),
|
||||||
|
"output k={} cannot be greater than input k={}",
|
||||||
|
self.k(),
|
||||||
|
lhs.k()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let cols_out: usize = rhs.rank_out() + 1;
|
let cols_out: usize = rhs.rank_out() + 1;
|
||||||
|
|
||||||
let (mut tmp_dft, scratch1) = scratch.tmp_glwe_fourier(module, lhs.basek(), lhs.k(), lhs.rank());
|
|
||||||
|
|
||||||
(0..self.rank_in()).for_each(|col_i| {
|
(0..self.rank_in()).for_each(|col_i| {
|
||||||
(0..self.rows()).for_each(|row_j| {
|
(0..self.rows()).for_each(|row_j| {
|
||||||
|
let (mut tmp_idft_data, scratct1) = scratch.tmp_vec_znx_big(module, cols_out, self.size());
|
||||||
|
|
||||||
|
{
|
||||||
|
let (mut tmp_dft, scratch2) = scratct1.tmp_glwe_fourier(module, lhs.basek(), lhs.k(), lhs.rank());
|
||||||
|
|
||||||
// Extracts relevant row
|
// Extracts relevant row
|
||||||
lhs.get_row(module, row_j, col_i, &mut tmp_dft);
|
lhs.get_row(module, row_j, col_i, &mut tmp_dft);
|
||||||
|
|
||||||
// Get a VecZnxBig from scratch space
|
// Get a VecZnxBig from scratch space
|
||||||
let (mut tmp_idft_data, scratch2) = scratch1.tmp_vec_znx_big(module, cols_out, self.size());
|
|
||||||
|
|
||||||
// Switches input outside of DFT
|
// Switches input outside of DFT
|
||||||
(0..cols_out).for_each(|i| {
|
(0..cols_out).for_each(|i| {
|
||||||
module.vec_znx_idft(&mut tmp_idft_data, i, &tmp_dft.data, i, scratch2);
|
module.vec_znx_idft(&mut tmp_idft_data, i, &tmp_dft.data, i, scratch2);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Consumes to small vec znx
|
// Consumes to small vec znx
|
||||||
let mut tmp_idft_small_data: VecZnx<&mut [u8]> = tmp_idft_data.to_vec_znx_small();
|
let mut tmp_idft_small_data: VecZnx<&mut [u8]> = tmp_idft_data.to_vec_znx_small();
|
||||||
@@ -284,7 +293,10 @@ impl<DataSelf: AsMut<[u8]> + AsRef<[u8]>> AutomorphismKey<DataSelf, FFT64> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Key-switch (-sa + pi_{k}(s), a) to (-pi^{-1}_{k'}(s)a + pi_{k}(s), a)
|
// Key-switch (-sa + pi_{k}(s), a) to (-pi^{-1}_{k'}(s)a + pi_{k}(s), a)
|
||||||
tmp_idft.keyswitch_inplace(module, &rhs.key, scratch2);
|
tmp_idft.keyswitch_inplace(module, &rhs.key, scratct1);
|
||||||
|
|
||||||
|
{
|
||||||
|
let (mut tmp_dft, _) = scratct1.tmp_glwe_fourier(module, self.basek(), self.k(), self.rank());
|
||||||
|
|
||||||
// Applies back the automorphism X^{k}: (-pi^{-1}_{k'}(s)a + pi_{k}(s), a) -> (-pi^{-1}_{k'+k}(s)a + s, a)
|
// Applies back the automorphism X^{k}: (-pi^{-1}_{k'}(s)a + pi_{k}(s), a) -> (-pi^{-1}_{k'+k}(s)a + s, a)
|
||||||
// and switches back to DFT domain
|
// and switches back to DFT domain
|
||||||
@@ -295,9 +307,11 @@ impl<DataSelf: AsMut<[u8]> + AsRef<[u8]>> AutomorphismKey<DataSelf, FFT64> {
|
|||||||
|
|
||||||
// Sets back the relevant row
|
// Sets back the relevant row
|
||||||
self.set_row(module, row_j, col_i, &tmp_dft);
|
self.set_row(module, row_j, col_i, &tmp_dft);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let (mut tmp_dft, _) = scratch.tmp_glwe_fourier(module, self.basek(), self.k(), self.rank());
|
||||||
tmp_dft.data.zero();
|
tmp_dft.data.zero();
|
||||||
|
|
||||||
(self.rows().min(lhs.rows())..self.rows()).for_each(|row_i| {
|
(self.rows().min(lhs.rows())..self.rows()).for_each(|row_i| {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ fn automorphism() {
|
|||||||
let log_n: usize = 8;
|
let log_n: usize = 8;
|
||||||
let basek: usize = 12;
|
let basek: usize = 12;
|
||||||
let k_in: usize = 60;
|
let k_in: usize = 60;
|
||||||
let k_out: usize = 60;
|
let k_out: usize = 40;
|
||||||
let digits: usize = k_in.div_ceil(basek);
|
let digits: usize = k_in.div_ceil(basek);
|
||||||
let sigma: f64 = 3.2;
|
let sigma: f64 = 3.2;
|
||||||
(1..4).for_each(|rank| {
|
(1..4).for_each(|rank| {
|
||||||
@@ -141,12 +141,12 @@ fn test_automorphism(
|
|||||||
sigma * sigma,
|
sigma * sigma,
|
||||||
0f64,
|
0f64,
|
||||||
rank as f64,
|
rank as f64,
|
||||||
k_in,
|
k_out,
|
||||||
k_apply,
|
k_apply,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
(noise_have - noise_want).abs() <= 0.5,
|
noise_have < noise_want + 0.5,
|
||||||
"{} {}",
|
"{} {}",
|
||||||
noise_have,
|
noise_have,
|
||||||
noise_want
|
noise_want
|
||||||
@@ -260,7 +260,7 @@ fn test_automorphism_inplace(
|
|||||||
);
|
);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
(noise_have - noise_want).abs() <= 0.5,
|
noise_have < noise_want + 0.5,
|
||||||
"{} {}",
|
"{} {}",
|
||||||
noise_have,
|
noise_have,
|
||||||
noise_want
|
noise_want
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ pub(crate) fn log2_std_noise_gglwe_product(
|
|||||||
b_logq,
|
b_logq,
|
||||||
);
|
);
|
||||||
noise = noise.sqrt();
|
noise = noise.sqrt();
|
||||||
noise.log2().min(-1.0) // max noise is [-2^{-1}, 2^{-1}]
|
noise.log2().min(-1.0).max(-(a_logq as f64)) // max noise is [-2^{-1}, 2^{-1}]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn noise_ggsw_product(
|
pub(crate) fn noise_ggsw_product(
|
||||||
|
|||||||
Reference in New Issue
Block a user