mirror of
https://github.com/arnaucube/poulpy.git
synced 2026-02-10 05:06:44 +01:00
Remove Zn (replaced by VecZnx), add more cross-base2k ops & tests
This commit is contained in:
@@ -9,10 +9,10 @@ use crate::{
|
||||
encryption::SIGMA,
|
||||
layouts::{
|
||||
GGLWEInfos, GLWEAutomorphismKey, GLWEAutomorphismKeyLayout, GLWEAutomorphismKeyPreparedFactory, GLWEPlaintext,
|
||||
GLWESecret, GLWESecretPreparedFactory,
|
||||
GLWESecret, GLWESecretPreparedFactory, LWEInfos,
|
||||
prepared::{GLWEAutomorphismKeyPrepared, GLWESecretPrepared},
|
||||
},
|
||||
noise::log2_std_noise_gglwe_product,
|
||||
var_noise_gglwe_product_v2,
|
||||
};
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
@@ -29,26 +29,27 @@ where
|
||||
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||
Scratch<BE>: ScratchAvailable + ScratchTakeCore<BE>,
|
||||
{
|
||||
let base2k: usize = 12;
|
||||
let k_in: usize = 60;
|
||||
let k_out: usize = 40;
|
||||
let dsize: usize = k_in.div_ceil(base2k);
|
||||
let base2k_in: usize = 17;
|
||||
let base2k_key: usize = 13;
|
||||
let base2k_out: usize = base2k_in; // MUST BE SAME
|
||||
let k_in: usize = 102;
|
||||
let max_dsize: usize = k_in.div_ceil(base2k_key);
|
||||
let p0: i64 = -1;
|
||||
let p1: i64 = -5;
|
||||
for rank in 1_usize..3 {
|
||||
for di in 1..dsize + 1 {
|
||||
let k_apply: usize = (dsize + di) * base2k;
|
||||
for dsize in 1..max_dsize + 1 {
|
||||
let k_ksk: usize = k_in + base2k_key * dsize;
|
||||
let k_out: usize = k_ksk; // Better capture noise.
|
||||
|
||||
let n: usize = module.n();
|
||||
let dsize_in: usize = 1;
|
||||
|
||||
let dnum_in: usize = k_in / (base2k * di);
|
||||
let dnum_out: usize = k_out / (base2k * di);
|
||||
let dnum_apply: usize = k_in.div_ceil(base2k * di);
|
||||
let dnum_in: usize = k_in / base2k_in;
|
||||
let dnum_ksk: usize = k_in.div_ceil(base2k_key * dsize);
|
||||
|
||||
let auto_key_in_infos: GLWEAutomorphismKeyLayout = GLWEAutomorphismKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_in.into(),
|
||||
k: k_in.into(),
|
||||
dnum: dnum_in.into(),
|
||||
dsize: dsize_in.into(),
|
||||
@@ -57,19 +58,19 @@ where
|
||||
|
||||
let auto_key_out_infos: GLWEAutomorphismKeyLayout = GLWEAutomorphismKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_out.into(),
|
||||
k: k_out.into(),
|
||||
dnum: dnum_out.into(),
|
||||
dnum: dnum_in.into(),
|
||||
dsize: dsize_in.into(),
|
||||
rank: rank.into(),
|
||||
};
|
||||
|
||||
let auto_key_apply_infos: GLWEAutomorphismKeyLayout = GLWEAutomorphismKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
k: k_apply.into(),
|
||||
dnum: dnum_apply.into(),
|
||||
dsize: di.into(),
|
||||
base2k: base2k_key.into(),
|
||||
k: k_ksk.into(),
|
||||
dnum: dnum_ksk.into(),
|
||||
dsize: dsize.into(),
|
||||
rank: rank.into(),
|
||||
};
|
||||
|
||||
@@ -83,13 +84,16 @@ where
|
||||
|
||||
let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(
|
||||
GLWEAutomorphismKey::encrypt_sk_tmp_bytes(module, &auto_key_in_infos)
|
||||
| GLWEAutomorphismKey::encrypt_sk_tmp_bytes(module, &auto_key_apply_infos)
|
||||
| GLWEAutomorphismKey::automorphism_tmp_bytes(
|
||||
.max(GLWEAutomorphismKey::encrypt_sk_tmp_bytes(
|
||||
module,
|
||||
&auto_key_apply_infos,
|
||||
))
|
||||
.max(GLWEAutomorphismKey::automorphism_tmp_bytes(
|
||||
module,
|
||||
&auto_key_out_infos,
|
||||
&auto_key_in_infos,
|
||||
&auto_key_apply_infos,
|
||||
),
|
||||
)),
|
||||
);
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&auto_key_in);
|
||||
@@ -128,7 +132,7 @@ where
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&auto_key_out_infos);
|
||||
let mut pt_out: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&auto_key_out_infos);
|
||||
|
||||
let mut sk_auto: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&auto_key_out_infos);
|
||||
sk_auto.fill_zero(); // Necessary to avoid panic of unfilled sk
|
||||
@@ -145,41 +149,44 @@ where
|
||||
let mut sk_auto_dft: GLWESecretPrepared<Vec<u8>, BE> = GLWESecretPrepared::alloc_from_infos(module, &sk_auto);
|
||||
sk_auto_dft.prepare(module, &sk_auto);
|
||||
|
||||
(0..auto_key_out.rank_in().into()).for_each(|col_i| {
|
||||
(0..auto_key_out.dnum().into()).for_each(|row_i| {
|
||||
for col_i in 0..auto_key_out.rank_in().into() {
|
||||
for row_i in 0..auto_key_out.dnum().into() {
|
||||
auto_key_out
|
||||
.at(row_i, col_i)
|
||||
.decrypt(module, &mut pt, &sk_auto_dft, scratch.borrow());
|
||||
.decrypt(module, &mut pt_out, &sk_auto_dft, scratch.borrow());
|
||||
|
||||
module.vec_znx_sub_scalar_inplace(
|
||||
&mut pt.data,
|
||||
&mut pt_out.data,
|
||||
0,
|
||||
(dsize_in - 1) + row_i * dsize_in,
|
||||
&sk.data,
|
||||
col_i,
|
||||
);
|
||||
|
||||
let noise_have: f64 = pt.data.stats(base2k, 0).std().log2();
|
||||
let noise_want: f64 = log2_std_noise_gglwe_product(
|
||||
n as f64,
|
||||
base2k * di,
|
||||
let noise_have: f64 = pt_out.data.stats(pt_out.base2k().into(), 0).std().log2();
|
||||
let max_noise: f64 = var_noise_gglwe_product_v2(
|
||||
module.n() as f64,
|
||||
k_ksk,
|
||||
dnum_ksk,
|
||||
dsize,
|
||||
base2k_key,
|
||||
0.5,
|
||||
0.5,
|
||||
0f64,
|
||||
SIGMA * SIGMA,
|
||||
0f64,
|
||||
rank as f64,
|
||||
k_out,
|
||||
k_apply,
|
||||
);
|
||||
)
|
||||
.sqrt()
|
||||
.log2();
|
||||
|
||||
assert!(
|
||||
noise_have < noise_want + 0.5,
|
||||
noise_have < max_noise + 0.5,
|
||||
"{noise_have} {}",
|
||||
noise_want + 0.5
|
||||
max_noise + 0.5
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -198,25 +205,27 @@ where
|
||||
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||
Scratch<BE>: ScratchAvailable + ScratchTakeCore<BE>,
|
||||
{
|
||||
let base2k: usize = 12;
|
||||
let k_in: usize = 60;
|
||||
let dsize: usize = k_in.div_ceil(base2k);
|
||||
let base2k_out: usize = 17;
|
||||
let base2k_key: usize = 13;
|
||||
let k_out: usize = 102;
|
||||
let max_dsize: usize = k_out.div_ceil(base2k_key);
|
||||
|
||||
let p0: i64 = -1;
|
||||
let p1: i64 = -5;
|
||||
for rank in 1_usize..3 {
|
||||
for di in 1..dsize + 1 {
|
||||
let k_apply: usize = (dsize + di) * base2k;
|
||||
for dsize in 1..max_dsize + 1 {
|
||||
let k_ksk: usize = k_out + base2k_key * dsize;
|
||||
|
||||
let n: usize = module.n();
|
||||
let dsize_in: usize = 1;
|
||||
|
||||
let dnum_in: usize = k_in / (base2k * di);
|
||||
let dnum_apply: usize = k_in.div_ceil(base2k * di);
|
||||
let dnum_in: usize = k_out / base2k_out;
|
||||
let dnum_ksk: usize = k_out.div_ceil(base2k_key * dsize);
|
||||
|
||||
let auto_key_layout: GLWEAutomorphismKeyLayout = GLWEAutomorphismKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
k: k_in.into(),
|
||||
base2k: base2k_out.into(),
|
||||
k: k_out.into(),
|
||||
dnum: dnum_in.into(),
|
||||
dsize: dsize_in.into(),
|
||||
rank: rank.into(),
|
||||
@@ -224,10 +233,10 @@ where
|
||||
|
||||
let auto_key_apply_layout: GLWEAutomorphismKeyLayout = GLWEAutomorphismKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
k: k_apply.into(),
|
||||
dnum: dnum_apply.into(),
|
||||
dsize: di.into(),
|
||||
base2k: base2k_key.into(),
|
||||
k: k_ksk.into(),
|
||||
dnum: dnum_ksk.into(),
|
||||
dsize: dsize.into(),
|
||||
rank: rank.into(),
|
||||
};
|
||||
|
||||
@@ -306,24 +315,27 @@ where
|
||||
col_i,
|
||||
);
|
||||
|
||||
let noise_have: f64 = pt.data.stats(base2k, 0).std().log2();
|
||||
let noise_want: f64 = log2_std_noise_gglwe_product(
|
||||
n as f64,
|
||||
base2k * di,
|
||||
let noise_have: f64 = pt.data.stats(pt.base2k().into(), 0).std().log2();
|
||||
let max_noise: f64 = var_noise_gglwe_product_v2(
|
||||
module.n() as f64,
|
||||
k_ksk,
|
||||
dnum_ksk,
|
||||
dsize,
|
||||
base2k_key,
|
||||
0.5,
|
||||
0.5,
|
||||
0f64,
|
||||
SIGMA * SIGMA,
|
||||
0f64,
|
||||
rank as f64,
|
||||
k_in,
|
||||
k_apply,
|
||||
);
|
||||
)
|
||||
.sqrt()
|
||||
.log2();
|
||||
|
||||
assert!(
|
||||
noise_have < noise_want + 0.5,
|
||||
noise_have < max_noise + 0.5,
|
||||
"{noise_have} {}",
|
||||
noise_want + 0.5
|
||||
max_noise + 0.5
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,26 +29,28 @@ where
|
||||
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||
Scratch<BE>: ScratchAvailable + ScratchTakeCore<BE>,
|
||||
{
|
||||
let base2k: usize = 12;
|
||||
let k_in: usize = 54;
|
||||
let dsize: usize = k_in.div_ceil(base2k);
|
||||
let p: i64 = -5;
|
||||
let base2k_in: usize = 17;
|
||||
let base2k_key: usize = 13;
|
||||
let base2k_out: usize = base2k_in; // MUST BE SAME
|
||||
let k_in: usize = 102;
|
||||
let max_dsize: usize = k_in.div_ceil(base2k_key);
|
||||
|
||||
let p: i64 = -5;
|
||||
for rank in 1_usize..3 {
|
||||
for di in 1..dsize + 1 {
|
||||
let k_ksk: usize = k_in + base2k * di;
|
||||
for dsize in 1..max_dsize + 1 {
|
||||
let k_ksk: usize = k_in + base2k_key * dsize;
|
||||
let k_tsk: usize = k_ksk;
|
||||
let k_out: usize = k_ksk; // Better capture noise.
|
||||
|
||||
let n: usize = module.n();
|
||||
let dnum: usize = k_in.div_ceil(base2k * di);
|
||||
let dnum_in: usize = k_in.div_euclid(base2k * di);
|
||||
let dnum_in: usize = k_in / base2k_in;
|
||||
let dnum_ksk: usize = k_in.div_ceil(base2k_key * dsize);
|
||||
|
||||
let dsize_in: usize = 1;
|
||||
|
||||
let ggsw_in_layout: GGSWLayout = GGSWLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_in.into(),
|
||||
k: k_in.into(),
|
||||
dnum: dnum_in.into(),
|
||||
dsize: dsize_in.into(),
|
||||
@@ -57,7 +59,7 @@ where
|
||||
|
||||
let ggsw_out_layout: GGSWLayout = GGSWLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_out.into(),
|
||||
k: k_out.into(),
|
||||
dnum: dnum_in.into(),
|
||||
dsize: dsize_in.into(),
|
||||
@@ -66,19 +68,19 @@ where
|
||||
|
||||
let tsk_layout: GGLWEToGGSWKeyLayout = GGLWEToGGSWKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_key.into(),
|
||||
k: k_tsk.into(),
|
||||
dnum: dnum.into(),
|
||||
dsize: di.into(),
|
||||
dnum: dnum_ksk.into(),
|
||||
dsize: dsize.into(),
|
||||
rank: rank.into(),
|
||||
};
|
||||
|
||||
let auto_key_layout: GGLWEToGGSWKeyLayout = GGLWEToGGSWKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_key.into(),
|
||||
k: k_ksk.into(),
|
||||
dnum: dnum.into(),
|
||||
dsize: di.into(),
|
||||
dnum: dnum_ksk.into(),
|
||||
dsize: dsize.into(),
|
||||
rank: rank.into(),
|
||||
};
|
||||
|
||||
@@ -154,7 +156,7 @@ where
|
||||
let max_noise = |col_j: usize| -> f64 {
|
||||
noise_ggsw_keyswitch(
|
||||
n as f64,
|
||||
base2k * di,
|
||||
base2k_key * dsize,
|
||||
col_j,
|
||||
var_xs,
|
||||
0f64,
|
||||
@@ -187,23 +189,25 @@ where
|
||||
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||
Scratch<BE>: ScratchAvailable + ScratchTakeCore<BE>,
|
||||
{
|
||||
let base2k: usize = 12;
|
||||
let k_out: usize = 54;
|
||||
let dsize: usize = k_out.div_ceil(base2k);
|
||||
let base2k_out: usize = 17;
|
||||
let base2k_key: usize = 13;
|
||||
let k_out: usize = 102;
|
||||
let max_dsize: usize = k_out.div_ceil(base2k_key);
|
||||
|
||||
let p: i64 = -1;
|
||||
for rank in 1_usize..3 {
|
||||
for di in 1..dsize + 1 {
|
||||
let k_ksk: usize = k_out + base2k * di;
|
||||
for dsize in 1..max_dsize + 1 {
|
||||
let k_ksk: usize = k_out + base2k_key * dsize;
|
||||
let k_tsk: usize = k_ksk;
|
||||
|
||||
let n: usize = module.n();
|
||||
let dnum: usize = k_out.div_ceil(di * base2k);
|
||||
let dnum_in: usize = k_out.div_euclid(base2k * di);
|
||||
let dnum_in: usize = k_out / base2k_out;
|
||||
let dnum_ksk: usize = k_out.div_ceil(base2k_key * dsize);
|
||||
let dsize_in: usize = 1;
|
||||
|
||||
let ggsw_out_layout: GGSWLayout = GGSWLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_out.into(),
|
||||
k: k_out.into(),
|
||||
dnum: dnum_in.into(),
|
||||
dsize: dsize_in.into(),
|
||||
@@ -212,19 +216,19 @@ where
|
||||
|
||||
let tsk_layout: GGLWEToGGSWKeyLayout = GGLWEToGGSWKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_key.into(),
|
||||
k: k_tsk.into(),
|
||||
dnum: dnum.into(),
|
||||
dsize: di.into(),
|
||||
dnum: dnum_ksk.into(),
|
||||
dsize: dsize.into(),
|
||||
rank: rank.into(),
|
||||
};
|
||||
|
||||
let auto_key_layout: GGLWEToGGSWKeyLayout = GGLWEToGGSWKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_key.into(),
|
||||
k: k_ksk.into(),
|
||||
dnum: dnum.into(),
|
||||
dsize: di.into(),
|
||||
dnum: dnum_ksk.into(),
|
||||
dsize: dsize.into(),
|
||||
rank: rank.into(),
|
||||
};
|
||||
|
||||
@@ -293,7 +297,7 @@ where
|
||||
let max_noise = |col_j: usize| -> f64 {
|
||||
noise_ggsw_keyswitch(
|
||||
n as f64,
|
||||
base2k * di,
|
||||
base2k_key * dsize,
|
||||
col_j,
|
||||
var_xs,
|
||||
0f64,
|
||||
|
||||
@@ -5,14 +5,14 @@ use poulpy_hal::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
GLWEAutomorphism, GLWEAutomorphismKeyEncryptSk, GLWEDecrypt, GLWEEncryptSk, GLWENoise, ScratchTakeCore,
|
||||
GLWEAutomorphism, GLWEAutomorphismKeyEncryptSk, GLWEDecrypt, GLWEEncryptSk, GLWENoise, GLWENormalize, ScratchTakeCore,
|
||||
encryption::SIGMA,
|
||||
layouts::{
|
||||
GLWE, GLWEAutomorphismKey, GLWEAutomorphismKeyLayout, GLWEAutomorphismKeyPreparedFactory, GLWELayout, GLWEPlaintext,
|
||||
GLWESecret, GLWESecretPreparedFactory,
|
||||
prepared::{GLWEAutomorphismKeyPrepared, GLWESecretPrepared},
|
||||
},
|
||||
noise::log2_std_noise_gglwe_product,
|
||||
var_noise_gglwe_product_v2,
|
||||
};
|
||||
|
||||
pub fn test_glwe_automorphism<BE: Backend>(module: &Module<BE>)
|
||||
@@ -25,55 +25,59 @@ where
|
||||
+ GLWEAutomorphismKeyEncryptSk<BE>
|
||||
+ GLWEAutomorphismKeyPreparedFactory<BE>
|
||||
+ GLWENoise<BE>
|
||||
+ VecZnxAutomorphismInplace<BE>,
|
||||
+ VecZnxAutomorphismInplace<BE>
|
||||
+ GLWENormalize<BE>,
|
||||
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||
Scratch<BE>: ScratchAvailable + ScratchTakeCore<BE>,
|
||||
{
|
||||
let base2k: usize = 12;
|
||||
let k_in: usize = 60;
|
||||
let dsize: usize = k_in.div_ceil(base2k);
|
||||
let base2k_in: usize = 17;
|
||||
let base2k_key: usize = 13;
|
||||
let base2k_out: usize = 15;
|
||||
let k_in: usize = 102;
|
||||
let max_dsize: usize = k_in.div_ceil(base2k_key);
|
||||
let p: i64 = -5;
|
||||
for rank in 1_usize..3 {
|
||||
for di in 1..dsize + 1 {
|
||||
let k_ksk: usize = k_in + base2k * di;
|
||||
for dsize in 1..max_dsize + 1 {
|
||||
let k_ksk: usize = k_in + base2k_key * dsize;
|
||||
let k_out: usize = k_ksk; // Better capture noise.
|
||||
|
||||
let n: usize = module.n();
|
||||
let dnum: usize = k_in.div_ceil(base2k * dsize);
|
||||
let dnum: usize = k_in.div_ceil(base2k_key * dsize);
|
||||
|
||||
let ct_in_infos: GLWELayout = GLWELayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_in.into(),
|
||||
k: k_in.into(),
|
||||
rank: rank.into(),
|
||||
};
|
||||
|
||||
let ct_out_infos: GLWELayout = GLWELayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_out.into(),
|
||||
k: k_out.into(),
|
||||
rank: rank.into(),
|
||||
};
|
||||
|
||||
let autokey_infos: GLWEAutomorphismKeyLayout = GLWEAutomorphismKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_key.into(),
|
||||
k: k_out.into(),
|
||||
rank: rank.into(),
|
||||
dnum: dnum.into(),
|
||||
dsize: di.into(),
|
||||
dsize: dsize.into(),
|
||||
};
|
||||
|
||||
let mut autokey: GLWEAutomorphismKey<Vec<u8>> = GLWEAutomorphismKey::alloc_from_infos(&autokey_infos);
|
||||
let mut ct_in: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&ct_in_infos);
|
||||
let mut ct_out: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&ct_out_infos);
|
||||
let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&ct_out_infos);
|
||||
let mut pt_in: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&ct_in_infos);
|
||||
let mut pt_out: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&ct_out_infos);
|
||||
|
||||
let mut source_xs: Source = Source::new([0u8; 32]);
|
||||
let mut source_xe: Source = Source::new([0u8; 32]);
|
||||
let mut source_xa: Source = Source::new([0u8; 32]);
|
||||
|
||||
module.vec_znx_fill_uniform(base2k, &mut pt_want.data, 0, &mut source_xa);
|
||||
module.vec_znx_fill_uniform(base2k_in, &mut pt_in.data, 0, &mut source_xa);
|
||||
|
||||
let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(
|
||||
GLWEAutomorphismKey::encrypt_sk_tmp_bytes(module, &autokey)
|
||||
@@ -99,7 +103,7 @@ where
|
||||
|
||||
ct_in.encrypt_sk(
|
||||
module,
|
||||
&pt_want,
|
||||
&pt_in,
|
||||
&sk_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
@@ -112,22 +116,26 @@ where
|
||||
|
||||
ct_out.automorphism(module, &ct_in, &autokey_prepared, scratch.borrow());
|
||||
|
||||
let max_noise: f64 = log2_std_noise_gglwe_product(
|
||||
let max_noise: f64 = var_noise_gglwe_product_v2(
|
||||
module.n() as f64,
|
||||
base2k * dsize,
|
||||
k_ksk,
|
||||
dnum,
|
||||
max_dsize,
|
||||
base2k_key,
|
||||
0.5,
|
||||
0.5,
|
||||
0f64,
|
||||
SIGMA * SIGMA,
|
||||
0f64,
|
||||
rank as f64,
|
||||
k_in,
|
||||
k_ksk,
|
||||
);
|
||||
)
|
||||
.sqrt()
|
||||
.log2();
|
||||
|
||||
module.vec_znx_automorphism_inplace(p, &mut pt_want.data, 0, scratch.borrow());
|
||||
module.glwe_normalize(&mut pt_out, &pt_in, scratch.borrow());
|
||||
module.vec_znx_automorphism_inplace(p, &mut pt_out.data, 0, scratch.borrow());
|
||||
|
||||
ct_out.assert_noise(module, &sk_prepared, &pt_want, max_noise + 1.0);
|
||||
ct_out.assert_noise(module, &sk_prepared, &pt_out, max_noise + 1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,31 +155,33 @@ where
|
||||
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||
Scratch<BE>: ScratchAvailable + ScratchTakeCore<BE>,
|
||||
{
|
||||
let base2k: usize = 12;
|
||||
let k_out: usize = 60;
|
||||
let dsize: usize = k_out.div_ceil(base2k);
|
||||
let base2k_out: usize = 17;
|
||||
let base2k_key: usize = 13;
|
||||
let k_out: usize = 102;
|
||||
let max_dsize: usize = k_out.div_ceil(base2k_key);
|
||||
|
||||
let p = -5;
|
||||
for rank in 1_usize..3 {
|
||||
for di in 1..dsize + 1 {
|
||||
let k_ksk: usize = k_out + base2k * di;
|
||||
for dsize in 1..max_dsize + 1 {
|
||||
let k_ksk: usize = k_out + base2k_key * dsize;
|
||||
|
||||
let n: usize = module.n();
|
||||
let dnum: usize = k_out.div_ceil(base2k * dsize);
|
||||
let dnum: usize = k_out.div_ceil(base2k_key * dsize);
|
||||
|
||||
let ct_out_infos: GLWELayout = GLWELayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_out.into(),
|
||||
k: k_out.into(),
|
||||
rank: rank.into(),
|
||||
};
|
||||
|
||||
let autokey_infos: GLWEAutomorphismKeyLayout = GLWEAutomorphismKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_key.into(),
|
||||
k: k_ksk.into(),
|
||||
rank: rank.into(),
|
||||
dnum: dnum.into(),
|
||||
dsize: di.into(),
|
||||
dsize: dsize.into(),
|
||||
};
|
||||
|
||||
let mut autokey: GLWEAutomorphismKey<Vec<u8>> = GLWEAutomorphismKey::alloc_from_infos(&autokey_infos);
|
||||
@@ -182,7 +192,7 @@ where
|
||||
let mut source_xe: Source = Source::new([0u8; 32]);
|
||||
let mut source_xa: Source = Source::new([0u8; 32]);
|
||||
|
||||
module.vec_znx_fill_uniform(base2k, &mut pt_want.data, 0, &mut source_xa);
|
||||
module.vec_znx_fill_uniform(base2k_out, &mut pt_want.data, 0, &mut source_xa);
|
||||
|
||||
let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(
|
||||
GLWEAutomorphismKey::encrypt_sk_tmp_bytes(module, &autokey)
|
||||
@@ -221,18 +231,21 @@ where
|
||||
|
||||
ct.automorphism_inplace(module, &autokey_prepared, scratch.borrow());
|
||||
|
||||
let max_noise: f64 = log2_std_noise_gglwe_product(
|
||||
let max_noise: f64 = var_noise_gglwe_product_v2(
|
||||
module.n() as f64,
|
||||
base2k * dsize,
|
||||
k_ksk,
|
||||
dnum,
|
||||
dsize,
|
||||
base2k_key,
|
||||
0.5,
|
||||
0.5,
|
||||
0f64,
|
||||
SIGMA * SIGMA,
|
||||
0f64,
|
||||
rank as f64,
|
||||
k_out,
|
||||
k_ksk,
|
||||
);
|
||||
)
|
||||
.sqrt()
|
||||
.log2();
|
||||
|
||||
module.vec_znx_automorphism_inplace(p, &mut pt_want.data, 0, scratch.borrow());
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use poulpy_hal::{
|
||||
api::{ScratchAvailable, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxFillUniform},
|
||||
api::{ScratchAvailable, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxFillUniform, VecZnxNormalize},
|
||||
layouts::{Backend, FillUniform, Module, Scratch, ScratchOwned, ZnxView},
|
||||
source::Source,
|
||||
};
|
||||
@@ -104,7 +104,8 @@ where
|
||||
+ GLWEDecrypt<BE>
|
||||
+ GLWESecretPreparedFactory<BE>
|
||||
+ LWEEncryptSk<BE>
|
||||
+ LWEToGLWEKeyPreparedFactory<BE>,
|
||||
+ LWEToGLWEKeyPreparedFactory<BE>
|
||||
+ VecZnxNormalize<BE>,
|
||||
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||
Scratch<BE>: ScratchAvailable + ScratchTakeCore<BE>,
|
||||
{
|
||||
@@ -120,23 +121,23 @@ where
|
||||
|
||||
let lwe_to_glwe_infos: LWEToGLWEKeyLayout = LWEToGLWEKeyLayout {
|
||||
n: n_glwe,
|
||||
base2k: Base2K(17),
|
||||
k: TorusPrecision(51),
|
||||
base2k: Base2K(13),
|
||||
k: TorusPrecision(92),
|
||||
dnum: Dnum(2),
|
||||
rank_out: rank,
|
||||
};
|
||||
|
||||
let glwe_infos: GLWELayout = GLWELayout {
|
||||
n: n_glwe,
|
||||
base2k: Base2K(17),
|
||||
k: TorusPrecision(34),
|
||||
base2k: Base2K(15),
|
||||
k: TorusPrecision(75),
|
||||
rank,
|
||||
};
|
||||
|
||||
let lwe_infos: LWELayout = LWELayout {
|
||||
n: n_lwe,
|
||||
base2k: Base2K(17),
|
||||
k: TorusPrecision(34),
|
||||
k: TorusPrecision(75),
|
||||
};
|
||||
|
||||
let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(
|
||||
@@ -160,7 +161,14 @@ where
|
||||
lwe_pt.encode_i64(data, k_lwe_pt);
|
||||
|
||||
let mut lwe_ct: LWE<Vec<u8>> = LWE::alloc_from_infos(&lwe_infos);
|
||||
lwe_ct.encrypt_sk(module, &lwe_pt, &sk_lwe, &mut source_xa, &mut source_xe);
|
||||
lwe_ct.encrypt_sk(
|
||||
module,
|
||||
&lwe_pt,
|
||||
&sk_lwe,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut ksk: LWEToGLWEKey<Vec<u8>> = LWEToGLWEKey::alloc_from_infos(&lwe_to_glwe_infos);
|
||||
|
||||
@@ -183,7 +191,19 @@ where
|
||||
let mut glwe_pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_infos);
|
||||
glwe_ct.decrypt(module, &mut glwe_pt, &sk_glwe_prepared, scratch.borrow());
|
||||
|
||||
assert_eq!(glwe_pt.data.at(0, 0)[0], lwe_pt.data.at(0, 0)[0]);
|
||||
let mut lwe_pt_conv = LWEPlaintext::alloc(glwe_pt.base2k(), lwe_pt.k());
|
||||
|
||||
module.vec_znx_normalize(
|
||||
glwe_pt.base2k().as_usize(),
|
||||
lwe_pt_conv.data_mut(),
|
||||
0,
|
||||
lwe_pt.base2k().as_usize(),
|
||||
lwe_pt.data(),
|
||||
0,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
assert_eq!(glwe_pt.data.at(0, 0)[0], lwe_pt_conv.data.at(0, 0)[0]);
|
||||
}
|
||||
|
||||
pub fn test_glwe_to_lwe<BE: Backend>(module: &Module<BE>)
|
||||
@@ -196,7 +216,8 @@ where
|
||||
+ GLWEDecrypt<BE>
|
||||
+ GLWESecretPreparedFactory<BE>
|
||||
+ GLWEToLWESwitchingKeyEncryptSk<BE>
|
||||
+ GLWEToLWEKeyPreparedFactory<BE>,
|
||||
+ GLWEToLWEKeyPreparedFactory<BE>
|
||||
+ VecZnxNormalize<BE>,
|
||||
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||
Scratch<BE>: ScratchAvailable + ScratchTakeCore<BE>,
|
||||
{
|
||||
@@ -208,8 +229,8 @@ where
|
||||
|
||||
let glwe_to_lwe_infos: GLWEToLWEKeyLayout = GLWEToLWEKeyLayout {
|
||||
n: n_glwe,
|
||||
base2k: Base2K(17),
|
||||
k: TorusPrecision(51),
|
||||
base2k: Base2K(13),
|
||||
k: TorusPrecision(91),
|
||||
dnum: Dnum(2),
|
||||
rank_in: rank,
|
||||
};
|
||||
@@ -217,14 +238,14 @@ where
|
||||
let glwe_infos: GLWELayout = GLWELayout {
|
||||
n: n_glwe,
|
||||
base2k: Base2K(17),
|
||||
k: TorusPrecision(34),
|
||||
k: TorusPrecision(72),
|
||||
rank,
|
||||
};
|
||||
|
||||
let lwe_infos: LWELayout = LWELayout {
|
||||
n: n_lwe,
|
||||
base2k: Base2K(17),
|
||||
k: TorusPrecision(34),
|
||||
base2k: Base2K(15),
|
||||
k: TorusPrecision(72),
|
||||
};
|
||||
|
||||
let mut source_xs: Source = Source::new([0u8; 32]);
|
||||
@@ -284,7 +305,19 @@ where
|
||||
lwe_ct.from_glwe(module, &glwe_ct, a_idx, &ksk_prepared, scratch.borrow());
|
||||
|
||||
let mut lwe_pt: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc_from_infos(&lwe_infos);
|
||||
lwe_ct.decrypt(module, &mut lwe_pt, &sk_lwe);
|
||||
lwe_ct.decrypt(module, &mut lwe_pt, &sk_lwe, scratch.borrow());
|
||||
|
||||
assert_eq!(glwe_pt.data.at(0, 0)[a_idx], lwe_pt.data.at(0, 0)[0]);
|
||||
let mut glwe_pt_conv = GLWEPlaintext::alloc(glwe_ct.n(), lwe_pt.base2k(), lwe_pt.k());
|
||||
|
||||
module.vec_znx_normalize(
|
||||
lwe_pt.base2k().as_usize(),
|
||||
glwe_pt_conv.data_mut(),
|
||||
0,
|
||||
glwe_ct.base2k().as_usize(),
|
||||
glwe_pt.data(),
|
||||
0,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
assert_eq!(glwe_pt_conv.data.at(0, 0)[a_idx], lwe_pt.data.at(0, 0)[0]);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ use crate::{
|
||||
prepared::{GLWESecretPrepared, GLWESwitchingKeyPrepared},
|
||||
},
|
||||
noise::log2_std_noise_gglwe_product,
|
||||
var_noise_gglwe_product_v2,
|
||||
};
|
||||
|
||||
pub fn test_gglwe_switching_key_keyswitch<BE: Backend>(module: &Module<BE>)
|
||||
@@ -24,27 +25,29 @@ where
|
||||
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||
Scratch<BE>: ScratchAvailable + ScratchTakeCore<BE>,
|
||||
{
|
||||
let base2k: usize = 12;
|
||||
let k_in: usize = 60;
|
||||
let dsize: usize = k_in.div_ceil(base2k);
|
||||
let base2k_in: usize = 17;
|
||||
let base2k_key: usize = 13;
|
||||
let base2k_out: usize = base2k_in; // MUST BE SAME
|
||||
let k_in: usize = 102;
|
||||
let max_dsize: usize = k_in.div_ceil(base2k_key);
|
||||
|
||||
for rank_in_s0s1 in 1_usize..3 {
|
||||
for rank_in_s0s1 in 1_usize..2 {
|
||||
for rank_out_s0s1 in 1_usize..3 {
|
||||
for rank_out_s1s2 in 1_usize..3 {
|
||||
for di in 1_usize..dsize + 1 {
|
||||
let k_ksk: usize = k_in + base2k * di;
|
||||
for dsize in 1_usize..max_dsize + 1 {
|
||||
let k_ksk: usize = k_in + base2k_key * dsize;
|
||||
let k_out: usize = k_ksk; // Better capture noise.
|
||||
|
||||
let n: usize = module.n();
|
||||
let dnum: usize = k_in / base2k;
|
||||
let dnum_apply: usize = k_in.div_ceil(base2k * di);
|
||||
let dsize_in: usize = 1;
|
||||
let dnum_in: usize = k_in / base2k_in;
|
||||
let dnum_ksk: usize = k_in.div_ceil(base2k_key * dsize);
|
||||
|
||||
let gglwe_s0s1_infos: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_in.into(),
|
||||
k: k_in.into(),
|
||||
dnum: dnum.into(),
|
||||
dnum: dnum_in.into(),
|
||||
dsize: dsize_in.into(),
|
||||
rank_in: rank_in_s0s1.into(),
|
||||
rank_out: rank_out_s0s1.into(),
|
||||
@@ -52,19 +55,19 @@ where
|
||||
|
||||
let gglwe_s1s2_infos: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_key.into(),
|
||||
k: k_ksk.into(),
|
||||
dnum: dnum_apply.into(),
|
||||
dsize: di.into(),
|
||||
dnum: dnum_ksk.into(),
|
||||
dsize: dsize.into(),
|
||||
rank_in: rank_out_s0s1.into(),
|
||||
rank_out: rank_out_s1s2.into(),
|
||||
};
|
||||
|
||||
let gglwe_s0s2_infos: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_out.into(),
|
||||
k: k_out.into(),
|
||||
dnum: dnum_apply.into(),
|
||||
dnum: dnum_in.into(),
|
||||
dsize: dsize_in.into(),
|
||||
rank_in: rank_in_s0s1.into(),
|
||||
rank_out: rank_out_s1s2.into(),
|
||||
@@ -85,8 +88,8 @@ where
|
||||
);
|
||||
let mut scratch_apply: ScratchOwned<BE> = ScratchOwned::alloc(GLWESwitchingKey::keyswitch_tmp_bytes(
|
||||
module,
|
||||
&gglwe_s0s1_infos,
|
||||
&gglwe_s0s2_infos,
|
||||
&gglwe_s0s1_infos,
|
||||
&gglwe_s1s2_infos,
|
||||
));
|
||||
|
||||
@@ -135,18 +138,21 @@ where
|
||||
scratch_apply.borrow(),
|
||||
);
|
||||
|
||||
let max_noise: f64 = log2_std_noise_gglwe_product(
|
||||
n as f64,
|
||||
base2k * di,
|
||||
let max_noise: f64 = var_noise_gglwe_product_v2(
|
||||
module.n() as f64,
|
||||
k_ksk,
|
||||
dnum_ksk,
|
||||
dsize,
|
||||
base2k_key,
|
||||
0.5,
|
||||
0.5,
|
||||
0f64,
|
||||
SIGMA * SIGMA,
|
||||
0f64,
|
||||
rank_out_s0s1 as f64,
|
||||
k_in,
|
||||
k_ksk,
|
||||
);
|
||||
)
|
||||
.sqrt()
|
||||
.log2();
|
||||
|
||||
gglwe_s0s2
|
||||
.key
|
||||
@@ -168,23 +174,27 @@ where
|
||||
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||
Scratch<BE>: ScratchAvailable + ScratchTakeCore<BE>,
|
||||
{
|
||||
let base2k: usize = 12;
|
||||
let k_out: usize = 60;
|
||||
let dsize: usize = k_out.div_ceil(base2k);
|
||||
let base2k_out: usize = 17;
|
||||
let base2k_key: usize = 13;
|
||||
let k_out: usize = 102;
|
||||
let max_dsize: usize = k_out.div_ceil(base2k_key);
|
||||
|
||||
for rank_in in 1_usize..3 {
|
||||
for rank_out in 1_usize..3 {
|
||||
for di in 1_usize..dsize + 1 {
|
||||
let k_ksk: usize = k_out + base2k * di;
|
||||
for dsize in 1_usize..max_dsize + 1 {
|
||||
let k_ksk: usize = k_out + base2k_key * dsize;
|
||||
|
||||
let n: usize = module.n();
|
||||
let dnum: usize = k_out.div_ceil(base2k * di);
|
||||
let dsize_in: usize = 1;
|
||||
|
||||
let dnum_in: usize = k_out / base2k_out;
|
||||
let dnum_ksk: usize = k_out.div_ceil(base2k_key * dsize);
|
||||
|
||||
let gglwe_s0s1_infos: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_out.into(),
|
||||
k: k_out.into(),
|
||||
dnum: dnum.into(),
|
||||
dnum: dnum_in.into(),
|
||||
dsize: dsize_in.into(),
|
||||
rank_in: rank_in.into(),
|
||||
rank_out: rank_out.into(),
|
||||
@@ -192,10 +202,10 @@ where
|
||||
|
||||
let gglwe_s1s2_infos: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_key.into(),
|
||||
k: k_ksk.into(),
|
||||
dnum: dnum.into(),
|
||||
dsize: di.into(),
|
||||
dnum: dnum_ksk.into(),
|
||||
dsize: dsize.into(),
|
||||
rank_in: rank_out.into(),
|
||||
rank_out: rank_out.into(),
|
||||
};
|
||||
@@ -263,7 +273,7 @@ where
|
||||
|
||||
let max_noise: f64 = log2_std_noise_gglwe_product(
|
||||
n as f64,
|
||||
base2k * di,
|
||||
base2k_key * dsize,
|
||||
var_xs,
|
||||
var_xs,
|
||||
0f64,
|
||||
|
||||
@@ -30,53 +30,57 @@ where
|
||||
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||
Scratch<BE>: ScratchAvailable + ScratchTakeCore<BE>,
|
||||
{
|
||||
let base2k: usize = 12;
|
||||
let k_in: usize = 54;
|
||||
let dsize: usize = k_in.div_ceil(base2k);
|
||||
let base2k_in: usize = 17;
|
||||
let base2k_key: usize = 13;
|
||||
let base2k_out: usize = base2k_in; // MUST BE SAME
|
||||
let k_in: usize = 102;
|
||||
let max_dsize: usize = k_in.div_ceil(base2k_key);
|
||||
|
||||
for rank in 1_usize..3 {
|
||||
for di in 1..dsize + 1 {
|
||||
let k_ksk: usize = k_in + base2k * di;
|
||||
for dsize in 1..max_dsize + 1 {
|
||||
let k_ksk: usize = k_in + base2k_key * dsize;
|
||||
let k_tsk: usize = k_ksk;
|
||||
let k_out: usize = k_ksk; // Better capture noise.
|
||||
|
||||
let n: usize = module.n();
|
||||
let dnum: usize = k_in.div_ceil(di * base2k);
|
||||
let dnum_in: usize = k_in / base2k_in;
|
||||
let dnum_ksk: usize = k_in.div_ceil(base2k_key * dsize);
|
||||
|
||||
let dsize_in: usize = 1;
|
||||
|
||||
let ggsw_in_infos: GGSWLayout = GGSWLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_in.into(),
|
||||
k: k_in.into(),
|
||||
dnum: dnum.into(),
|
||||
dnum: dnum_in.into(),
|
||||
dsize: dsize_in.into(),
|
||||
rank: rank.into(),
|
||||
};
|
||||
|
||||
let ggsw_out_infos: GGSWLayout = GGSWLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_out.into(),
|
||||
k: k_out.into(),
|
||||
dnum: dnum.into(),
|
||||
dnum: dnum_in.into(),
|
||||
dsize: dsize_in.into(),
|
||||
rank: rank.into(),
|
||||
};
|
||||
|
||||
let tsk_infos: GLWETensorKeyLayout = GLWETensorKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_key.into(),
|
||||
k: k_tsk.into(),
|
||||
dnum: dnum.into(),
|
||||
dsize: di.into(),
|
||||
dnum: dnum_ksk.into(),
|
||||
dsize: dsize.into(),
|
||||
rank: rank.into(),
|
||||
};
|
||||
|
||||
let ksk_apply_infos: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_key.into(),
|
||||
k: k_ksk.into(),
|
||||
dnum: dnum.into(),
|
||||
dsize: di.into(),
|
||||
dnum: dnum_ksk.into(),
|
||||
dsize: dsize.into(),
|
||||
rank_in: rank.into(),
|
||||
rank_out: rank.into(),
|
||||
};
|
||||
@@ -163,7 +167,7 @@ where
|
||||
let max_noise = |col_j: usize| -> f64 {
|
||||
noise_ggsw_keyswitch(
|
||||
n as f64,
|
||||
base2k * di,
|
||||
base2k_key * dsize,
|
||||
col_j,
|
||||
var_xs,
|
||||
0f64,
|
||||
@@ -195,43 +199,45 @@ where
|
||||
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||
Scratch<BE>: ScratchAvailable + ScratchTakeCore<BE>,
|
||||
{
|
||||
let base2k: usize = 12;
|
||||
let k_out: usize = 54;
|
||||
let dsize: usize = k_out.div_ceil(base2k);
|
||||
let base2k_out: usize = 17;
|
||||
let base2k_key: usize = 13;
|
||||
let k_out: usize = 102;
|
||||
let max_dsize: usize = k_out.div_ceil(base2k_key);
|
||||
|
||||
for rank in 1_usize..3 {
|
||||
for di in 1..dsize + 1 {
|
||||
let k_ksk: usize = k_out + base2k * di;
|
||||
for dsize in 1..max_dsize + 1 {
|
||||
let k_ksk: usize = k_out + base2k_key * dsize;
|
||||
let k_tsk: usize = k_ksk;
|
||||
|
||||
let n: usize = module.n();
|
||||
let dnum: usize = k_out.div_ceil(di * base2k);
|
||||
|
||||
let dnum_in: usize = k_out / base2k_out;
|
||||
let dnum_ksk: usize = k_out.div_ceil(base2k_key * dsize);
|
||||
let dsize_in: usize = 1;
|
||||
|
||||
let ggsw_out_infos: GGSWLayout = GGSWLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_out.into(),
|
||||
k: k_out.into(),
|
||||
dnum: dnum.into(),
|
||||
dnum: dnum_in.into(),
|
||||
dsize: dsize_in.into(),
|
||||
rank: rank.into(),
|
||||
};
|
||||
|
||||
let tsk_infos: GLWETensorKeyLayout = GLWETensorKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_key.into(),
|
||||
k: k_tsk.into(),
|
||||
dnum: dnum.into(),
|
||||
dsize: di.into(),
|
||||
dnum: dnum_ksk.into(),
|
||||
dsize: dsize.into(),
|
||||
rank: rank.into(),
|
||||
};
|
||||
|
||||
let ksk_apply_infos: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_key.into(),
|
||||
k: k_ksk.into(),
|
||||
dnum: dnum.into(),
|
||||
dsize: di.into(),
|
||||
dnum: dnum_ksk.into(),
|
||||
dsize: dsize.into(),
|
||||
rank_in: rank.into(),
|
||||
rank_out: rank.into(),
|
||||
};
|
||||
@@ -311,7 +317,7 @@ where
|
||||
let max_noise = |col_j: usize| -> f64 {
|
||||
noise_ggsw_keyswitch(
|
||||
n as f64,
|
||||
base2k * di,
|
||||
base2k_key * dsize,
|
||||
col_j,
|
||||
var_xs,
|
||||
0f64,
|
||||
|
||||
@@ -12,7 +12,6 @@ use crate::{
|
||||
GLWESwitchingKeyPreparedFactory, LWEInfos,
|
||||
prepared::{GLWESecretPrepared, GLWESwitchingKeyPrepared},
|
||||
},
|
||||
noise::log2_std_noise_gglwe_product,
|
||||
var_noise_gglwe_product_v2,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use poulpy_hal::{
|
||||
api::{ScratchAvailable, ScratchOwnedAlloc, ScratchOwnedBorrow},
|
||||
api::{ScratchAvailable, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxNormalize},
|
||||
layouts::{Backend, Module, Scratch, ScratchOwned, ZnxView},
|
||||
source::Source,
|
||||
};
|
||||
@@ -14,21 +14,27 @@ use crate::{
|
||||
|
||||
pub fn test_lwe_keyswitch<BE: Backend>(module: &Module<BE>)
|
||||
where
|
||||
Module<BE>:
|
||||
LWEKeySwitch<BE> + LWESwitchingKeyEncrypt<BE> + LWEEncryptSk<BE> + LWESwitchingKeyPreparedFactory<BE> + LWEDecrypt<BE>,
|
||||
Module<BE>: LWEKeySwitch<BE>
|
||||
+ LWESwitchingKeyEncrypt<BE>
|
||||
+ LWEEncryptSk<BE>
|
||||
+ LWESwitchingKeyPreparedFactory<BE>
|
||||
+ LWEDecrypt<BE>
|
||||
+ VecZnxNormalize<BE>,
|
||||
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||
Scratch<BE>: ScratchAvailable + ScratchTakeCore<BE>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let base2k: usize = 17;
|
||||
let base2k_in: usize = 17;
|
||||
let base2k_out: usize = 15;
|
||||
let base2k_key: usize = 13;
|
||||
|
||||
let n_lwe_in: usize = 22;
|
||||
let n_lwe_out: usize = 30;
|
||||
let k_lwe_ct: usize = 2 * base2k;
|
||||
let n_lwe_in: usize = module.n() >> 1;
|
||||
let n_lwe_out: usize = module.n() >> 1;
|
||||
let k_lwe_ct: usize = 102;
|
||||
let k_lwe_pt: usize = 8;
|
||||
|
||||
let k_ksk: usize = k_lwe_ct + base2k;
|
||||
let dnum: usize = k_lwe_ct.div_ceil(base2k);
|
||||
let k_ksk: usize = k_lwe_ct + base2k_key;
|
||||
let dnum: usize = k_lwe_ct.div_ceil(base2k_key);
|
||||
|
||||
let mut source_xs: Source = Source::new([0u8; 32]);
|
||||
let mut source_xa: Source = Source::new([0u8; 32]);
|
||||
@@ -36,21 +42,21 @@ where
|
||||
|
||||
let key_apply_infos: LWESwitchingKeyLayout = LWESwitchingKeyLayout {
|
||||
n: n.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_key.into(),
|
||||
k: k_ksk.into(),
|
||||
dnum: dnum.into(),
|
||||
};
|
||||
|
||||
let lwe_in_infos: LWELayout = LWELayout {
|
||||
n: n_lwe_in.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_in.into(),
|
||||
k: k_lwe_ct.into(),
|
||||
};
|
||||
|
||||
let lwe_out_infos: LWELayout = LWELayout {
|
||||
n: n_lwe_out.into(),
|
||||
k: k_lwe_ct.into(),
|
||||
base2k: base2k.into(),
|
||||
base2k: base2k_out.into(),
|
||||
};
|
||||
|
||||
let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(
|
||||
@@ -66,7 +72,7 @@ where
|
||||
|
||||
let data: i64 = 17;
|
||||
|
||||
let mut lwe_pt_in: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(base2k.into(), k_lwe_pt.into());
|
||||
let mut lwe_pt_in: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(base2k_in.into(), k_lwe_pt.into());
|
||||
lwe_pt_in.encode_i64(data, k_lwe_pt.into());
|
||||
|
||||
let mut lwe_ct_in: LWE<Vec<u8>> = LWE::alloc_from_infos(&lwe_in_infos);
|
||||
@@ -76,6 +82,7 @@ where
|
||||
&sk_lwe_in,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut ksk: LWESwitchingKey<Vec<u8>> = LWESwitchingKey::alloc_from_infos(&key_apply_infos);
|
||||
@@ -97,7 +104,18 @@ where
|
||||
lwe_ct_out.keyswitch(module, &lwe_ct_in, &ksk_prepared, scratch.borrow());
|
||||
|
||||
let mut lwe_pt_out: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc_from_infos(&lwe_out_infos);
|
||||
lwe_ct_out.decrypt(module, &mut lwe_pt_out, &sk_lwe_out);
|
||||
lwe_ct_out.decrypt(module, &mut lwe_pt_out, &sk_lwe_out, scratch.borrow());
|
||||
|
||||
assert_eq!(lwe_pt_in.data.at(0, 0)[0], lwe_pt_out.data.at(0, 0)[0]);
|
||||
let mut lwe_pt_want: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc_from_infos(&lwe_out_infos);
|
||||
module.vec_znx_normalize(
|
||||
base2k_out,
|
||||
lwe_pt_want.data_mut(),
|
||||
0,
|
||||
base2k_in,
|
||||
lwe_pt_in.data(),
|
||||
0,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
assert_eq!(lwe_pt_want.data.at(0, 0)[0], lwe_pt_out.data.at(0, 0)[0]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user