mirror of
https://github.com/arnaucube/poulpy.git
synced 2026-02-10 13:16:44 +01:00
updated repo for publishing (#74)
This commit is contained in:
committed by
GitHub
parent
0be569eca0
commit
62eb87cc07
361
poulpy-core/src/tests/generics/automorphism/gglwe_atk.rs
Normal file
361
poulpy-core/src/tests/generics/automorphism/gglwe_atk.rs
Normal file
@@ -0,0 +1,361 @@
|
||||
use poulpy_backend::hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, VecZnxAddInplace,
|
||||
VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxBigAddInplace,
|
||||
VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxCopy,
|
||||
VecZnxDftAllocBytes, VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigConsume, VecZnxFillUniform, VecZnxNormalize,
|
||||
VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubABInplace, VecZnxSubScalarInplace,
|
||||
VecZnxSwithcDegree, VmpApply, VmpApplyAdd, VmpApplyTmpBytes, VmpPMatAlloc, VmpPrepare,
|
||||
},
|
||||
layouts::{Backend, Module, ScratchOwned},
|
||||
oep::{
|
||||
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
|
||||
TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
layouts::{
|
||||
GGLWEAutomorphismKey, GLWEPlaintext, GLWESecret, Infos,
|
||||
prepared::{GGLWEAutomorphismKeyPrepared, GLWESecretPrepared, Prepare, PrepareAlloc},
|
||||
},
|
||||
noise::log2_std_noise_gglwe_product,
|
||||
};
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn test_gglwe_automorphism_key_automorphism<B>(
|
||||
module: &Module<B>,
|
||||
p0: i64,
|
||||
p1: i64,
|
||||
basek: usize,
|
||||
digits: usize,
|
||||
k_in: usize,
|
||||
k_out: usize,
|
||||
k_apply: usize,
|
||||
sigma: f64,
|
||||
rank: usize,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VmpApplyTmpBytes
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxAutomorphism
|
||||
+ VecZnxAutomorphismInplace
|
||||
+ SvpPPolAllocBytes
|
||||
+ VecZnxDftAllocBytes
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>
|
||||
+ SvpPrepare<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ VecZnxSwithcDegree
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxSubScalarInplace,
|
||||
B: Backend
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let digits_in: usize = 1;
|
||||
|
||||
let rows_in: usize = k_in / (basek * digits);
|
||||
let rows_apply: usize = k_in.div_ceil(basek * digits);
|
||||
|
||||
let mut auto_key_in: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_in, rows_in, digits_in, rank);
|
||||
let mut auto_key_out: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_out, rows_in, digits_in, rank);
|
||||
let mut auto_key_apply: GGLWEAutomorphismKey<Vec<u8>> =
|
||||
GGLWEAutomorphismKey::alloc(n, basek, k_apply, rows_apply, digits, rank);
|
||||
|
||||
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]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_apply, rank)
|
||||
| GGLWEAutomorphismKey::automorphism_scratch_space(module, n, basek, k_out, k_in, k_apply, digits, rank),
|
||||
);
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
|
||||
// gglwe_{s1}(s0) = s0 -> s1
|
||||
auto_key_in.encrypt_sk(
|
||||
module,
|
||||
p0,
|
||||
&sk,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
// gglwe_{s2}(s1) -> s1 -> s2
|
||||
auto_key_apply.encrypt_sk(
|
||||
module,
|
||||
p1,
|
||||
&sk,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut auto_key_apply_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> =
|
||||
GGLWEAutomorphismKeyPrepared::alloc(module, n, basek, k_apply, rows_apply, digits, rank);
|
||||
|
||||
auto_key_apply_prepared.prepare(module, &auto_key_apply, scratch.borrow());
|
||||
|
||||
// gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0)
|
||||
auto_key_out.automorphism(
|
||||
module,
|
||||
&auto_key_in,
|
||||
&auto_key_apply_prepared,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_out);
|
||||
|
||||
let mut sk_auto: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk_auto.fill_zero(); // Necessary to avoid panic of unfilled sk
|
||||
(0..rank).for_each(|i| {
|
||||
module.vec_znx_automorphism(
|
||||
module.galois_element_inv(p0 * p1),
|
||||
&mut sk_auto.data.as_vec_znx_mut(),
|
||||
i,
|
||||
&sk.data.as_vec_znx(),
|
||||
i,
|
||||
);
|
||||
});
|
||||
|
||||
let sk_auto_dft: GLWESecretPrepared<Vec<u8>, B> = sk_auto.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
(0..auto_key_out.rank_in()).for_each(|col_i| {
|
||||
(0..auto_key_out.rows()).for_each(|row_i| {
|
||||
auto_key_out
|
||||
.at(row_i, col_i)
|
||||
.decrypt(module, &mut pt, &sk_auto_dft, scratch.borrow());
|
||||
|
||||
module.vec_znx_sub_scalar_inplace(
|
||||
&mut pt.data,
|
||||
0,
|
||||
(digits_in - 1) + row_i * digits_in,
|
||||
&sk.data,
|
||||
col_i,
|
||||
);
|
||||
|
||||
let noise_have: f64 = pt.data.std(basek, 0).log2();
|
||||
let noise_want: f64 = log2_std_noise_gglwe_product(
|
||||
n as f64,
|
||||
basek * digits,
|
||||
0.5,
|
||||
0.5,
|
||||
0f64,
|
||||
sigma * sigma,
|
||||
0f64,
|
||||
rank as f64,
|
||||
k_out,
|
||||
k_apply,
|
||||
);
|
||||
|
||||
assert!(
|
||||
noise_have < noise_want + 0.5,
|
||||
"{} {}",
|
||||
noise_have,
|
||||
noise_want
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn test_gglwe_automorphism_key_automorphism_inplace<B>(
|
||||
module: &Module<B>,
|
||||
p0: i64,
|
||||
p1: i64,
|
||||
basek: usize,
|
||||
digits: usize,
|
||||
k_in: usize,
|
||||
k_apply: usize,
|
||||
sigma: f64,
|
||||
rank: usize,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxDftAllocBytes
|
||||
+ VmpApplyTmpBytes
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxAutomorphism
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxAutomorphism
|
||||
+ VecZnxAutomorphismInplace
|
||||
+ VecZnxDftAllocBytes
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxSubScalarInplace
|
||||
+ VecZnxCopy
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>,
|
||||
B: Backend
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let digits_in: usize = 1;
|
||||
|
||||
let rows_in: usize = k_in / (basek * digits);
|
||||
let rows_apply: usize = k_in.div_ceil(basek * digits);
|
||||
|
||||
let mut auto_key: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_in, rows_in, digits_in, rank);
|
||||
let mut auto_key_apply: GGLWEAutomorphismKey<Vec<u8>> =
|
||||
GGLWEAutomorphismKey::alloc(n, basek, k_apply, rows_apply, digits, rank);
|
||||
|
||||
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]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_apply, rank)
|
||||
| GGLWEAutomorphismKey::automorphism_inplace_scratch_space(module, n, basek, k_in, k_apply, digits, rank),
|
||||
);
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
|
||||
// gglwe_{s1}(s0) = s0 -> s1
|
||||
auto_key.encrypt_sk(
|
||||
module,
|
||||
p0,
|
||||
&sk,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
// gglwe_{s2}(s1) -> s1 -> s2
|
||||
auto_key_apply.encrypt_sk(
|
||||
module,
|
||||
p1,
|
||||
&sk,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut auto_key_apply_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> =
|
||||
GGLWEAutomorphismKeyPrepared::alloc(module, n, basek, k_apply, rows_apply, digits, rank);
|
||||
|
||||
auto_key_apply_prepared.prepare(module, &auto_key_apply, scratch.borrow());
|
||||
|
||||
// gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0)
|
||||
auto_key.automorphism_inplace(module, &auto_key_apply_prepared, scratch.borrow());
|
||||
|
||||
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_in);
|
||||
|
||||
let mut sk_auto: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk_auto.fill_zero(); // Necessary to avoid panic of unfilled sk
|
||||
|
||||
(0..rank).for_each(|i| {
|
||||
module.vec_znx_automorphism(
|
||||
module.galois_element_inv(p0 * p1),
|
||||
&mut sk_auto.data.as_vec_znx_mut(),
|
||||
i,
|
||||
&sk.data.as_vec_znx(),
|
||||
i,
|
||||
);
|
||||
});
|
||||
|
||||
let sk_auto_dft: GLWESecretPrepared<Vec<u8>, B> = sk_auto.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
(0..auto_key.rank_in()).for_each(|col_i| {
|
||||
(0..auto_key.rows()).for_each(|row_i| {
|
||||
auto_key
|
||||
.at(row_i, col_i)
|
||||
.decrypt(module, &mut pt, &sk_auto_dft, scratch.borrow());
|
||||
module.vec_znx_sub_scalar_inplace(
|
||||
&mut pt.data,
|
||||
0,
|
||||
(digits_in - 1) + row_i * digits_in,
|
||||
&sk.data,
|
||||
col_i,
|
||||
);
|
||||
|
||||
let noise_have: f64 = pt.data.std(basek, 0).log2();
|
||||
let noise_want: f64 = log2_std_noise_gglwe_product(
|
||||
n as f64,
|
||||
basek * digits,
|
||||
0.5,
|
||||
0.5,
|
||||
0f64,
|
||||
sigma * sigma,
|
||||
0f64,
|
||||
rank as f64,
|
||||
k_in,
|
||||
k_apply,
|
||||
);
|
||||
|
||||
assert!(
|
||||
noise_have < noise_want + 0.5,
|
||||
"{} {}",
|
||||
noise_have,
|
||||
noise_want
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
333
poulpy-core/src/tests/generics/automorphism/ggsw_ct.rs
Normal file
333
poulpy-core/src/tests/generics/automorphism/ggsw_ct.rs
Normal file
@@ -0,0 +1,333 @@
|
||||
use poulpy_backend::hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApply, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare,
|
||||
VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace,
|
||||
VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigAllocBytes, VecZnxBigNormalize,
|
||||
VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAddInplace, VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftCopy,
|
||||
VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigConsume, VecZnxDftToVecZnxBigTmpA, VecZnxFillUniform, VecZnxNormalize,
|
||||
VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubABInplace, VecZnxSwithcDegree, VmpApply,
|
||||
VmpApplyAdd, VmpApplyTmpBytes, VmpPMatAlloc, VmpPrepare,
|
||||
},
|
||||
layouts::{Backend, Module, ScalarZnx, ScratchOwned},
|
||||
oep::{
|
||||
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
|
||||
TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
layouts::{
|
||||
GGLWEAutomorphismKey, GGLWETensorKey, GGSWCiphertext, GLWESecret,
|
||||
prepared::{GGLWEAutomorphismKeyPrepared, GGLWETensorKeyPrepared, GLWESecretPrepared, Prepare, PrepareAlloc},
|
||||
},
|
||||
noise::noise_ggsw_keyswitch,
|
||||
};
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn test_ggsw_automorphism<B>(
|
||||
p: i64,
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
k_out: usize,
|
||||
k_in: usize,
|
||||
k_ksk: usize,
|
||||
k_tsk: usize,
|
||||
digits: usize,
|
||||
rank: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxBigAlloc<B>
|
||||
+ VecZnxDftAlloc<B>
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxDftToVecZnxBigTmpA<B>
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxCopy
|
||||
+ VecZnxSubABInplace
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VecZnxDftCopy<B>
|
||||
+ VecZnxDftAddInplace<B>
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpApply<B>
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxAutomorphismInplace
|
||||
+ VecZnxAutomorphism,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>
|
||||
+ VecZnxDftAllocBytesImpl<B>
|
||||
+ VecZnxBigAllocBytesImpl<B>
|
||||
+ TakeSvpPPolImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = k_in.div_ceil(basek * digits);
|
||||
let rows_in: usize = k_in.div_euclid(basek * digits);
|
||||
|
||||
let digits_in: usize = 1;
|
||||
|
||||
let mut ct_in: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_in, rows_in, digits_in, rank);
|
||||
let mut ct_out: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_out, rows_in, digits_in, rank);
|
||||
let mut tensor_key: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(n, basek, k_tsk, rows, digits, rank);
|
||||
let mut auto_key: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank);
|
||||
let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
|
||||
|
||||
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]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_in, rank)
|
||||
| GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank)
|
||||
| GGLWETensorKey::encrypt_sk_scratch_space(module, n, basek, k_tsk, rank)
|
||||
| GGSWCiphertext::automorphism_scratch_space(
|
||||
module, n, basek, k_out, k_in, k_ksk, digits, k_tsk, digits, rank,
|
||||
),
|
||||
);
|
||||
|
||||
let var_xs: f64 = 0.5;
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(var_xs, &mut source_xs);
|
||||
let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
auto_key.encrypt_sk(
|
||||
module,
|
||||
p,
|
||||
&sk,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
tensor_key.encrypt_sk(
|
||||
module,
|
||||
&sk,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
pt_scalar.fill_ternary_hw(0, n, &mut source_xs);
|
||||
|
||||
ct_in.encrypt_sk(
|
||||
module,
|
||||
&pt_scalar,
|
||||
&sk_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut auto_key_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> =
|
||||
GGLWEAutomorphismKeyPrepared::alloc(module, n, basek, k_ksk, rows, digits, rank);
|
||||
auto_key_prepared.prepare(module, &auto_key, scratch.borrow());
|
||||
|
||||
let mut tsk_prepared: GGLWETensorKeyPrepared<Vec<u8>, B> =
|
||||
GGLWETensorKeyPrepared::alloc(module, n, basek, k_tsk, rows, digits, rank);
|
||||
tsk_prepared.prepare(module, &tensor_key, scratch.borrow());
|
||||
|
||||
ct_out.automorphism(
|
||||
module,
|
||||
&ct_in,
|
||||
&auto_key_prepared,
|
||||
&tsk_prepared,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
module.vec_znx_automorphism_inplace(p, &mut pt_scalar.as_vec_znx_mut(), 0);
|
||||
|
||||
let max_noise = |col_j: usize| -> f64 {
|
||||
noise_ggsw_keyswitch(
|
||||
n as f64,
|
||||
basek * digits,
|
||||
col_j,
|
||||
var_xs,
|
||||
0f64,
|
||||
sigma * sigma,
|
||||
0f64,
|
||||
rank as f64,
|
||||
k_in,
|
||||
k_ksk,
|
||||
k_tsk,
|
||||
) + 0.5
|
||||
};
|
||||
|
||||
ct_out.assert_noise(module, &sk_prepared, &pt_scalar, max_noise);
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn test_ggsw_automorphism_inplace<B>(
|
||||
p: i64,
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
k_ct: usize,
|
||||
k_ksk: usize,
|
||||
k_tsk: usize,
|
||||
digits: usize,
|
||||
rank: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxBigAlloc<B>
|
||||
+ VecZnxDftAlloc<B>
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxDftToVecZnxBigTmpA<B>
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxCopy
|
||||
+ VecZnxSubABInplace
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxDftCopy<B>
|
||||
+ VecZnxDftAddInplace<B>
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ VecZnxFillUniform
|
||||
+ SvpApply<B>
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxAutomorphismInplace
|
||||
+ VecZnxAutomorphism,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>
|
||||
+ VecZnxDftAllocBytesImpl<B>
|
||||
+ VecZnxBigAllocBytesImpl<B>
|
||||
+ TakeSvpPPolImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = k_ct.div_ceil(digits * basek);
|
||||
let rows_in: usize = k_ct.div_euclid(basek * digits);
|
||||
let digits_in: usize = 1;
|
||||
|
||||
let mut ct: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ct, rows_in, digits_in, rank);
|
||||
let mut tensor_key: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(n, basek, k_tsk, rows, digits, rank);
|
||||
let mut auto_key: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank);
|
||||
let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
|
||||
|
||||
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]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ct, rank)
|
||||
| GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank)
|
||||
| GGLWETensorKey::encrypt_sk_scratch_space(module, n, basek, k_tsk, rank)
|
||||
| GGSWCiphertext::automorphism_inplace_scratch_space(module, n, basek, k_ct, k_ksk, digits, k_tsk, digits, rank),
|
||||
);
|
||||
|
||||
let var_xs: f64 = 0.5;
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(var_xs, &mut source_xs);
|
||||
let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
auto_key.encrypt_sk(
|
||||
module,
|
||||
p,
|
||||
&sk,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
tensor_key.encrypt_sk(
|
||||
module,
|
||||
&sk,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
pt_scalar.fill_ternary_hw(0, n, &mut source_xs);
|
||||
|
||||
ct.encrypt_sk(
|
||||
module,
|
||||
&pt_scalar,
|
||||
&sk_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut auto_key_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> =
|
||||
GGLWEAutomorphismKeyPrepared::alloc(module, n, basek, k_ksk, rows, digits, rank);
|
||||
auto_key_prepared.prepare(module, &auto_key, scratch.borrow());
|
||||
|
||||
let mut tsk_prepared: GGLWETensorKeyPrepared<Vec<u8>, B> =
|
||||
GGLWETensorKeyPrepared::alloc(module, n, basek, k_tsk, rows, digits, rank);
|
||||
tsk_prepared.prepare(module, &tensor_key, scratch.borrow());
|
||||
|
||||
ct.automorphism_inplace(module, &auto_key_prepared, &tsk_prepared, scratch.borrow());
|
||||
|
||||
module.vec_znx_automorphism_inplace(p, &mut pt_scalar.as_vec_znx_mut(), 0);
|
||||
|
||||
let max_noise = |col_j: usize| -> f64 {
|
||||
noise_ggsw_keyswitch(
|
||||
n as f64,
|
||||
basek * digits,
|
||||
col_j,
|
||||
var_xs,
|
||||
0f64,
|
||||
sigma * sigma,
|
||||
0f64,
|
||||
rank as f64,
|
||||
k_ct,
|
||||
k_ksk,
|
||||
k_tsk,
|
||||
) + 0.5
|
||||
};
|
||||
|
||||
ct.assert_noise(module, &sk_prepared, &pt_scalar, max_noise);
|
||||
}
|
||||
271
poulpy-core/src/tests/generics/automorphism/glwe_ct.rs
Normal file
271
poulpy-core/src/tests/generics/automorphism/glwe_ct.rs
Normal file
@@ -0,0 +1,271 @@
|
||||
use poulpy_backend::hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, VecZnxAddInplace,
|
||||
VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxBigAddInplace,
|
||||
VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAllocBytes,
|
||||
VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigConsume, VecZnxFillUniform, VecZnxNormalize, VecZnxNormalizeInplace,
|
||||
VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubABInplace, VecZnxSwithcDegree, VmpApply, VmpApplyAdd, VmpApplyTmpBytes,
|
||||
VmpPMatAlloc, VmpPrepare,
|
||||
},
|
||||
layouts::{Backend, Module, ScratchOwned},
|
||||
oep::{
|
||||
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
|
||||
TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
layouts::{
|
||||
GGLWEAutomorphismKey, GLWECiphertext, GLWEPlaintext, GLWESecret, Infos,
|
||||
prepared::{GGLWEAutomorphismKeyPrepared, GLWESecretPrepared, Prepare, PrepareAlloc},
|
||||
},
|
||||
noise::log2_std_noise_gglwe_product,
|
||||
};
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn test_glwe_automorphism<B>(
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
p: i64,
|
||||
k_out: usize,
|
||||
k_in: usize,
|
||||
k_ksk: usize,
|
||||
digits: usize,
|
||||
rank: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VmpApplyTmpBytes
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VecZnxAutomorphism
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxAutomorphismInplace
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = k_in.div_ceil(basek * digits);
|
||||
|
||||
let mut autokey: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank);
|
||||
let mut ct_in: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_in, rank);
|
||||
let mut ct_out: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_out, rank);
|
||||
let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_in);
|
||||
|
||||
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(basek, &mut pt_want.data, 0, k_in, &mut source_xa);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, n, basek, autokey.k(), rank)
|
||||
| GLWECiphertext::decrypt_scratch_space(module, n, basek, ct_out.k())
|
||||
| GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, ct_in.k())
|
||||
| GLWECiphertext::automorphism_scratch_space(
|
||||
module,
|
||||
n,
|
||||
basek,
|
||||
ct_out.k(),
|
||||
ct_in.k(),
|
||||
autokey.k(),
|
||||
digits,
|
||||
rank,
|
||||
),
|
||||
);
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
autokey.encrypt_sk(
|
||||
module,
|
||||
p,
|
||||
&sk,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
ct_in.encrypt_sk(
|
||||
module,
|
||||
&pt_want,
|
||||
&sk_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut autokey_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> =
|
||||
GGLWEAutomorphismKeyPrepared::alloc(module, n, basek, k_ksk, rows, digits, rank);
|
||||
autokey_prepared.prepare(module, &autokey, scratch.borrow());
|
||||
|
||||
ct_out.automorphism(module, &ct_in, &autokey_prepared, scratch.borrow());
|
||||
|
||||
let max_noise: f64 = log2_std_noise_gglwe_product(
|
||||
module.n() as f64,
|
||||
basek * digits,
|
||||
0.5,
|
||||
0.5,
|
||||
0f64,
|
||||
sigma * sigma,
|
||||
0f64,
|
||||
rank as f64,
|
||||
k_in,
|
||||
k_ksk,
|
||||
);
|
||||
|
||||
module.vec_znx_automorphism_inplace(p, &mut pt_want.data, 0);
|
||||
|
||||
ct_out.assert_noise(module, &sk_prepared, &pt_want, max_noise + 1.0);
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn test_glwe_automorphism_inplace<B>(
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
p: i64,
|
||||
k_ct: usize,
|
||||
k_ksk: usize,
|
||||
digits: usize,
|
||||
rank: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VmpApplyTmpBytes
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VecZnxAutomorphism
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxAutomorphismInplace
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = k_ct.div_ceil(basek * digits);
|
||||
|
||||
let mut autokey: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank);
|
||||
let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank);
|
||||
let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_ct);
|
||||
|
||||
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(basek, &mut pt_want.data, 0, k_ct, &mut source_xa);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, n, basek, autokey.k(), rank)
|
||||
| GLWECiphertext::decrypt_scratch_space(module, n, basek, ct.k())
|
||||
| GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, ct.k())
|
||||
| GLWECiphertext::automorphism_inplace_scratch_space(module, n, basek, ct.k(), autokey.k(), digits, rank),
|
||||
);
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
autokey.encrypt_sk(
|
||||
module,
|
||||
p,
|
||||
&sk,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
ct.encrypt_sk(
|
||||
module,
|
||||
&pt_want,
|
||||
&sk_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut autokey_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> =
|
||||
GGLWEAutomorphismKeyPrepared::alloc(module, n, basek, k_ksk, rows, digits, rank);
|
||||
autokey_prepared.prepare(module, &autokey, scratch.borrow());
|
||||
|
||||
ct.automorphism_inplace(module, &autokey_prepared, scratch.borrow());
|
||||
|
||||
let max_noise: f64 = log2_std_noise_gglwe_product(
|
||||
module.n() as f64,
|
||||
basek * digits,
|
||||
0.5,
|
||||
0.5,
|
||||
0f64,
|
||||
sigma * sigma,
|
||||
0f64,
|
||||
rank as f64,
|
||||
k_ct,
|
||||
k_ksk,
|
||||
);
|
||||
|
||||
module.vec_znx_automorphism_inplace(p, &mut pt_want.data, 0);
|
||||
|
||||
ct.assert_noise(module, &sk_prepared, &pt_want, max_noise + 1.0);
|
||||
}
|
||||
7
poulpy-core/src/tests/generics/automorphism/mod.rs
Normal file
7
poulpy-core/src/tests/generics/automorphism/mod.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
mod gglwe_atk;
|
||||
mod ggsw_ct;
|
||||
mod glwe_ct;
|
||||
|
||||
pub use gglwe_atk::*;
|
||||
pub use ggsw_ct::*;
|
||||
pub use glwe_ct::*;
|
||||
244
poulpy-core/src/tests/generics/conversion.rs
Normal file
244
poulpy-core/src/tests/generics/conversion.rs
Normal file
@@ -0,0 +1,244 @@
|
||||
use poulpy_backend::hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, VecZnxAddInplace,
|
||||
VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace,
|
||||
VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAllocBytes, VecZnxDftFromVecZnx,
|
||||
VecZnxDftToVecZnxBigConsume, VecZnxFillUniform, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes,
|
||||
VecZnxSub, VecZnxSubABInplace, VecZnxSwithcDegree, VmpApply, VmpApplyAdd, VmpApplyTmpBytes, VmpPMatAlloc, VmpPrepare,
|
||||
ZnxView,
|
||||
},
|
||||
layouts::{Backend, Module, ScratchOwned},
|
||||
oep::{
|
||||
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
|
||||
TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
GLWECiphertext, GLWEPlaintext, GLWESecret, GLWEToLWESwitchingKey, Infos, LWECiphertext, LWEPlaintext, LWESecret,
|
||||
LWEToGLWESwitchingKey,
|
||||
prepared::{GLWESecretPrepared, GLWEToLWESwitchingKeyPrepared, LWEToGLWESwitchingKeyPrepared, PrepareAlloc},
|
||||
};
|
||||
|
||||
pub fn test_lwe_to_glwe<B>(module: &Module<B>)
|
||||
where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxAutomorphismInplace,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let basek: usize = 17;
|
||||
let sigma: f64 = 3.2;
|
||||
|
||||
let rank: usize = 2;
|
||||
|
||||
let n_lwe: usize = 22;
|
||||
let k_lwe_ct: usize = 2 * basek;
|
||||
let k_lwe_pt: usize = 8;
|
||||
|
||||
let k_glwe_ct: usize = 3 * basek;
|
||||
|
||||
let k_ksk: usize = k_lwe_ct + basek;
|
||||
|
||||
let mut source_xs: Source = Source::new([0u8; 32]);
|
||||
let mut source_xa: Source = Source::new([0u8; 32]);
|
||||
let mut source_xe: Source = Source::new([0u8; 32]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
LWEToGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank)
|
||||
| GLWECiphertext::from_lwe_scratch_space(module, n, basek, k_lwe_ct, k_glwe_ct, k_ksk, rank)
|
||||
| GLWECiphertext::decrypt_scratch_space(module, n, basek, k_glwe_ct),
|
||||
);
|
||||
|
||||
let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk_glwe.fill_ternary_prob(0.5, &mut source_xs);
|
||||
|
||||
let sk_glwe_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_glwe.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe);
|
||||
sk_lwe.fill_ternary_prob(0.5, &mut source_xs);
|
||||
|
||||
let data: i64 = 17;
|
||||
|
||||
let mut lwe_pt: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_pt);
|
||||
lwe_pt.encode_i64(data, k_lwe_pt);
|
||||
|
||||
let mut lwe_ct: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe, basek, k_lwe_ct);
|
||||
lwe_ct.encrypt_sk(
|
||||
module,
|
||||
&lwe_pt,
|
||||
&sk_lwe,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
);
|
||||
|
||||
let mut ksk: LWEToGLWESwitchingKey<Vec<u8>> = LWEToGLWESwitchingKey::alloc(n, basek, k_ksk, lwe_ct.size(), rank);
|
||||
|
||||
ksk.encrypt_sk(
|
||||
module,
|
||||
&sk_lwe,
|
||||
&sk_glwe,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut glwe_ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_glwe_ct, rank);
|
||||
|
||||
let ksk_prepared: LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
glwe_ct.from_lwe(module, &lwe_ct, &ksk_prepared, scratch.borrow());
|
||||
|
||||
let mut glwe_pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_glwe_ct);
|
||||
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]);
|
||||
}
|
||||
|
||||
pub fn test_glwe_to_lwe<B>(module: &Module<B>)
|
||||
where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxAutomorphismInplace,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let basek: usize = 17;
|
||||
let sigma: f64 = 3.2;
|
||||
|
||||
let rank: usize = 2;
|
||||
|
||||
let n_lwe: usize = 22;
|
||||
let k_lwe_ct: usize = 2 * basek;
|
||||
let k_lwe_pt: usize = 8;
|
||||
|
||||
let k_glwe_ct: usize = 3 * basek;
|
||||
|
||||
let k_ksk: usize = k_lwe_ct + basek;
|
||||
|
||||
let mut source_xs: Source = Source::new([0u8; 32]);
|
||||
let mut source_xa: Source = Source::new([0u8; 32]);
|
||||
let mut source_xe: Source = Source::new([0u8; 32]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
LWEToGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank)
|
||||
| LWECiphertext::from_glwe_scratch_space(module, n, basek, k_lwe_ct, k_glwe_ct, k_ksk, rank)
|
||||
| GLWECiphertext::decrypt_scratch_space(module, n, basek, k_glwe_ct),
|
||||
);
|
||||
|
||||
let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk_glwe.fill_ternary_prob(0.5, &mut source_xs);
|
||||
|
||||
let sk_glwe_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_glwe.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
let mut sk_lwe = LWESecret::alloc(n_lwe);
|
||||
sk_lwe.fill_ternary_prob(0.5, &mut source_xs);
|
||||
|
||||
let data: i64 = 17;
|
||||
let mut glwe_pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_glwe_ct);
|
||||
glwe_pt.encode_coeff_i64(data, k_lwe_pt, 0);
|
||||
|
||||
let mut glwe_ct = GLWECiphertext::alloc(n, basek, k_glwe_ct, rank);
|
||||
glwe_ct.encrypt_sk(
|
||||
module,
|
||||
&glwe_pt,
|
||||
&sk_glwe_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut ksk: GLWEToLWESwitchingKey<Vec<u8>> = GLWEToLWESwitchingKey::alloc(n, basek, k_ksk, glwe_ct.size(), rank);
|
||||
|
||||
ksk.encrypt_sk(
|
||||
module,
|
||||
&sk_lwe,
|
||||
&sk_glwe,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut lwe_ct: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe, basek, k_lwe_ct);
|
||||
|
||||
let ksk_prepared: GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
lwe_ct.from_glwe(module, &glwe_ct, &ksk_prepared, scratch.borrow());
|
||||
|
||||
let mut lwe_pt: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_ct);
|
||||
lwe_ct.decrypt(module, &mut lwe_pt, &sk_lwe);
|
||||
|
||||
assert_eq!(glwe_pt.data.at(0, 0)[0], lwe_pt.data.at(0, 0)[0]);
|
||||
}
|
||||
215
poulpy-core/src/tests/generics/encryption/gglwe_atk.rs
Normal file
215
poulpy-core/src/tests/generics/encryption/gglwe_atk.rs
Normal file
@@ -0,0 +1,215 @@
|
||||
use poulpy_backend::hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, VecZnxAddInplace,
|
||||
VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxBigAddInplace,
|
||||
VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxCopy,
|
||||
VecZnxDftAllocBytes, VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigConsume, VecZnxFillUniform, VecZnxNormalize,
|
||||
VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubABInplace, VecZnxSubScalarInplace,
|
||||
VecZnxSwithcDegree, VmpApply, VmpApplyAdd, VmpApplyTmpBytes, VmpPMatAlloc, VmpPrepare,
|
||||
},
|
||||
layouts::{Backend, Module, ScratchOwned},
|
||||
oep::{
|
||||
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
|
||||
TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
GGLWEAutomorphismKey, GLWESecret,
|
||||
compressed::{Decompress, GGLWEAutomorphismKeyCompressed},
|
||||
prepared::{GLWESecretPrepared, PrepareAlloc},
|
||||
};
|
||||
|
||||
pub fn test_gglwe_automorphisk_key_encrypt_sk<B>(
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
k_ksk: usize,
|
||||
digits: usize,
|
||||
rank: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VmpApplyTmpBytes
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxAutomorphism
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxAutomorphismInplace
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxSubScalarInplace
|
||||
+ VecZnxCopy
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>,
|
||||
B: Backend
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = (k_ksk - digits * basek) / (digits * basek);
|
||||
|
||||
let mut atk: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank);
|
||||
|
||||
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]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWEAutomorphismKey::encrypt_sk_scratch_space(
|
||||
module, n, basek, k_ksk, rank,
|
||||
));
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
|
||||
let p = -5;
|
||||
|
||||
atk.encrypt_sk(
|
||||
module,
|
||||
p,
|
||||
&sk,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut sk_out: GLWESecret<Vec<u8>> = sk.clone();
|
||||
(0..atk.rank()).for_each(|i| {
|
||||
module.vec_znx_automorphism(
|
||||
module.galois_element_inv(p),
|
||||
&mut sk_out.data.as_vec_znx_mut(),
|
||||
i,
|
||||
&sk.data.as_vec_znx(),
|
||||
i,
|
||||
);
|
||||
});
|
||||
let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
atk.key
|
||||
.key
|
||||
.assert_noise(module, &sk_out_prepared, &sk.data, sigma);
|
||||
}
|
||||
|
||||
pub fn test_gglwe_automorphisk_key_compressed_encrypt_sk<B>(
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
k_ksk: usize,
|
||||
digits: usize,
|
||||
rank: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VmpApplyTmpBytes
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxAutomorphism
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxAutomorphismInplace
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxSubScalarInplace
|
||||
+ VecZnxCopy
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>,
|
||||
B: Backend
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = (k_ksk - digits * basek) / (digits * basek);
|
||||
|
||||
let mut atk_compressed: GGLWEAutomorphismKeyCompressed<Vec<u8>> =
|
||||
GGLWEAutomorphismKeyCompressed::alloc(n, basek, k_ksk, rows, digits, rank);
|
||||
|
||||
let mut source_xs: Source = Source::new([0u8; 32]);
|
||||
let mut source_xe: Source = Source::new([0u8; 32]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWEAutomorphismKey::encrypt_sk_scratch_space(
|
||||
module, n, basek, k_ksk, rank,
|
||||
));
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
|
||||
let p = -5;
|
||||
|
||||
let seed_xa: [u8; 32] = [1u8; 32];
|
||||
|
||||
atk_compressed.encrypt_sk(
|
||||
module,
|
||||
p,
|
||||
&sk,
|
||||
seed_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut sk_out: GLWESecret<Vec<u8>> = sk.clone();
|
||||
(0..atk_compressed.rank()).for_each(|i| {
|
||||
module.vec_znx_automorphism(
|
||||
module.galois_element_inv(p),
|
||||
&mut sk_out.data.as_vec_znx_mut(),
|
||||
i,
|
||||
&sk.data.as_vec_znx(),
|
||||
i,
|
||||
);
|
||||
});
|
||||
let sk_out_prepared = sk_out.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
let mut atk: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank);
|
||||
atk.decompress(module, &atk_compressed);
|
||||
|
||||
atk.key
|
||||
.key
|
||||
.assert_noise(module, &sk_out_prepared, &sk.data, sigma);
|
||||
}
|
||||
186
poulpy-core/src/tests/generics/encryption/gglwe_ct.rs
Normal file
186
poulpy-core/src/tests/generics/encryption/gglwe_ct.rs
Normal file
@@ -0,0 +1,186 @@
|
||||
use poulpy_backend::hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, VecZnxAddInplace,
|
||||
VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAllocBytes,
|
||||
VecZnxBigNormalize, VecZnxCopy, VecZnxDftAllocBytes, VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigConsume, VecZnxFillUniform,
|
||||
VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubABInplace, VecZnxSubScalarInplace,
|
||||
VecZnxSwithcDegree, VmpPMatAlloc, VmpPrepare,
|
||||
},
|
||||
layouts::{Backend, Module, ScratchOwned},
|
||||
oep::{
|
||||
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
|
||||
TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
GGLWESwitchingKey, GLWESecret,
|
||||
compressed::{Decompress, GGLWESwitchingKeyCompressed},
|
||||
prepared::{GLWESecretPrepared, PrepareAlloc},
|
||||
};
|
||||
|
||||
pub fn test_gglwe_switching_key_encrypt_sk<B>(
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
k_ksk: usize,
|
||||
digits: usize,
|
||||
rank_in: usize,
|
||||
rank_out: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxSubScalarInplace
|
||||
+ VecZnxCopy
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>
|
||||
+ VecZnxDftAllocBytesImpl<B>
|
||||
+ VecZnxBigAllocBytesImpl<B>
|
||||
+ TakeSvpPPolImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = (k_ksk - digits * basek) / (digits * basek);
|
||||
|
||||
let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_in, rank_out);
|
||||
|
||||
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]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWESwitchingKey::encrypt_sk_scratch_space(
|
||||
module, n, basek, k_ksk, rank_in, rank_out,
|
||||
));
|
||||
|
||||
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in);
|
||||
sk_in.fill_ternary_prob(0.5, &mut source_xs);
|
||||
|
||||
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out);
|
||||
sk_out.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
ksk.encrypt_sk(
|
||||
module,
|
||||
&sk_in,
|
||||
&sk_out,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
ksk.key
|
||||
.assert_noise(module, &sk_out_prepared, &sk_in.data, sigma);
|
||||
}
|
||||
|
||||
pub fn test_gglwe_switching_key_compressed_encrypt_sk<B>(
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
k_ksk: usize,
|
||||
digits: usize,
|
||||
rank_in: usize,
|
||||
rank_out: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxSubScalarInplace
|
||||
+ VecZnxCopy
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>
|
||||
+ VecZnxDftAllocBytesImpl<B>
|
||||
+ VecZnxBigAllocBytesImpl<B>
|
||||
+ TakeSvpPPolImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = (k_ksk - digits * basek) / (digits * basek);
|
||||
|
||||
let mut ksk_compressed: GGLWESwitchingKeyCompressed<Vec<u8>> =
|
||||
GGLWESwitchingKeyCompressed::alloc(n, basek, k_ksk, rows, digits, rank_in, rank_out);
|
||||
|
||||
let mut source_xs: Source = Source::new([0u8; 32]);
|
||||
let mut source_xe: Source = Source::new([0u8; 32]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWESwitchingKeyCompressed::encrypt_sk_scratch_space(
|
||||
module, n, basek, k_ksk, rank_in, rank_out,
|
||||
));
|
||||
|
||||
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in);
|
||||
sk_in.fill_ternary_prob(0.5, &mut source_xs);
|
||||
|
||||
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out);
|
||||
sk_out.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
let seed_xa = [1u8; 32];
|
||||
|
||||
ksk_compressed.encrypt_sk(
|
||||
module,
|
||||
&sk_in,
|
||||
&sk_out,
|
||||
seed_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_in, rank_out);
|
||||
ksk.decompress(module, &ksk_compressed);
|
||||
|
||||
ksk.key
|
||||
.assert_noise(module, &sk_out_prepared, &sk_in.data, sigma);
|
||||
}
|
||||
180
poulpy-core/src/tests/generics/encryption/ggsw_ct.rs
Normal file
180
poulpy-core/src/tests/generics/encryption/ggsw_ct.rs
Normal file
@@ -0,0 +1,180 @@
|
||||
use poulpy_backend::hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, VecZnxAddInplace,
|
||||
VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc,
|
||||
VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAlloc, VecZnxDftAllocBytes,
|
||||
VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigConsume, VecZnxDftToVecZnxBigTmpA, VecZnxFillUniform, VecZnxNormalize,
|
||||
VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubABInplace, VmpPMatAlloc, VmpPrepare,
|
||||
},
|
||||
layouts::{Backend, Module, ScalarZnx, ScratchOwned},
|
||||
oep::{
|
||||
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
|
||||
TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
GGSWCiphertext, GLWESecret,
|
||||
compressed::{Decompress, GGSWCiphertextCompressed},
|
||||
prepared::{GLWESecretPrepared, PrepareAlloc},
|
||||
};
|
||||
|
||||
pub fn test_ggsw_encrypt_sk<B>(module: &Module<B>, basek: usize, k: usize, digits: usize, rank: usize, sigma: f64)
|
||||
where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxCopy
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VecZnxBigAlloc<B>
|
||||
+ VecZnxDftAlloc<B>
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxDftToVecZnxBigTmpA<B>,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>
|
||||
+ VecZnxDftAllocBytesImpl<B>
|
||||
+ VecZnxBigAllocBytesImpl<B>
|
||||
+ TakeSvpPPolImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = (k - digits * basek) / (digits * basek);
|
||||
|
||||
let mut ct: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k, rows, digits, rank);
|
||||
|
||||
let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
|
||||
|
||||
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]);
|
||||
|
||||
pt_scalar.fill_ternary_hw(0, n, &mut source_xs);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGSWCiphertext::encrypt_sk_scratch_space(
|
||||
module, n, basek, k, rank,
|
||||
));
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
ct.encrypt_sk(
|
||||
module,
|
||||
&pt_scalar,
|
||||
&sk_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let noise_f = |_col_i: usize| -(k as f64) + sigma.log2() + 0.5;
|
||||
|
||||
ct.assert_noise(module, &sk_prepared, &pt_scalar, noise_f);
|
||||
}
|
||||
|
||||
pub fn test_ggsw_compressed_encrypt_sk<B>(module: &Module<B>, basek: usize, k: usize, digits: usize, rank: usize, sigma: f64)
|
||||
where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxCopy
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VecZnxBigAlloc<B>
|
||||
+ VecZnxDftAlloc<B>
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxDftToVecZnxBigTmpA<B>,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>
|
||||
+ VecZnxDftAllocBytesImpl<B>
|
||||
+ VecZnxBigAllocBytesImpl<B>
|
||||
+ TakeSvpPPolImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = (k - digits * basek) / (digits * basek);
|
||||
|
||||
let mut ct_compressed: GGSWCiphertextCompressed<Vec<u8>> = GGSWCiphertextCompressed::alloc(n, basek, k, rows, digits, rank);
|
||||
|
||||
let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
|
||||
|
||||
let mut source_xs: Source = Source::new([0u8; 32]);
|
||||
let mut source_xe: Source = Source::new([0u8; 32]);
|
||||
|
||||
pt_scalar.fill_ternary_hw(0, n, &mut source_xs);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGSWCiphertextCompressed::encrypt_sk_scratch_space(
|
||||
module, n, basek, k, rank,
|
||||
));
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
let seed_xa: [u8; 32] = [1u8; 32];
|
||||
|
||||
ct_compressed.encrypt_sk(
|
||||
module,
|
||||
&pt_scalar,
|
||||
&sk_prepared,
|
||||
seed_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let noise_f = |_col_i: usize| -(k as f64) + sigma.log2() + 0.5;
|
||||
|
||||
let mut ct: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k, rows, digits, rank);
|
||||
ct.decompress(module, &ct_compressed);
|
||||
|
||||
ct.assert_noise(module, &sk_prepared, &pt_scalar, noise_f);
|
||||
}
|
||||
375
poulpy-core/src/tests/generics/encryption/glwe_ct.rs
Normal file
375
poulpy-core/src/tests/generics/encryption/glwe_ct.rs
Normal file
@@ -0,0 +1,375 @@
|
||||
use poulpy_backend::hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApply, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare,
|
||||
VecZnxAddInplace, VecZnxAddNormal, VecZnxBigAddInplace, VecZnxBigAddNormal, VecZnxBigAddSmallInplace,
|
||||
VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxCopy, VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftFromVecZnx,
|
||||
VecZnxDftToVecZnxBigConsume, VecZnxFillUniform, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes,
|
||||
VecZnxSub, VecZnxSubABInplace,
|
||||
},
|
||||
layouts::{Backend, Module, ScratchOwned},
|
||||
oep::{
|
||||
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
|
||||
TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
layouts::{
|
||||
GLWECiphertext, GLWEPlaintext, GLWEPublicKey, GLWESecret, Infos,
|
||||
compressed::{Decompress, GLWECiphertextCompressed},
|
||||
prepared::{GLWEPublicKeyPrepared, GLWESecretPrepared, PrepareAlloc},
|
||||
},
|
||||
operations::GLWEOperations,
|
||||
};
|
||||
|
||||
pub fn test_glwe_encrypt_sk<B>(module: &Module<B>, basek: usize, k_ct: usize, k_pt: usize, sigma: f64, rank: usize)
|
||||
where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxDftAllocBytes
|
||||
+ VecZnxBigAllocBytes
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPrepare<B>
|
||||
+ SvpApply<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxBigAddNormal<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>,
|
||||
{
|
||||
let n = module.n();
|
||||
let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank);
|
||||
let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_pt);
|
||||
let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_pt);
|
||||
|
||||
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]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, ct.k())
|
||||
| GLWECiphertext::decrypt_scratch_space(module, n, basek, ct.k()),
|
||||
);
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_pt, &mut source_xa);
|
||||
|
||||
ct.encrypt_sk(
|
||||
module,
|
||||
&pt_want,
|
||||
&sk_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
ct.decrypt(module, &mut pt_have, &sk_prepared, scratch.borrow());
|
||||
|
||||
pt_want.sub_inplace_ab(module, &pt_have);
|
||||
|
||||
let noise_have: f64 = pt_want.data.std(basek, 0) * (ct.k() as f64).exp2();
|
||||
let noise_want: f64 = sigma;
|
||||
|
||||
assert!(noise_have <= noise_want + 0.2);
|
||||
}
|
||||
|
||||
pub fn test_glwe_compressed_encrypt_sk<B>(module: &Module<B>, basek: usize, k_ct: usize, k_pt: usize, sigma: f64, rank: usize)
|
||||
where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxDftAllocBytes
|
||||
+ VecZnxBigAllocBytes
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPrepare<B>
|
||||
+ SvpApply<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxBigAddNormal<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ VecZnxCopy,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>,
|
||||
{
|
||||
let n = module.n();
|
||||
let mut ct_compressed: GLWECiphertextCompressed<Vec<u8>> = GLWECiphertextCompressed::alloc(n, basek, k_ct, rank);
|
||||
|
||||
let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_pt);
|
||||
let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_pt);
|
||||
|
||||
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]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GLWECiphertextCompressed::encrypt_sk_scratch_space(module, n, basek, k_ct)
|
||||
| GLWECiphertext::decrypt_scratch_space(module, n, basek, k_ct),
|
||||
);
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_pt, &mut source_xa);
|
||||
|
||||
let seed_xa: [u8; 32] = [1u8; 32];
|
||||
|
||||
ct_compressed.encrypt_sk(
|
||||
module,
|
||||
&pt_want,
|
||||
&sk_prepared,
|
||||
seed_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank);
|
||||
ct.decompress(module, &ct_compressed);
|
||||
|
||||
ct.decrypt(module, &mut pt_have, &sk_prepared, scratch.borrow());
|
||||
|
||||
pt_want.sub_inplace_ab(module, &pt_have);
|
||||
|
||||
let noise_have: f64 = pt_want.data.std(basek, 0) * (ct.k() as f64).exp2();
|
||||
let noise_want: f64 = sigma;
|
||||
|
||||
assert!(
|
||||
noise_have <= noise_want + 0.2,
|
||||
"{} <= {}",
|
||||
noise_have,
|
||||
noise_want + 0.2
|
||||
);
|
||||
}
|
||||
|
||||
pub fn test_glwe_encrypt_zero_sk<B>(module: &Module<B>, basek: usize, k_ct: usize, sigma: f64, rank: usize)
|
||||
where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxDftAllocBytes
|
||||
+ VecZnxBigAllocBytes
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPrepare<B>
|
||||
+ SvpApply<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxBigAddNormal<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>,
|
||||
{
|
||||
let n = module.n();
|
||||
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_ct);
|
||||
|
||||
let mut source_xs: Source = Source::new([0u8; 32]);
|
||||
let mut source_xe: Source = Source::new([1u8; 32]);
|
||||
let mut source_xa: Source = Source::new([0u8; 32]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GLWECiphertext::decrypt_scratch_space(module, n, basek, k_ct)
|
||||
| GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k_ct),
|
||||
);
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank);
|
||||
|
||||
ct.encrypt_zero_sk(
|
||||
module,
|
||||
&sk_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
ct.decrypt(module, &mut pt, &sk_prepared, scratch.borrow());
|
||||
|
||||
assert!((sigma - pt.data.std(basek, 0) * (k_ct as f64).exp2()) <= 0.2);
|
||||
}
|
||||
|
||||
pub fn test_glwe_encrypt_pk<B>(module: &Module<B>, basek: usize, k_ct: usize, k_pk: usize, sigma: f64, rank: usize)
|
||||
where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxCopy
|
||||
+ VecZnxDftAlloc<B>
|
||||
+ SvpApply<B>
|
||||
+ VecZnxBigAddNormal<B>,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank);
|
||||
let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_ct);
|
||||
let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_ct);
|
||||
|
||||
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]);
|
||||
let mut source_xu: Source = Source::new([0u8; 32]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, ct.k())
|
||||
| GLWECiphertext::decrypt_scratch_space(module, n, basek, ct.k())
|
||||
| GLWECiphertext::encrypt_pk_scratch_space(module, n, basek, k_pk),
|
||||
);
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
let mut pk: GLWEPublicKey<Vec<u8>> = GLWEPublicKey::alloc(n, basek, k_pk, rank);
|
||||
pk.generate_from_sk(module, &sk_prepared, &mut source_xa, &mut source_xe, sigma);
|
||||
|
||||
module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_ct, &mut source_xa);
|
||||
|
||||
let pk_prepared: GLWEPublicKeyPrepared<Vec<u8>, B> = pk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
ct.encrypt_pk(
|
||||
module,
|
||||
&pt_want,
|
||||
&pk_prepared,
|
||||
&mut source_xu,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
ct.decrypt(module, &mut pt_have, &sk_prepared, scratch.borrow());
|
||||
|
||||
pt_want.sub_inplace_ab(module, &pt_have);
|
||||
|
||||
let noise_have: f64 = pt_want.data.std(basek, 0).log2();
|
||||
let noise_want: f64 = ((((rank as f64) + 1.0) * n as f64 * 0.5 * sigma * sigma).sqrt()).log2() - (k_ct as f64);
|
||||
|
||||
assert!(
|
||||
noise_have <= noise_want + 0.2,
|
||||
"{} {}",
|
||||
noise_have,
|
||||
noise_want
|
||||
);
|
||||
}
|
||||
248
poulpy-core/src/tests/generics/encryption/glwe_tsk.rs
Normal file
248
poulpy-core/src/tests/generics/encryption/glwe_tsk.rs
Normal file
@@ -0,0 +1,248 @@
|
||||
use poulpy_backend::hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApply, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare,
|
||||
VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc,
|
||||
VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxCopy, VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftFromVecZnx,
|
||||
VecZnxDftToVecZnxBigConsume, VecZnxDftToVecZnxBigTmpA, VecZnxFillUniform, VecZnxNormalize, VecZnxNormalizeInplace,
|
||||
VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubABInplace, VecZnxSubScalarInplace, VecZnxSwithcDegree,
|
||||
},
|
||||
layouts::{Backend, Module, ScratchOwned, VecZnxDft},
|
||||
oep::{
|
||||
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
|
||||
TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
GGLWETensorKey, GLWEPlaintext, GLWESecret, Infos,
|
||||
compressed::{Decompress, GGLWETensorKeyCompressed},
|
||||
prepared::{GLWESecretPrepared, PrepareAlloc},
|
||||
};
|
||||
|
||||
pub fn test_glwe_tensor_key_encrypt_sk<B>(module: &Module<B>, basek: usize, k: usize, sigma: f64, rank: usize)
|
||||
where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxCopy
|
||||
+ VecZnxDftAlloc<B>
|
||||
+ SvpApply<B>
|
||||
+ VecZnxBigAlloc<B>
|
||||
+ VecZnxDftToVecZnxBigTmpA<B>
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxSubScalarInplace,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>
|
||||
+ VecZnxDftAllocBytesImpl<B>
|
||||
+ VecZnxBigAllocBytesImpl<B>
|
||||
+ TakeSvpPPolImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = k / basek;
|
||||
|
||||
let mut tensor_key: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(n, basek, k, rows, 1, rank);
|
||||
|
||||
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]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWETensorKey::encrypt_sk_scratch_space(
|
||||
module,
|
||||
n,
|
||||
basek,
|
||||
tensor_key.k(),
|
||||
rank,
|
||||
));
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
tensor_key.encrypt_sk(
|
||||
module,
|
||||
&sk,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k);
|
||||
|
||||
let mut sk_ij_dft = module.vec_znx_dft_alloc(n, 1, 1);
|
||||
let mut sk_ij_big = module.vec_znx_big_alloc(n, 1, 1);
|
||||
let mut sk_ij: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, 1);
|
||||
let mut sk_dft: VecZnxDft<Vec<u8>, B> = module.vec_znx_dft_alloc(n, rank, 1);
|
||||
|
||||
(0..rank).for_each(|i| {
|
||||
module.vec_znx_dft_from_vec_znx(1, 0, &mut sk_dft, i, &sk.data.as_vec_znx(), i);
|
||||
});
|
||||
|
||||
(0..rank).for_each(|i| {
|
||||
(0..rank).for_each(|j| {
|
||||
module.svp_apply(&mut sk_ij_dft, 0, &sk_prepared.data, j, &sk_dft, i);
|
||||
module.vec_znx_dft_to_vec_znx_big_tmp_a(&mut sk_ij_big, 0, &mut sk_ij_dft, 0);
|
||||
module.vec_znx_big_normalize(
|
||||
basek,
|
||||
&mut sk_ij.data.as_vec_znx_mut(),
|
||||
0,
|
||||
&sk_ij_big,
|
||||
0,
|
||||
scratch.borrow(),
|
||||
);
|
||||
(0..tensor_key.rank_in()).for_each(|col_i| {
|
||||
(0..tensor_key.rows()).for_each(|row_i| {
|
||||
tensor_key
|
||||
.at(i, j)
|
||||
.at(row_i, col_i)
|
||||
.decrypt(module, &mut pt, &sk_prepared, scratch.borrow());
|
||||
|
||||
module.vec_znx_sub_scalar_inplace(&mut pt.data, 0, row_i, &sk_ij.data, col_i);
|
||||
|
||||
let std_pt: f64 = pt.data.std(basek, 0) * (k as f64).exp2();
|
||||
assert!((sigma - std_pt).abs() <= 0.5, "{} {}", sigma, std_pt);
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn test_glwe_tensor_key_compressed_encrypt_sk<B>(module: &Module<B>, basek: usize, k: usize, sigma: f64, rank: usize)
|
||||
where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxCopy
|
||||
+ VecZnxDftAlloc<B>
|
||||
+ SvpApply<B>
|
||||
+ VecZnxBigAlloc<B>
|
||||
+ VecZnxDftToVecZnxBigTmpA<B>
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxSubScalarInplace,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>
|
||||
+ VecZnxDftAllocBytesImpl<B>
|
||||
+ VecZnxBigAllocBytesImpl<B>
|
||||
+ TakeSvpPPolImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = k / basek;
|
||||
|
||||
let mut tensor_key_compressed: GGLWETensorKeyCompressed<Vec<u8>> =
|
||||
GGLWETensorKeyCompressed::alloc(n, basek, k, rows, 1, rank);
|
||||
|
||||
let mut source_xs: Source = Source::new([0u8; 32]);
|
||||
let mut source_xe: Source = Source::new([0u8; 32]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWETensorKeyCompressed::encrypt_sk_scratch_space(
|
||||
module,
|
||||
n,
|
||||
basek,
|
||||
tensor_key_compressed.k(),
|
||||
rank,
|
||||
));
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
let seed_xa: [u8; 32] = [1u8; 32];
|
||||
|
||||
tensor_key_compressed.encrypt_sk(
|
||||
module,
|
||||
&sk,
|
||||
seed_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut tensor_key: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(n, basek, k, rows, 1, rank);
|
||||
tensor_key.decompress(module, &tensor_key_compressed);
|
||||
|
||||
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k);
|
||||
|
||||
let mut sk_ij_dft = module.vec_znx_dft_alloc(n, 1, 1);
|
||||
let mut sk_ij_big = module.vec_znx_big_alloc(n, 1, 1);
|
||||
let mut sk_ij: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, 1);
|
||||
let mut sk_dft: VecZnxDft<Vec<u8>, B> = module.vec_znx_dft_alloc(n, rank, 1);
|
||||
|
||||
(0..rank).for_each(|i| {
|
||||
module.vec_znx_dft_from_vec_znx(1, 0, &mut sk_dft, i, &sk.data.as_vec_znx(), i);
|
||||
});
|
||||
|
||||
(0..rank).for_each(|i| {
|
||||
(0..rank).for_each(|j| {
|
||||
module.svp_apply(&mut sk_ij_dft, 0, &sk_prepared.data, j, &sk_dft, i);
|
||||
module.vec_znx_dft_to_vec_znx_big_tmp_a(&mut sk_ij_big, 0, &mut sk_ij_dft, 0);
|
||||
module.vec_znx_big_normalize(
|
||||
basek,
|
||||
&mut sk_ij.data.as_vec_znx_mut(),
|
||||
0,
|
||||
&sk_ij_big,
|
||||
0,
|
||||
scratch.borrow(),
|
||||
);
|
||||
(0..tensor_key.rank_in()).for_each(|col_i| {
|
||||
(0..tensor_key.rows()).for_each(|row_i| {
|
||||
tensor_key
|
||||
.at(i, j)
|
||||
.at(row_i, col_i)
|
||||
.decrypt(module, &mut pt, &sk_prepared, scratch.borrow());
|
||||
|
||||
module.vec_znx_sub_scalar_inplace(&mut pt.data, 0, row_i, &sk_ij.data, col_i);
|
||||
|
||||
let std_pt: f64 = pt.data.std(basek, 0) * (k as f64).exp2();
|
||||
assert!((sigma - std_pt).abs() <= 0.5, "{} {}", sigma, std_pt);
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
}
|
||||
11
poulpy-core/src/tests/generics/encryption/mod.rs
Normal file
11
poulpy-core/src/tests/generics/encryption/mod.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
mod gglwe_atk;
|
||||
mod gglwe_ct;
|
||||
mod ggsw_ct;
|
||||
mod glwe_ct;
|
||||
mod glwe_tsk;
|
||||
|
||||
pub use gglwe_atk::*;
|
||||
pub use gglwe_ct::*;
|
||||
pub use ggsw_ct::*;
|
||||
pub use glwe_ct::*;
|
||||
pub use glwe_tsk::*;
|
||||
309
poulpy-core/src/tests/generics/external_product/gglwe_ksk.rs
Normal file
309
poulpy-core/src/tests/generics/external_product/gglwe_ksk.rs
Normal file
@@ -0,0 +1,309 @@
|
||||
use poulpy_backend::hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, VecZnxAddInplace,
|
||||
VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAllocBytes,
|
||||
VecZnxBigNormalize, VecZnxCopy, VecZnxDftAllocBytes, VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigConsume, VecZnxFillUniform,
|
||||
VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotateInplace, VecZnxSub, VecZnxSubABInplace,
|
||||
VecZnxSubScalarInplace, VecZnxSwithcDegree, VmpApply, VmpApplyAdd, VmpApplyTmpBytes, VmpPMatAlloc, VmpPrepare,
|
||||
ZnxViewMut,
|
||||
},
|
||||
layouts::{Backend, Module, ScalarZnx, ScalarZnxToMut, ScratchOwned},
|
||||
oep::{
|
||||
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
|
||||
TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
layouts::{
|
||||
GGLWESwitchingKey, GGSWCiphertext, GLWESecret,
|
||||
prepared::{GGSWCiphertextPrepared, GLWESecretPrepared, PrepareAlloc},
|
||||
},
|
||||
noise::noise_ggsw_product,
|
||||
};
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn test_gglwe_switching_key_external_product<B>(
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
k_out: usize,
|
||||
k_in: usize,
|
||||
k_ggsw: usize,
|
||||
digits: usize,
|
||||
rank_in: usize,
|
||||
rank_out: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxSubScalarInplace
|
||||
+ VecZnxCopy
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VecZnxRotateInplace
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VmpPrepare<B>,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>
|
||||
+ VecZnxDftAllocBytesImpl<B>
|
||||
+ VecZnxBigAllocBytesImpl<B>
|
||||
+ TakeSvpPPolImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = k_in.div_ceil(basek * digits);
|
||||
let digits_in: usize = 1;
|
||||
|
||||
let mut ct_gglwe_in: GGLWESwitchingKey<Vec<u8>> =
|
||||
GGLWESwitchingKey::alloc(n, basek, k_in, rows, digits_in, rank_in, rank_out);
|
||||
let mut ct_gglwe_out: GGLWESwitchingKey<Vec<u8>> =
|
||||
GGLWESwitchingKey::alloc(n, basek, k_out, rows, digits_in, rank_in, rank_out);
|
||||
let mut ct_rgsw: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank_out);
|
||||
|
||||
let mut pt_rgsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
|
||||
|
||||
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]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_in, rank_in, rank_out)
|
||||
| GGLWESwitchingKey::external_product_scratch_space(module, n, basek, k_out, k_in, k_ggsw, digits, rank_out)
|
||||
| GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ggsw, rank_out),
|
||||
);
|
||||
|
||||
let r: usize = 1;
|
||||
|
||||
pt_rgsw.to_mut().raw_mut()[r] = 1; // X^{r}
|
||||
|
||||
let var_xs: f64 = 0.5;
|
||||
|
||||
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in);
|
||||
sk_in.fill_ternary_prob(var_xs, &mut source_xs);
|
||||
|
||||
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out);
|
||||
sk_out.fill_ternary_prob(var_xs, &mut source_xs);
|
||||
let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
// gglwe_{s1}(s0) = s0 -> s1
|
||||
ct_gglwe_in.encrypt_sk(
|
||||
module,
|
||||
&sk_in,
|
||||
&sk_out,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
ct_rgsw.encrypt_sk(
|
||||
module,
|
||||
&pt_rgsw,
|
||||
&sk_out_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let ct_rgsw_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = ct_rgsw.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
// gglwe_(m) (x) RGSW_(X^k) = gglwe_(m * X^k)
|
||||
ct_gglwe_out.external_product(module, &ct_gglwe_in, &ct_rgsw_prepared, scratch.borrow());
|
||||
|
||||
(0..rank_in).for_each(|i| {
|
||||
module.vec_znx_rotate_inplace(r as i64, &mut sk_in.data.as_vec_znx_mut(), i); // * X^{r}
|
||||
});
|
||||
|
||||
let var_gct_err_lhs: f64 = sigma * sigma;
|
||||
let var_gct_err_rhs: f64 = 0f64;
|
||||
|
||||
let var_msg: f64 = 1f64 / n as f64; // X^{k}
|
||||
let var_a0_err: f64 = sigma * sigma;
|
||||
let var_a1_err: f64 = 1f64 / 12f64;
|
||||
|
||||
let max_noise: f64 = noise_ggsw_product(
|
||||
n as f64,
|
||||
basek * digits,
|
||||
var_xs,
|
||||
var_msg,
|
||||
var_a0_err,
|
||||
var_a1_err,
|
||||
var_gct_err_lhs,
|
||||
var_gct_err_rhs,
|
||||
rank_out as f64,
|
||||
k_in,
|
||||
k_ggsw,
|
||||
);
|
||||
|
||||
ct_gglwe_out
|
||||
.key
|
||||
.assert_noise(module, &sk_out_prepared, &sk_in.data, max_noise + 0.5);
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn test_gglwe_switching_key_external_product_inplace<B>(
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
k_ct: usize,
|
||||
k_ggsw: usize,
|
||||
digits: usize,
|
||||
rank_in: usize,
|
||||
rank_out: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxSubScalarInplace
|
||||
+ VecZnxCopy
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VecZnxRotateInplace
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VmpPrepare<B>,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>
|
||||
+ VecZnxDftAllocBytesImpl<B>
|
||||
+ VecZnxBigAllocBytesImpl<B>
|
||||
+ TakeSvpPPolImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = k_ct.div_ceil(basek * digits);
|
||||
|
||||
let digits_in: usize = 1;
|
||||
|
||||
let mut ct_gglwe: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_ct, rows, digits_in, rank_in, rank_out);
|
||||
let mut ct_rgsw: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank_out);
|
||||
|
||||
let mut pt_rgsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
|
||||
|
||||
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]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ct, rank_in, rank_out)
|
||||
| GGLWESwitchingKey::external_product_inplace_scratch_space(module, n, basek, k_ct, k_ggsw, digits, rank_out)
|
||||
| GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ggsw, rank_out),
|
||||
);
|
||||
|
||||
let r: usize = 1;
|
||||
|
||||
pt_rgsw.to_mut().raw_mut()[r] = 1; // X^{r}
|
||||
|
||||
let var_xs: f64 = 0.5;
|
||||
|
||||
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in);
|
||||
sk_in.fill_ternary_prob(var_xs, &mut source_xs);
|
||||
|
||||
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out);
|
||||
sk_out.fill_ternary_prob(var_xs, &mut source_xs);
|
||||
let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
// gglwe_{s1}(s0) = s0 -> s1
|
||||
ct_gglwe.encrypt_sk(
|
||||
module,
|
||||
&sk_in,
|
||||
&sk_out,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
ct_rgsw.encrypt_sk(
|
||||
module,
|
||||
&pt_rgsw,
|
||||
&sk_out_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let ct_rgsw_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = ct_rgsw.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
// gglwe_(m) (x) RGSW_(X^k) = gglwe_(m * X^k)
|
||||
ct_gglwe.external_product_inplace(module, &ct_rgsw_prepared, scratch.borrow());
|
||||
|
||||
(0..rank_in).for_each(|i| {
|
||||
module.vec_znx_rotate_inplace(r as i64, &mut sk_in.data.as_vec_znx_mut(), i); // * X^{r}
|
||||
});
|
||||
|
||||
let var_gct_err_lhs: f64 = sigma * sigma;
|
||||
let var_gct_err_rhs: f64 = 0f64;
|
||||
|
||||
let var_msg: f64 = 1f64 / n as f64; // X^{k}
|
||||
let var_a0_err: f64 = sigma * sigma;
|
||||
let var_a1_err: f64 = 1f64 / 12f64;
|
||||
|
||||
let max_noise: f64 = noise_ggsw_product(
|
||||
n as f64,
|
||||
basek * digits,
|
||||
var_xs,
|
||||
var_msg,
|
||||
var_a0_err,
|
||||
var_a1_err,
|
||||
var_gct_err_lhs,
|
||||
var_gct_err_rhs,
|
||||
rank_out as f64,
|
||||
k_ct,
|
||||
k_ggsw,
|
||||
);
|
||||
|
||||
ct_gglwe
|
||||
.key
|
||||
.assert_noise(module, &sk_out_prepared, &sk_in.data, max_noise + 0.5);
|
||||
}
|
||||
295
poulpy-core/src/tests/generics/external_product/ggsw_ct.rs
Normal file
295
poulpy-core/src/tests/generics/external_product/ggsw_ct.rs
Normal file
@@ -0,0 +1,295 @@
|
||||
use poulpy_backend::hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, VecZnxAddInplace,
|
||||
VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc,
|
||||
VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAlloc, VecZnxDftAllocBytes,
|
||||
VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigConsume, VecZnxDftToVecZnxBigTmpA, VecZnxFillUniform, VecZnxNormalize,
|
||||
VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotateInplace, VecZnxSub, VecZnxSubABInplace, VmpApply,
|
||||
VmpApplyAdd, VmpApplyTmpBytes, VmpPMatAlloc, VmpPrepare, ZnxViewMut,
|
||||
},
|
||||
layouts::{Backend, Module, ScalarZnx, ScalarZnxToMut, ScratchOwned},
|
||||
oep::{
|
||||
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
|
||||
TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
layouts::{
|
||||
GGSWCiphertext, GLWESecret,
|
||||
prepared::{GGSWCiphertextPrepared, GLWESecretPrepared, PrepareAlloc},
|
||||
},
|
||||
noise::noise_ggsw_product,
|
||||
};
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn test_ggsw_external_product<B>(
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
k_in: usize,
|
||||
k_out: usize,
|
||||
k_ggsw: usize,
|
||||
digits: usize,
|
||||
rank: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxCopy
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VecZnxRotateInplace
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VecZnxBigAlloc<B>
|
||||
+ VecZnxDftAlloc<B>
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxDftToVecZnxBigTmpA<B>,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>
|
||||
+ VecZnxDftAllocBytesImpl<B>
|
||||
+ VecZnxBigAllocBytesImpl<B>
|
||||
+ TakeSvpPPolImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = k_in.div_ceil(basek * digits);
|
||||
let rows_in: usize = k_in.div_euclid(basek * digits);
|
||||
let digits_in: usize = 1;
|
||||
|
||||
let mut ct_ggsw_lhs_in: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_in, rows_in, digits_in, rank);
|
||||
let mut ct_ggsw_lhs_out: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_out, rows_in, digits_in, rank);
|
||||
let mut ct_ggsw_rhs: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank);
|
||||
let mut pt_ggsw_lhs: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
|
||||
let mut pt_ggsw_rhs: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
|
||||
|
||||
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]);
|
||||
|
||||
pt_ggsw_lhs.fill_ternary_prob(0, 0.5, &mut source_xs);
|
||||
|
||||
let k: usize = 1;
|
||||
|
||||
pt_ggsw_rhs.to_mut().raw_mut()[k] = 1; //X^{k}
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ggsw, rank)
|
||||
| GGSWCiphertext::external_product_scratch_space(module, n, basek, k_out, k_in, k_ggsw, digits, rank),
|
||||
);
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
ct_ggsw_rhs.encrypt_sk(
|
||||
module,
|
||||
&pt_ggsw_rhs,
|
||||
&sk_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
ct_ggsw_lhs_in.encrypt_sk(
|
||||
module,
|
||||
&pt_ggsw_lhs,
|
||||
&sk_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let ct_rhs_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = ct_ggsw_rhs.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
ct_ggsw_lhs_out.external_product(module, &ct_ggsw_lhs_in, &ct_rhs_prepared, scratch.borrow());
|
||||
|
||||
module.vec_znx_rotate_inplace(k as i64, &mut pt_ggsw_lhs.as_vec_znx_mut(), 0);
|
||||
|
||||
let var_gct_err_lhs: f64 = sigma * sigma;
|
||||
let var_gct_err_rhs: f64 = 0f64;
|
||||
|
||||
let var_msg: f64 = 1f64 / n as f64; // X^{k}
|
||||
let var_a0_err: f64 = sigma * sigma;
|
||||
let var_a1_err: f64 = 1f64 / 12f64;
|
||||
|
||||
let max_noise = |_col_j: usize| -> f64 {
|
||||
noise_ggsw_product(
|
||||
n as f64,
|
||||
basek * digits,
|
||||
0.5,
|
||||
var_msg,
|
||||
var_a0_err,
|
||||
var_a1_err,
|
||||
var_gct_err_lhs,
|
||||
var_gct_err_rhs,
|
||||
rank as f64,
|
||||
k_in,
|
||||
k_ggsw,
|
||||
) + 0.5
|
||||
};
|
||||
|
||||
ct_ggsw_lhs_out.assert_noise(module, &sk_prepared, &pt_ggsw_lhs, max_noise);
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn test_ggsw_external_product_inplace<B>(
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
k_ct: usize,
|
||||
k_ggsw: usize,
|
||||
digits: usize,
|
||||
rank: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxCopy
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VecZnxRotateInplace
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VecZnxBigAlloc<B>
|
||||
+ VecZnxDftAlloc<B>
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxDftToVecZnxBigTmpA<B>,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>
|
||||
+ VecZnxDftAllocBytesImpl<B>
|
||||
+ VecZnxBigAllocBytesImpl<B>
|
||||
+ TakeSvpPPolImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = k_ct.div_ceil(digits * basek);
|
||||
let rows_in: usize = k_ct.div_euclid(basek * digits);
|
||||
let digits_in: usize = 1;
|
||||
|
||||
let mut ct_ggsw_lhs: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ct, rows_in, digits_in, rank);
|
||||
let mut ct_ggsw_rhs: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank);
|
||||
|
||||
let mut pt_ggsw_lhs: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
|
||||
let mut pt_ggsw_rhs: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
|
||||
|
||||
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]);
|
||||
|
||||
pt_ggsw_lhs.fill_ternary_prob(0, 0.5, &mut source_xs);
|
||||
|
||||
let k: usize = 1;
|
||||
|
||||
pt_ggsw_rhs.to_mut().raw_mut()[k] = 1; //X^{k}
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ggsw, rank)
|
||||
| GGSWCiphertext::external_product_inplace_scratch_space(module, n, basek, k_ct, k_ggsw, digits, rank),
|
||||
);
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
ct_ggsw_rhs.encrypt_sk(
|
||||
module,
|
||||
&pt_ggsw_rhs,
|
||||
&sk_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
ct_ggsw_lhs.encrypt_sk(
|
||||
module,
|
||||
&pt_ggsw_lhs,
|
||||
&sk_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let ct_rhs_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = ct_ggsw_rhs.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
ct_ggsw_lhs.external_product_inplace(module, &ct_rhs_prepared, scratch.borrow());
|
||||
|
||||
module.vec_znx_rotate_inplace(k as i64, &mut pt_ggsw_lhs.as_vec_znx_mut(), 0);
|
||||
|
||||
let var_gct_err_lhs: f64 = sigma * sigma;
|
||||
let var_gct_err_rhs: f64 = 0f64;
|
||||
|
||||
let var_msg: f64 = 1f64 / n as f64; // X^{k}
|
||||
let var_a0_err: f64 = sigma * sigma;
|
||||
let var_a1_err: f64 = 1f64 / 12f64;
|
||||
|
||||
let max_noise = |_col_j: usize| -> f64 {
|
||||
noise_ggsw_product(
|
||||
n as f64,
|
||||
basek * digits,
|
||||
0.5,
|
||||
var_msg,
|
||||
var_a0_err,
|
||||
var_a1_err,
|
||||
var_gct_err_lhs,
|
||||
var_gct_err_rhs,
|
||||
rank as f64,
|
||||
k_ct,
|
||||
k_ggsw,
|
||||
) + 0.5
|
||||
};
|
||||
|
||||
ct_ggsw_lhs.assert_noise(module, &sk_prepared, &pt_ggsw_lhs, max_noise);
|
||||
}
|
||||
288
poulpy-core/src/tests/generics/external_product/glwe_ct.rs
Normal file
288
poulpy-core/src/tests/generics/external_product/glwe_ct.rs
Normal file
@@ -0,0 +1,288 @@
|
||||
use poulpy_backend::hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, VecZnxAddInplace,
|
||||
VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAllocBytes,
|
||||
VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigConsume, VecZnxFillUniform,
|
||||
VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotateInplace, VecZnxSub, VecZnxSubABInplace,
|
||||
VmpApply, VmpApplyAdd, VmpApplyTmpBytes, VmpPMatAlloc, VmpPrepare, ZnxViewMut,
|
||||
},
|
||||
layouts::{Backend, Module, ScalarZnx, ScratchOwned},
|
||||
oep::{
|
||||
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
|
||||
TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
layouts::{
|
||||
GGSWCiphertext, GLWECiphertext, GLWEPlaintext, GLWESecret, Infos,
|
||||
prepared::{GGSWCiphertextPrepared, GLWESecretPrepared, PrepareAlloc},
|
||||
},
|
||||
noise::noise_ggsw_product,
|
||||
};
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn test_glwe_external_product<B>(
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
k_out: usize,
|
||||
k_in: usize,
|
||||
k_ggsw: usize,
|
||||
digits: usize,
|
||||
rank: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxRotateInplace
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = k_in.div_ceil(basek * digits);
|
||||
|
||||
let mut ct_ggsw: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank);
|
||||
let mut ct_glwe_in: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_in, rank);
|
||||
let mut ct_glwe_out: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_out, rank);
|
||||
let mut pt_rgsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
|
||||
let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_in);
|
||||
|
||||
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]);
|
||||
|
||||
// Random input plaintext
|
||||
module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_in, &mut source_xa);
|
||||
|
||||
pt_want.data.at_mut(0, 0)[1] = 1;
|
||||
|
||||
let k: usize = 1;
|
||||
|
||||
pt_rgsw.raw_mut()[k] = 1; // X^{k}
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, ct_ggsw.k(), rank)
|
||||
| GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, ct_glwe_in.k())
|
||||
| GLWECiphertext::external_product_scratch_space(
|
||||
module,
|
||||
n,
|
||||
basek,
|
||||
ct_glwe_out.k(),
|
||||
ct_glwe_in.k(),
|
||||
ct_ggsw.k(),
|
||||
digits,
|
||||
rank,
|
||||
),
|
||||
);
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
ct_ggsw.encrypt_sk(
|
||||
module,
|
||||
&pt_rgsw,
|
||||
&sk_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
ct_glwe_in.encrypt_sk(
|
||||
module,
|
||||
&pt_want,
|
||||
&sk_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let ct_ggsw_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = ct_ggsw.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
ct_glwe_out.external_product(module, &ct_glwe_in, &ct_ggsw_prepared, scratch.borrow());
|
||||
|
||||
module.vec_znx_rotate_inplace(k as i64, &mut pt_want.data, 0);
|
||||
|
||||
let var_gct_err_lhs: f64 = sigma * sigma;
|
||||
let var_gct_err_rhs: f64 = 0f64;
|
||||
|
||||
let var_msg: f64 = 1f64 / n as f64; // X^{k}
|
||||
let var_a0_err: f64 = sigma * sigma;
|
||||
let var_a1_err: f64 = 1f64 / 12f64;
|
||||
|
||||
let max_noise: f64 = noise_ggsw_product(
|
||||
n as f64,
|
||||
basek * digits,
|
||||
0.5,
|
||||
var_msg,
|
||||
var_a0_err,
|
||||
var_a1_err,
|
||||
var_gct_err_lhs,
|
||||
var_gct_err_rhs,
|
||||
rank as f64,
|
||||
k_in,
|
||||
k_ggsw,
|
||||
);
|
||||
|
||||
ct_glwe_out.assert_noise(module, &sk_prepared, &pt_want, max_noise + 0.5);
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn test_glwe_external_product_inplace<B>(
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
k_ct: usize,
|
||||
k_ggsw: usize,
|
||||
digits: usize,
|
||||
rank: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxRotateInplace
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = k_ct.div_ceil(basek * digits);
|
||||
|
||||
let mut ct_ggsw: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank);
|
||||
let mut ct_glwe: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank);
|
||||
let mut pt_rgsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
|
||||
let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_ct);
|
||||
|
||||
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]);
|
||||
|
||||
// Random input plaintext
|
||||
module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_ct, &mut source_xa);
|
||||
|
||||
pt_want.data.at_mut(0, 0)[1] = 1;
|
||||
|
||||
let k: usize = 1;
|
||||
|
||||
pt_rgsw.raw_mut()[k] = 1; // X^{k}
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, ct_ggsw.k(), rank)
|
||||
| GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, ct_glwe.k())
|
||||
| GLWECiphertext::external_product_inplace_scratch_space(module, n, basek, ct_glwe.k(), ct_ggsw.k(), digits, rank),
|
||||
);
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
ct_ggsw.encrypt_sk(
|
||||
module,
|
||||
&pt_rgsw,
|
||||
&sk_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
ct_glwe.encrypt_sk(
|
||||
module,
|
||||
&pt_want,
|
||||
&sk_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let ct_ggsw_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = ct_ggsw.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
ct_glwe.external_product_inplace(module, &ct_ggsw_prepared, scratch.borrow());
|
||||
|
||||
module.vec_znx_rotate_inplace(k as i64, &mut pt_want.data, 0);
|
||||
|
||||
let var_gct_err_lhs: f64 = sigma * sigma;
|
||||
let var_gct_err_rhs: f64 = 0f64;
|
||||
|
||||
let var_msg: f64 = 1f64 / n as f64; // X^{k}
|
||||
let var_a0_err: f64 = sigma * sigma;
|
||||
let var_a1_err: f64 = 1f64 / 12f64;
|
||||
|
||||
let max_noise: f64 = noise_ggsw_product(
|
||||
n as f64,
|
||||
basek * digits,
|
||||
0.5,
|
||||
var_msg,
|
||||
var_a0_err,
|
||||
var_a1_err,
|
||||
var_gct_err_lhs,
|
||||
var_gct_err_rhs,
|
||||
rank as f64,
|
||||
k_ct,
|
||||
k_ggsw,
|
||||
);
|
||||
|
||||
ct_glwe.assert_noise(module, &sk_prepared, &pt_want, max_noise + 0.5);
|
||||
}
|
||||
7
poulpy-core/src/tests/generics/external_product/mod.rs
Normal file
7
poulpy-core/src/tests/generics/external_product/mod.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
mod gglwe_ksk;
|
||||
mod ggsw_ct;
|
||||
mod glwe_ct;
|
||||
|
||||
pub use gglwe_ksk::*;
|
||||
pub use ggsw_ct::*;
|
||||
pub use glwe_ct::*;
|
||||
311
poulpy-core/src/tests/generics/keyswitch/gglwe_ct.rs
Normal file
311
poulpy-core/src/tests/generics/keyswitch/gglwe_ct.rs
Normal file
@@ -0,0 +1,311 @@
|
||||
use poulpy_backend::hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, VecZnxAddInplace,
|
||||
VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAllocBytes,
|
||||
VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAllocBytes, VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigConsume,
|
||||
VecZnxFillUniform, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubABInplace,
|
||||
VecZnxSubScalarInplace, VecZnxSwithcDegree, VmpApply, VmpApplyAdd, VmpApplyTmpBytes, VmpPMatAlloc, VmpPrepare,
|
||||
},
|
||||
layouts::{Backend, Module, ScratchOwned},
|
||||
oep::{
|
||||
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
|
||||
TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
layouts::{
|
||||
GGLWESwitchingKey, GLWESecret,
|
||||
prepared::{GGLWESwitchingKeyPrepared, GLWESecretPrepared, PrepareAlloc},
|
||||
},
|
||||
noise::log2_std_noise_gglwe_product,
|
||||
};
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn test_gglwe_switching_key_keyswitch<B>(
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
k_out: usize,
|
||||
k_in: usize,
|
||||
k_ksk: usize,
|
||||
digits: usize,
|
||||
rank_in_s0s1: usize,
|
||||
rank_out_s0s1: usize,
|
||||
rank_out_s1s2: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxSubScalarInplace,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = k_in.div_ceil(basek * digits);
|
||||
let digits_in: usize = 1;
|
||||
|
||||
let mut ct_gglwe_s0s1: GGLWESwitchingKey<Vec<u8>> =
|
||||
GGLWESwitchingKey::alloc(n, basek, k_in, rows, digits_in, rank_in_s0s1, rank_out_s0s1);
|
||||
let mut ct_gglwe_s1s2: GGLWESwitchingKey<Vec<u8>> =
|
||||
GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_out_s0s1, rank_out_s1s2);
|
||||
let mut ct_gglwe_s0s2: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(
|
||||
n,
|
||||
basek,
|
||||
k_out,
|
||||
rows,
|
||||
digits_in,
|
||||
rank_in_s0s1,
|
||||
rank_out_s1s2,
|
||||
);
|
||||
|
||||
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]);
|
||||
|
||||
let mut scratch_enc: ScratchOwned<B> = ScratchOwned::alloc(GGLWESwitchingKey::encrypt_sk_scratch_space(
|
||||
module,
|
||||
n,
|
||||
basek,
|
||||
k_ksk,
|
||||
rank_in_s0s1 | rank_out_s0s1,
|
||||
rank_out_s0s1 | rank_out_s1s2,
|
||||
));
|
||||
let mut scratch_apply: ScratchOwned<B> = ScratchOwned::alloc(GGLWESwitchingKey::keyswitch_scratch_space(
|
||||
module,
|
||||
n,
|
||||
basek,
|
||||
k_out,
|
||||
k_in,
|
||||
k_ksk,
|
||||
digits,
|
||||
ct_gglwe_s1s2.rank_in(),
|
||||
ct_gglwe_s1s2.rank_out(),
|
||||
));
|
||||
|
||||
let mut sk0: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in_s0s1);
|
||||
sk0.fill_ternary_prob(0.5, &mut source_xs);
|
||||
|
||||
let mut sk1: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out_s0s1);
|
||||
sk1.fill_ternary_prob(0.5, &mut source_xs);
|
||||
|
||||
let mut sk2: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out_s1s2);
|
||||
sk2.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk2_prepared: GLWESecretPrepared<Vec<u8>, B> = sk2.prepare_alloc(module, scratch_apply.borrow());
|
||||
|
||||
// gglwe_{s1}(s0) = s0 -> s1
|
||||
ct_gglwe_s0s1.encrypt_sk(
|
||||
module,
|
||||
&sk0,
|
||||
&sk1,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch_enc.borrow(),
|
||||
);
|
||||
|
||||
// gglwe_{s2}(s1) -> s1 -> s2
|
||||
ct_gglwe_s1s2.encrypt_sk(
|
||||
module,
|
||||
&sk1,
|
||||
&sk2,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch_enc.borrow(),
|
||||
);
|
||||
|
||||
let ct_gglwe_s1s2_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> =
|
||||
ct_gglwe_s1s2.prepare_alloc(module, scratch_apply.borrow());
|
||||
|
||||
// gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0)
|
||||
ct_gglwe_s0s2.keyswitch(
|
||||
module,
|
||||
&ct_gglwe_s0s1,
|
||||
&ct_gglwe_s1s2_prepared,
|
||||
scratch_apply.borrow(),
|
||||
);
|
||||
|
||||
let max_noise: f64 = log2_std_noise_gglwe_product(
|
||||
n as f64,
|
||||
basek * digits,
|
||||
0.5,
|
||||
0.5,
|
||||
0f64,
|
||||
sigma * sigma,
|
||||
0f64,
|
||||
rank_out_s0s1 as f64,
|
||||
k_in,
|
||||
k_ksk,
|
||||
);
|
||||
|
||||
ct_gglwe_s0s2
|
||||
.key
|
||||
.assert_noise(module, &sk2_prepared, &sk0.data, max_noise + 0.5);
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn test_gglwe_switching_key_keyswitch_inplace<B>(
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
k_ct: usize,
|
||||
k_ksk: usize,
|
||||
digits: usize,
|
||||
rank_in: usize,
|
||||
rank_out: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxSubScalarInplace,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = k_ct.div_ceil(basek * digits);
|
||||
let digits_in: usize = 1;
|
||||
|
||||
let mut ct_gglwe_s0s1: GGLWESwitchingKey<Vec<u8>> =
|
||||
GGLWESwitchingKey::alloc(n, basek, k_ct, rows, digits_in, rank_in, rank_out);
|
||||
let mut ct_gglwe_s1s2: GGLWESwitchingKey<Vec<u8>> =
|
||||
GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_out, rank_out);
|
||||
|
||||
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]);
|
||||
|
||||
let mut scratch_enc: ScratchOwned<B> = ScratchOwned::alloc(GGLWESwitchingKey::encrypt_sk_scratch_space(
|
||||
module,
|
||||
n,
|
||||
basek,
|
||||
k_ksk,
|
||||
rank_in | rank_out,
|
||||
rank_out,
|
||||
));
|
||||
let mut scratch_apply: ScratchOwned<B> = ScratchOwned::alloc(GGLWESwitchingKey::keyswitch_inplace_scratch_space(
|
||||
module, n, basek, k_ct, k_ksk, digits, rank_out,
|
||||
));
|
||||
|
||||
let var_xs: f64 = 0.5;
|
||||
|
||||
let mut sk0: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in);
|
||||
sk0.fill_ternary_prob(var_xs, &mut source_xs);
|
||||
|
||||
let mut sk1: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out);
|
||||
sk1.fill_ternary_prob(var_xs, &mut source_xs);
|
||||
|
||||
let mut sk2: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out);
|
||||
sk2.fill_ternary_prob(var_xs, &mut source_xs);
|
||||
let sk2_prepared: GLWESecretPrepared<Vec<u8>, B> = sk2.prepare_alloc(module, scratch_apply.borrow());
|
||||
|
||||
// gglwe_{s1}(s0) = s0 -> s1
|
||||
ct_gglwe_s0s1.encrypt_sk(
|
||||
module,
|
||||
&sk0,
|
||||
&sk1,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch_enc.borrow(),
|
||||
);
|
||||
|
||||
// gglwe_{s2}(s1) -> s1 -> s2
|
||||
ct_gglwe_s1s2.encrypt_sk(
|
||||
module,
|
||||
&sk1,
|
||||
&sk2,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch_enc.borrow(),
|
||||
);
|
||||
|
||||
let ct_gglwe_s1s2_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> =
|
||||
ct_gglwe_s1s2.prepare_alloc(module, scratch_apply.borrow());
|
||||
|
||||
// gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0)
|
||||
ct_gglwe_s0s1.keyswitch_inplace(module, &ct_gglwe_s1s2_prepared, scratch_apply.borrow());
|
||||
|
||||
let ct_gglwe_s0s2: GGLWESwitchingKey<Vec<u8>> = ct_gglwe_s0s1;
|
||||
|
||||
let max_noise: f64 = log2_std_noise_gglwe_product(
|
||||
n as f64,
|
||||
basek * digits,
|
||||
var_xs,
|
||||
var_xs,
|
||||
0f64,
|
||||
sigma * sigma,
|
||||
0f64,
|
||||
rank_out as f64,
|
||||
k_ct,
|
||||
k_ksk,
|
||||
);
|
||||
|
||||
ct_gglwe_s0s2
|
||||
.key
|
||||
.assert_noise(module, &sk2_prepared, &sk0.data, max_noise + 0.5);
|
||||
}
|
||||
312
poulpy-core/src/tests/generics/keyswitch/ggsw_ct.rs
Normal file
312
poulpy-core/src/tests/generics/keyswitch/ggsw_ct.rs
Normal file
@@ -0,0 +1,312 @@
|
||||
use poulpy_backend::hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApply, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare,
|
||||
VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc,
|
||||
VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAddInplace, VecZnxDftAlloc,
|
||||
VecZnxDftAllocBytes, VecZnxDftCopy, VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigConsume, VecZnxDftToVecZnxBigTmpA,
|
||||
VecZnxFillUniform, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubABInplace,
|
||||
VecZnxSwithcDegree, VmpApply, VmpApplyAdd, VmpApplyTmpBytes, VmpPMatAlloc, VmpPrepare,
|
||||
},
|
||||
layouts::{Backend, Module, ScalarZnx, ScratchOwned},
|
||||
oep::{
|
||||
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
|
||||
TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
layouts::{
|
||||
GGLWESwitchingKey, GGLWETensorKey, GGSWCiphertext, GLWESecret,
|
||||
prepared::{GGLWESwitchingKeyPrepared, GGLWETensorKeyPrepared, GLWESecretPrepared, PrepareAlloc},
|
||||
},
|
||||
noise::noise_ggsw_keyswitch,
|
||||
};
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn test_ggsw_keyswitch<B>(
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
k_out: usize,
|
||||
k_in: usize,
|
||||
k_ksk: usize,
|
||||
k_tsk: usize,
|
||||
digits: usize,
|
||||
rank: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxSwithcDegree
|
||||
+ SvpApply<B>
|
||||
+ VecZnxDftToVecZnxBigTmpA<B>
|
||||
+ VecZnxDftCopy<B>
|
||||
+ VecZnxDftAddInplace<B>
|
||||
+ VecZnxBigAlloc<B>
|
||||
+ VecZnxDftAlloc<B>,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = k_in.div_ceil(digits * basek);
|
||||
|
||||
let digits_in: usize = 1;
|
||||
|
||||
let mut ct_in: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_in, rows, digits_in, rank);
|
||||
let mut ct_out: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_out, rows, digits_in, rank);
|
||||
let mut tsk: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(n, basek, k_ksk, rows, digits, rank);
|
||||
let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank, rank);
|
||||
let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
|
||||
|
||||
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]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_in, rank)
|
||||
| GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank, rank)
|
||||
| GGLWETensorKey::encrypt_sk_scratch_space(module, n, basek, k_tsk, rank)
|
||||
| GGSWCiphertext::keyswitch_scratch_space(
|
||||
module, n, basek, k_out, k_in, k_ksk, digits, k_tsk, digits, rank,
|
||||
),
|
||||
);
|
||||
|
||||
let var_xs: f64 = 0.5;
|
||||
|
||||
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk_in.fill_ternary_prob(var_xs, &mut source_xs);
|
||||
let sk_in_dft: GLWESecretPrepared<Vec<u8>, B> = sk_in.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk_out.fill_ternary_prob(var_xs, &mut source_xs);
|
||||
let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
ksk.encrypt_sk(
|
||||
module,
|
||||
&sk_in,
|
||||
&sk_out,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
tsk.encrypt_sk(
|
||||
module,
|
||||
&sk_out,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
pt_scalar.fill_ternary_hw(0, n, &mut source_xs);
|
||||
|
||||
ct_in.encrypt_sk(
|
||||
module,
|
||||
&pt_scalar,
|
||||
&sk_in_dft,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let ksk_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow());
|
||||
let tsk_prepared: GGLWETensorKeyPrepared<Vec<u8>, B> = tsk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
ct_out.keyswitch(
|
||||
module,
|
||||
&ct_in,
|
||||
&ksk_prepared,
|
||||
&tsk_prepared,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let max_noise = |col_j: usize| -> f64 {
|
||||
noise_ggsw_keyswitch(
|
||||
n as f64,
|
||||
basek * digits,
|
||||
col_j,
|
||||
var_xs,
|
||||
0f64,
|
||||
sigma * sigma,
|
||||
0f64,
|
||||
rank as f64,
|
||||
k_in,
|
||||
k_ksk,
|
||||
k_tsk,
|
||||
) + 0.5
|
||||
};
|
||||
|
||||
ct_out.assert_noise(module, &sk_out_prepared, &pt_scalar, max_noise);
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn test_ggsw_keyswitch_inplace<B>(
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
k_ct: usize,
|
||||
k_ksk: usize,
|
||||
k_tsk: usize,
|
||||
digits: usize,
|
||||
rank: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxSwithcDegree
|
||||
+ SvpApply<B>
|
||||
+ VecZnxDftToVecZnxBigTmpA<B>
|
||||
+ VecZnxDftCopy<B>
|
||||
+ VecZnxDftAddInplace<B>
|
||||
+ VecZnxBigAlloc<B>
|
||||
+ VecZnxDftAlloc<B>,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = k_ct.div_ceil(digits * basek);
|
||||
|
||||
let digits_in: usize = 1;
|
||||
|
||||
let mut ct: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ct, rows, digits_in, rank);
|
||||
let mut tsk: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(n, basek, k_tsk, rows, digits, rank);
|
||||
let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank, rank);
|
||||
let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
|
||||
|
||||
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]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ct, rank)
|
||||
| GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank, rank)
|
||||
| GGLWETensorKey::encrypt_sk_scratch_space(module, n, basek, k_tsk, rank)
|
||||
| GGSWCiphertext::keyswitch_inplace_scratch_space(module, n, basek, k_ct, k_ksk, digits, k_tsk, digits, rank),
|
||||
);
|
||||
|
||||
let var_xs: f64 = 0.5;
|
||||
|
||||
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk_in.fill_ternary_prob(var_xs, &mut source_xs);
|
||||
let sk_in_dft: GLWESecretPrepared<Vec<u8>, B> = sk_in.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk_out.fill_ternary_prob(var_xs, &mut source_xs);
|
||||
let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
ksk.encrypt_sk(
|
||||
module,
|
||||
&sk_in,
|
||||
&sk_out,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
tsk.encrypt_sk(
|
||||
module,
|
||||
&sk_out,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
pt_scalar.fill_ternary_hw(0, n, &mut source_xs);
|
||||
|
||||
ct.encrypt_sk(
|
||||
module,
|
||||
&pt_scalar,
|
||||
&sk_in_dft,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let ksk_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow());
|
||||
let tsk_prepared: GGLWETensorKeyPrepared<Vec<u8>, B> = tsk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
ct.keyswitch_inplace(module, &ksk_prepared, &tsk_prepared, scratch.borrow());
|
||||
|
||||
let max_noise = |col_j: usize| -> f64 {
|
||||
noise_ggsw_keyswitch(
|
||||
n as f64,
|
||||
basek * digits,
|
||||
col_j,
|
||||
var_xs,
|
||||
0f64,
|
||||
sigma * sigma,
|
||||
0f64,
|
||||
rank as f64,
|
||||
k_ct,
|
||||
k_ksk,
|
||||
k_tsk,
|
||||
) + 0.5
|
||||
};
|
||||
|
||||
ct.assert_noise(module, &sk_out_prepared, &pt_scalar, max_noise);
|
||||
}
|
||||
263
poulpy-core/src/tests/generics/keyswitch/glwe_ct.rs
Normal file
263
poulpy-core/src/tests/generics/keyswitch/glwe_ct.rs
Normal file
@@ -0,0 +1,263 @@
|
||||
use poulpy_backend::hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, VecZnxAddInplace,
|
||||
VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAllocBytes,
|
||||
VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAllocBytes, VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigConsume,
|
||||
VecZnxFillUniform, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubABInplace,
|
||||
VecZnxSwithcDegree, VmpApply, VmpApplyAdd, VmpApplyTmpBytes, VmpPMatAlloc, VmpPrepare,
|
||||
},
|
||||
layouts::{Backend, Module, ScratchOwned},
|
||||
oep::{
|
||||
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
|
||||
TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
layouts::{
|
||||
GGLWESwitchingKey, GLWECiphertext, GLWEPlaintext, GLWESecret, Infos,
|
||||
prepared::{GGLWESwitchingKeyPrepared, GLWESecretPrepared, PrepareAlloc},
|
||||
},
|
||||
noise::log2_std_noise_gglwe_product,
|
||||
};
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn test_glwe_keyswitch<B>(
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
k_out: usize,
|
||||
k_in: usize,
|
||||
k_ksk: usize,
|
||||
digits: usize,
|
||||
rank_in: usize,
|
||||
rank_out: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxSwithcDegree,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>,
|
||||
{
|
||||
let n = module.n();
|
||||
let rows: usize = k_in.div_ceil(basek * digits);
|
||||
|
||||
let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_in, rank_out);
|
||||
let mut ct_in: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_in, rank_in);
|
||||
let mut ct_out: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_out, rank_out);
|
||||
let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_in);
|
||||
|
||||
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(basek, &mut pt_want.data, 0, k_in, &mut source_xa);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, ksk.k(), rank_in, rank_out)
|
||||
| GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, ct_in.k())
|
||||
| GLWECiphertext::keyswitch_scratch_space(
|
||||
module,
|
||||
n,
|
||||
basek,
|
||||
ct_out.k(),
|
||||
ct_in.k(),
|
||||
ksk.k(),
|
||||
digits,
|
||||
rank_in,
|
||||
rank_out,
|
||||
),
|
||||
);
|
||||
|
||||
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in);
|
||||
sk_in.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_in_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_in.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out);
|
||||
sk_out.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
ksk.encrypt_sk(
|
||||
module,
|
||||
&sk_in,
|
||||
&sk_out,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
ct_in.encrypt_sk(
|
||||
module,
|
||||
&pt_want,
|
||||
&sk_in_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let ksk_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
ct_out.keyswitch(module, &ct_in, &ksk_prepared, scratch.borrow());
|
||||
|
||||
let max_noise: f64 = log2_std_noise_gglwe_product(
|
||||
module.n() as f64,
|
||||
basek * digits,
|
||||
0.5,
|
||||
0.5,
|
||||
0f64,
|
||||
sigma * sigma,
|
||||
0f64,
|
||||
rank_in as f64,
|
||||
k_in,
|
||||
k_ksk,
|
||||
);
|
||||
|
||||
ct_out.assert_noise(module, &sk_out_prepared, &pt_want, max_noise + 0.5);
|
||||
}
|
||||
|
||||
pub fn test_glwe_keyswitch_inplace<B>(
|
||||
module: &Module<B>,
|
||||
basek: usize,
|
||||
k_ct: usize,
|
||||
k_ksk: usize,
|
||||
digits: usize,
|
||||
rank: usize,
|
||||
sigma: f64,
|
||||
) where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxSwithcDegree,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let rows: usize = k_ct.div_ceil(basek * digits);
|
||||
|
||||
let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank, rank);
|
||||
let mut ct_glwe: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank);
|
||||
let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_ct);
|
||||
|
||||
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(basek, &mut pt_want.data, 0, k_ct, &mut source_xa);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, ksk.k(), rank, rank)
|
||||
| GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, ct_glwe.k())
|
||||
| GLWECiphertext::keyswitch_inplace_scratch_space(module, n, basek, ct_glwe.k(), ksk.k(), digits, rank),
|
||||
);
|
||||
|
||||
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk_in.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_in_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_in.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk_out.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
ksk.encrypt_sk(
|
||||
module,
|
||||
&sk_in,
|
||||
&sk_out,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
ct_glwe.encrypt_sk(
|
||||
module,
|
||||
&pt_want,
|
||||
&sk_in_prepared,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let ksk_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
ct_glwe.keyswitch_inplace(module, &ksk_prepared, scratch.borrow());
|
||||
|
||||
let max_noise: f64 = log2_std_noise_gglwe_product(
|
||||
module.n() as f64,
|
||||
basek * digits,
|
||||
0.5,
|
||||
0.5,
|
||||
0f64,
|
||||
sigma * sigma,
|
||||
0f64,
|
||||
rank as f64,
|
||||
k_ct,
|
||||
k_ksk,
|
||||
);
|
||||
|
||||
ct_glwe.assert_noise(module, &sk_out_prepared, &pt_want, max_noise + 0.5);
|
||||
}
|
||||
127
poulpy-core/src/tests/generics/keyswitch/lwe_ct.rs
Normal file
127
poulpy-core/src/tests/generics/keyswitch/lwe_ct.rs
Normal file
@@ -0,0 +1,127 @@
|
||||
use poulpy_backend::hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, VecZnxAddInplace,
|
||||
VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace,
|
||||
VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAllocBytes, VecZnxDftFromVecZnx,
|
||||
VecZnxDftToVecZnxBigConsume, VecZnxFillUniform, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes,
|
||||
VecZnxSub, VecZnxSubABInplace, VecZnxSwithcDegree, VmpApply, VmpApplyAdd, VmpApplyTmpBytes, VmpPMatAlloc, VmpPrepare,
|
||||
ZnxView,
|
||||
},
|
||||
layouts::{Backend, Module, ScratchOwned},
|
||||
oep::{
|
||||
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
|
||||
TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
Infos, LWECiphertext, LWEPlaintext, LWESecret, LWESwitchingKey,
|
||||
prepared::{LWESwitchingKeyPrepared, PrepareAlloc},
|
||||
};
|
||||
|
||||
pub fn test_lwe_keyswitch<B>(module: &Module<B>)
|
||||
where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxAutomorphismInplace,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let basek: usize = 17;
|
||||
let sigma: f64 = 3.2;
|
||||
|
||||
let n_lwe_in: usize = 22;
|
||||
let n_lwe_out: usize = 30;
|
||||
let k_lwe_ct: usize = 2 * basek;
|
||||
let k_lwe_pt: usize = 8;
|
||||
|
||||
let k_ksk: usize = k_lwe_ct + basek;
|
||||
|
||||
let mut source_xs: Source = Source::new([0u8; 32]);
|
||||
let mut source_xa: Source = Source::new([0u8; 32]);
|
||||
let mut source_xe: Source = Source::new([0u8; 32]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
LWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk)
|
||||
| LWECiphertext::keyswitch_scratch_space(module, n, basek, k_lwe_ct, k_lwe_ct, k_ksk),
|
||||
);
|
||||
|
||||
let mut sk_lwe_in: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe_in);
|
||||
sk_lwe_in.fill_ternary_prob(0.5, &mut source_xs);
|
||||
|
||||
let mut sk_lwe_out: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe_out);
|
||||
sk_lwe_out.fill_ternary_prob(0.5, &mut source_xs);
|
||||
|
||||
let data: i64 = 17;
|
||||
|
||||
let mut lwe_pt_in: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_pt);
|
||||
|
||||
lwe_pt_in.encode_i64(data, k_lwe_pt);
|
||||
|
||||
let mut lwe_ct_in: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe_in, basek, k_lwe_ct);
|
||||
lwe_ct_in.encrypt_sk(
|
||||
module,
|
||||
&lwe_pt_in,
|
||||
&sk_lwe_in,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
);
|
||||
|
||||
let mut ksk: LWESwitchingKey<Vec<u8>> = LWESwitchingKey::alloc(n, basek, k_ksk, lwe_ct_in.size());
|
||||
|
||||
ksk.encrypt_sk(
|
||||
module,
|
||||
&sk_lwe_in,
|
||||
&sk_lwe_out,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut lwe_ct_out: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe_out, basek, k_lwe_ct);
|
||||
|
||||
let ksk_prepared: LWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
lwe_ct_out.keyswitch(module, &lwe_ct_in, &ksk_prepared, scratch.borrow());
|
||||
|
||||
let mut lwe_pt_out: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_ct);
|
||||
lwe_ct_out.decrypt(module, &mut lwe_pt_out, &sk_lwe_out);
|
||||
|
||||
assert_eq!(lwe_pt_in.data.at(0, 0)[0], lwe_pt_out.data.at(0, 0)[0]);
|
||||
}
|
||||
9
poulpy-core/src/tests/generics/keyswitch/mod.rs
Normal file
9
poulpy-core/src/tests/generics/keyswitch/mod.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
mod gglwe_ct;
|
||||
mod ggsw_ct;
|
||||
mod glwe_ct;
|
||||
mod lwe_ct;
|
||||
|
||||
pub use gglwe_ct::*;
|
||||
pub use ggsw_ct::*;
|
||||
pub use glwe_ct::*;
|
||||
pub use lwe_ct::*;
|
||||
12
poulpy-core/src/tests/generics/mod.rs
Normal file
12
poulpy-core/src/tests/generics/mod.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
pub mod automorphism;
|
||||
pub mod encryption;
|
||||
pub mod external_product;
|
||||
pub mod keyswitch;
|
||||
|
||||
mod conversion;
|
||||
mod packing;
|
||||
mod trace;
|
||||
|
||||
pub use conversion::*;
|
||||
pub use packing::*;
|
||||
pub use trace::*;
|
||||
200
poulpy-core/src/tests/generics/packing.rs
Normal file
200
poulpy-core/src/tests/generics/packing.rs
Normal file
@@ -0,0 +1,200 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use poulpy_backend::hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, VecZnxAddInplace,
|
||||
VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxBigAddInplace,
|
||||
VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, VecZnxBigAutomorphismInplace, VecZnxBigNormalize,
|
||||
VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallBInplace, VecZnxCopy, VecZnxDftAllocBytes, VecZnxDftFromVecZnx,
|
||||
VecZnxDftToVecZnxBigConsume, VecZnxFillUniform, VecZnxNegateInplace, VecZnxNormalize, VecZnxNormalizeInplace,
|
||||
VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxRshInplace, VecZnxSub, VecZnxSubABInplace,
|
||||
VecZnxSwithcDegree, VmpApply, VmpApplyAdd, VmpApplyTmpBytes, VmpPMatAlloc, VmpPrepare,
|
||||
},
|
||||
layouts::{Backend, Module, ScratchOwned},
|
||||
oep::{
|
||||
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
|
||||
TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
GLWEOperations, GLWEPacker,
|
||||
layouts::{
|
||||
GGLWEAutomorphismKey, GLWECiphertext, GLWEPlaintext, GLWESecret,
|
||||
prepared::{GGLWEAutomorphismKeyPrepared, GLWESecretPrepared, PrepareAlloc},
|
||||
},
|
||||
};
|
||||
|
||||
pub fn test_glwe_packing<B>(module: &Module<B>)
|
||||
where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxAutomorphism
|
||||
+ VecZnxBigAutomorphismInplace<B>
|
||||
+ VecZnxBigSubSmallBInplace<B>
|
||||
+ VecZnxNegateInplace
|
||||
+ VecZnxRshInplace
|
||||
+ VecZnxRotateInplace
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ VecZnxRotate
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxAutomorphismInplace
|
||||
+ VecZnxCopy,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>,
|
||||
{
|
||||
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]);
|
||||
|
||||
let n: usize = module.n();
|
||||
let basek: usize = 18;
|
||||
let k_ct: usize = 36;
|
||||
let pt_k: usize = 18;
|
||||
let rank: usize = 3;
|
||||
let sigma: f64 = 3.2;
|
||||
let digits: usize = 1;
|
||||
let k_ksk: usize = k_ct + basek * digits;
|
||||
|
||||
let rows: usize = k_ct.div_ceil(basek * digits);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k_ct)
|
||||
| GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank)
|
||||
| GLWEPacker::scratch_space(module, n, basek, k_ct, k_ksk, digits, rank),
|
||||
);
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_dft: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_ct);
|
||||
let mut data: Vec<i64> = vec![0i64; n];
|
||||
data.iter_mut().enumerate().for_each(|(i, x)| {
|
||||
*x = i as i64;
|
||||
});
|
||||
|
||||
pt.encode_vec_i64(&data, pt_k);
|
||||
|
||||
let gal_els: Vec<i64> = GLWEPacker::galois_elements(module);
|
||||
|
||||
let mut auto_keys: HashMap<i64, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>> = HashMap::new();
|
||||
let mut tmp: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank);
|
||||
gal_els.iter().for_each(|gal_el| {
|
||||
tmp.encrypt_sk(
|
||||
module,
|
||||
*gal_el,
|
||||
&sk,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
let atk_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = tmp.prepare_alloc(module, scratch.borrow());
|
||||
auto_keys.insert(*gal_el, atk_prepared);
|
||||
});
|
||||
|
||||
let log_batch: usize = 0;
|
||||
|
||||
let mut packer: GLWEPacker = GLWEPacker::new(n, log_batch, basek, k_ct, rank);
|
||||
|
||||
let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank);
|
||||
|
||||
ct.encrypt_sk(
|
||||
module,
|
||||
&pt,
|
||||
&sk_dft,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let log_n: usize = module.log_n();
|
||||
|
||||
(0..n >> log_batch).for_each(|i| {
|
||||
ct.encrypt_sk(
|
||||
module,
|
||||
&pt,
|
||||
&sk_dft,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
pt.rotate_inplace(module, -(1 << log_batch)); // X^-batch * pt
|
||||
|
||||
if reverse_bits_msb(i, log_n as u32).is_multiple_of(5) {
|
||||
packer.add(module, Some(&ct), &auto_keys, scratch.borrow());
|
||||
} else {
|
||||
packer.add(
|
||||
module,
|
||||
None::<&GLWECiphertext<Vec<u8>>>,
|
||||
&auto_keys,
|
||||
scratch.borrow(),
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
let mut res = GLWECiphertext::alloc(n, basek, k_ct, rank);
|
||||
packer.flush(module, &mut res);
|
||||
|
||||
let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_ct);
|
||||
let mut data: Vec<i64> = vec![0i64; n];
|
||||
data.iter_mut().enumerate().for_each(|(i, x)| {
|
||||
if i.is_multiple_of(5) {
|
||||
*x = reverse_bits_msb(i, log_n as u32) as i64;
|
||||
}
|
||||
});
|
||||
|
||||
pt_want.encode_vec_i64(&data, pt_k);
|
||||
|
||||
res.decrypt(module, &mut pt, &sk_dft, scratch.borrow());
|
||||
|
||||
pt.sub_inplace_ab(module, &pt_want);
|
||||
|
||||
let noise_have: f64 = pt.std().log2();
|
||||
// println!("noise_have: {}", noise_have);
|
||||
assert!(
|
||||
noise_have < -((k_ct - basek) as f64),
|
||||
"noise: {}",
|
||||
noise_have
|
||||
);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn reverse_bits_msb(x: usize, n: u32) -> usize {
|
||||
x.reverse_bits() >> (usize::BITS - n)
|
||||
}
|
||||
168
poulpy-core/src/tests/generics/trace.rs
Normal file
168
poulpy-core/src/tests/generics/trace.rs
Normal file
@@ -0,0 +1,168 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use poulpy_backend::hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, VecZnxAddInplace,
|
||||
VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxBigAddInplace, VecZnxBigAddSmallInplace,
|
||||
VecZnxBigAllocBytes, VecZnxBigAutomorphismInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes,
|
||||
VecZnxBigSubSmallBInplace, VecZnxCopy, VecZnxDftAllocBytes, VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigConsume,
|
||||
VecZnxFillUniform, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotateInplace,
|
||||
VecZnxRshInplace, VecZnxSub, VecZnxSubABInplace, VecZnxSwithcDegree, VmpApply, VmpApplyAdd, VmpApplyTmpBytes,
|
||||
VmpPMatAlloc, VmpPrepare, ZnxView, ZnxViewMut,
|
||||
},
|
||||
layouts::{Backend, Module, ScratchOwned},
|
||||
oep::{
|
||||
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
|
||||
TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
layouts::{
|
||||
GGLWEAutomorphismKey, GLWECiphertext, GLWEPlaintext, GLWESecret, Infos,
|
||||
prepared::{GGLWEAutomorphismKeyPrepared, GLWESecretPrepared, PrepareAlloc},
|
||||
},
|
||||
noise::var_noise_gglwe_product,
|
||||
};
|
||||
|
||||
pub fn test_glwe_trace_inplace<B>(module: &Module<B>, basek: usize, k: usize, sigma: f64, rank: usize)
|
||||
where
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VecZnxAutomorphism
|
||||
+ VecZnxBigAutomorphismInplace<B>
|
||||
+ VecZnxBigSubSmallBInplace<B>
|
||||
+ VecZnxRshInplace
|
||||
+ VecZnxRotateInplace
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftFromVecZnx<B>
|
||||
+ SvpApplyInplace<B>
|
||||
+ VecZnxDftToVecZnxBigConsume<B>
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAllocBytes
|
||||
+ SvpPPolAlloc<B>
|
||||
+ VecZnxBigAllocBytes
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VmpApplyTmpBytes
|
||||
+ VmpApply<B>
|
||||
+ VmpApplyAdd<B>
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxCopy,
|
||||
B: Backend
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeSvpPPolImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeScalarZnxImpl<B>
|
||||
+ TakeVecZnxImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let k_autokey: usize = k + basek;
|
||||
|
||||
let digits: usize = 1;
|
||||
let rows: usize = k.div_ceil(basek * digits);
|
||||
|
||||
let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k, rank);
|
||||
let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k);
|
||||
let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k);
|
||||
|
||||
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]);
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
|
||||
GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, ct.k())
|
||||
| GLWECiphertext::decrypt_scratch_space(module, n, basek, ct.k())
|
||||
| GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_autokey, rank)
|
||||
| GLWECiphertext::trace_inplace_scratch_space(module, n, basek, ct.k(), k_autokey, digits, rank),
|
||||
);
|
||||
|
||||
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
|
||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||
let sk_dft: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
let mut data_want: Vec<i64> = vec![0i64; n];
|
||||
|
||||
data_want
|
||||
.iter_mut()
|
||||
.for_each(|x| *x = source_xa.next_i64() & 0xFF);
|
||||
|
||||
module.vec_znx_fill_uniform(basek, &mut pt_have.data, 0, k, &mut source_xa);
|
||||
|
||||
ct.encrypt_sk(
|
||||
module,
|
||||
&pt_have,
|
||||
&sk_dft,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut auto_keys: HashMap<i64, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>> = HashMap::new();
|
||||
let gal_els: Vec<i64> = GLWECiphertext::trace_galois_elements(module);
|
||||
let mut tmp: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_autokey, rows, digits, rank);
|
||||
gal_els.iter().for_each(|gal_el| {
|
||||
tmp.encrypt_sk(
|
||||
module,
|
||||
*gal_el,
|
||||
&sk,
|
||||
&mut source_xa,
|
||||
&mut source_xe,
|
||||
sigma,
|
||||
scratch.borrow(),
|
||||
);
|
||||
let atk_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = tmp.prepare_alloc(module, scratch.borrow());
|
||||
auto_keys.insert(*gal_el, atk_prepared);
|
||||
});
|
||||
|
||||
ct.trace_inplace(module, 0, 5, &auto_keys, scratch.borrow());
|
||||
ct.trace_inplace(module, 5, module.log_n(), &auto_keys, scratch.borrow());
|
||||
|
||||
(0..pt_want.size()).for_each(|i| pt_want.data.at_mut(0, i)[0] = pt_have.data.at(0, i)[0]);
|
||||
|
||||
ct.decrypt(module, &mut pt_have, &sk_dft, scratch.borrow());
|
||||
|
||||
module.vec_znx_sub_ab_inplace(&mut pt_want.data, 0, &pt_have.data, 0);
|
||||
module.vec_znx_normalize_inplace(basek, &mut pt_want.data, 0, scratch.borrow());
|
||||
|
||||
let noise_have: f64 = pt_want.std().log2();
|
||||
|
||||
let mut noise_want: f64 = var_noise_gglwe_product(
|
||||
n as f64,
|
||||
basek,
|
||||
0.5,
|
||||
0.5,
|
||||
1.0 / 12.0,
|
||||
sigma * sigma,
|
||||
0.0,
|
||||
rank as f64,
|
||||
k,
|
||||
k_autokey,
|
||||
);
|
||||
noise_want += sigma * sigma * (-2.0 * (k) as f64).exp2();
|
||||
noise_want += n as f64 * 1.0 / 12.0 * 0.5 * rank as f64 * (-2.0 * (k) as f64).exp2();
|
||||
noise_want = noise_want.sqrt().log2();
|
||||
|
||||
assert!(
|
||||
(noise_have - noise_want).abs() < 1.0,
|
||||
"{} > {}",
|
||||
noise_have,
|
||||
noise_want
|
||||
);
|
||||
}
|
||||
264
poulpy-core/src/tests/implementation/cpu_spqlios/fft64/gglwe.rs
Normal file
264
poulpy-core/src/tests/implementation/cpu_spqlios/fft64/gglwe.rs
Normal file
@@ -0,0 +1,264 @@
|
||||
use poulpy_backend::{
|
||||
hal::{api::ModuleNew, layouts::Module},
|
||||
implementation::cpu_spqlios::FFT64,
|
||||
};
|
||||
|
||||
use crate::tests::generics::{
|
||||
automorphism::{test_gglwe_automorphism_key_automorphism, test_gglwe_automorphism_key_automorphism_inplace},
|
||||
encryption::{
|
||||
test_gglwe_automorphisk_key_compressed_encrypt_sk, test_gglwe_automorphisk_key_encrypt_sk,
|
||||
test_gglwe_switching_key_compressed_encrypt_sk, test_gglwe_switching_key_encrypt_sk,
|
||||
test_glwe_tensor_key_compressed_encrypt_sk, test_glwe_tensor_key_encrypt_sk,
|
||||
},
|
||||
external_product::{test_gglwe_switching_key_external_product, test_gglwe_switching_key_external_product_inplace},
|
||||
keyswitch::{test_gglwe_switching_key_keyswitch, test_gglwe_switching_key_keyswitch_inplace},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn gglwe_switching_key_encrypt_sk() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_ksk: usize = 54;
|
||||
let digits: usize = k_ksk / basek;
|
||||
(1..4).for_each(|rank_in| {
|
||||
(1..4).for_each(|rank_out| {
|
||||
(1..digits + 1).for_each(|di| {
|
||||
println!(
|
||||
"test_gglwe_switching_key_encrypt_sk digits: {} ranks: ({} {})",
|
||||
di, rank_in, rank_out
|
||||
);
|
||||
test_gglwe_switching_key_encrypt_sk(&module, basek, k_ksk, di, rank_in, rank_out, 3.2);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gglwe_switching_key_compressed_encrypt_sk() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_ksk: usize = 54;
|
||||
let digits: usize = k_ksk / basek;
|
||||
(1..4).for_each(|rank_in| {
|
||||
(1..4).for_each(|rank_out| {
|
||||
(1..digits + 1).for_each(|di| {
|
||||
println!(
|
||||
"test_gglwe_switching_key_compressed_encrypt_sk digits: {} ranks: ({} {})",
|
||||
di, rank_in, rank_out
|
||||
);
|
||||
test_gglwe_switching_key_compressed_encrypt_sk(&module, basek, k_ksk, di, rank_in, rank_out, 3.2);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gglwe_switching_key_keyswitch() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_in: usize = 60;
|
||||
let digits: usize = k_in.div_ceil(basek);
|
||||
(1..4).for_each(|rank_in_s0s1| {
|
||||
(1..4).for_each(|rank_out_s0s1| {
|
||||
(1..4).for_each(|rank_out_s1s2| {
|
||||
(1..digits + 1).for_each(|di| {
|
||||
let k_ksk: usize = k_in + basek * di;
|
||||
println!(
|
||||
"test_gglwe_switching_key_keyswitch digits: {} ranks: ({},{},{})",
|
||||
di, rank_in_s0s1, rank_out_s0s1, rank_out_s1s2
|
||||
);
|
||||
let k_out: usize = k_ksk; // Better capture noise.
|
||||
test_gglwe_switching_key_keyswitch(
|
||||
&module,
|
||||
basek,
|
||||
k_out,
|
||||
k_in,
|
||||
k_ksk,
|
||||
di,
|
||||
rank_in_s0s1,
|
||||
rank_out_s0s1,
|
||||
rank_out_s1s2,
|
||||
3.2,
|
||||
);
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gglwe_switching_key_keyswitch_inplace() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_ct: usize = 60;
|
||||
let digits: usize = k_ct.div_ceil(basek);
|
||||
(1..4).for_each(|rank_in_s0s1| {
|
||||
(1..4).for_each(|rank_out_s0s1| {
|
||||
(1..digits + 1).for_each(|di| {
|
||||
let k_ksk: usize = k_ct + basek * di;
|
||||
println!(
|
||||
"test_gglwe_switching_key_keyswitch_inplace digits: {} ranks: ({},{})",
|
||||
di, rank_in_s0s1, rank_out_s0s1
|
||||
);
|
||||
test_gglwe_switching_key_keyswitch_inplace(
|
||||
&module,
|
||||
basek,
|
||||
k_ct,
|
||||
k_ksk,
|
||||
di,
|
||||
rank_in_s0s1,
|
||||
rank_out_s0s1,
|
||||
3.2,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gglwe_switching_key_external_product() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_in: usize = 60;
|
||||
let digits: usize = k_in.div_ceil(basek);
|
||||
(1..4).for_each(|rank_in| {
|
||||
(1..4).for_each(|rank_out| {
|
||||
(1..digits + 1).for_each(|di| {
|
||||
let k_ggsw: usize = k_in + basek * di;
|
||||
println!(
|
||||
"test_gglwe_switching_key_external_product digits: {} ranks: ({} {})",
|
||||
di, rank_in, rank_out
|
||||
);
|
||||
let k_out: usize = k_in; // Better capture noise.
|
||||
test_gglwe_switching_key_external_product(
|
||||
&module, basek, k_out, k_in, k_ggsw, di, rank_in, rank_out, 3.2,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gglwe_switching_key_external_product_inplace() {
|
||||
let log_n: usize = 5;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_ct: usize = 60;
|
||||
let digits: usize = k_ct.div_ceil(basek);
|
||||
(1..4).for_each(|rank_in| {
|
||||
(1..4).for_each(|rank_out| {
|
||||
(1..digits).for_each(|di| {
|
||||
let k_ggsw: usize = k_ct + basek * di;
|
||||
println!(
|
||||
"test_gglwe_switching_key_external_product_inplace digits: {} ranks: ({} {})",
|
||||
di, rank_in, rank_out
|
||||
);
|
||||
test_gglwe_switching_key_external_product_inplace(&module, basek, k_ct, k_ggsw, di, rank_in, rank_out, 3.2);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gglwe_automorphisk_key_encrypt_sk() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k: usize = 60;
|
||||
let digits: usize = k.div_ceil(basek) - 1;
|
||||
let sigma: f64 = 3.2;
|
||||
(1..4).for_each(|rank| {
|
||||
(2..digits + 1).for_each(|di| {
|
||||
println!(
|
||||
"test_gglwe_automorphisk_key_encrypt_sk digits: {} rank: {}",
|
||||
di, rank
|
||||
);
|
||||
test_gglwe_automorphisk_key_encrypt_sk(&module, basek, k, di, rank, sigma);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gglwe_automorphisk_key_compressed_encrypt_sk() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k: usize = 60;
|
||||
let digits: usize = k.div_ceil(basek) - 1;
|
||||
let sigma: f64 = 3.2;
|
||||
(1..4).for_each(|rank| {
|
||||
(2..digits + 1).for_each(|di| {
|
||||
println!(
|
||||
"test_gglwe_automorphisk_key_compressed_encrypt_sk digits: {} rank: {}",
|
||||
di, rank
|
||||
);
|
||||
test_gglwe_automorphisk_key_compressed_encrypt_sk(&module, basek, k, di, rank, sigma);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gglwe_automorphism_key_automorphism() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_in: usize = 60;
|
||||
let k_out: usize = 40;
|
||||
let digits: usize = k_in.div_ceil(basek);
|
||||
let sigma: f64 = 3.2;
|
||||
(1..4).for_each(|rank| {
|
||||
(2..digits + 1).for_each(|di| {
|
||||
println!(
|
||||
"test_gglwe_automorphism_key_automorphism: {} rank: {}",
|
||||
di, rank
|
||||
);
|
||||
let k_apply: usize = (digits + di) * basek;
|
||||
test_gglwe_automorphism_key_automorphism(&module, -1, 5, basek, di, k_in, k_out, k_apply, sigma, rank);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gglwe_automorphism_key_automorphism_inplace() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_in: usize = 60;
|
||||
let digits: usize = k_in.div_ceil(basek);
|
||||
let sigma: f64 = 3.2;
|
||||
(1..4).for_each(|rank| {
|
||||
(2..digits + 1).for_each(|di| {
|
||||
println!(
|
||||
"test_gglwe_automorphism_key_automorphism_inplace: {} rank: {}",
|
||||
di, rank
|
||||
);
|
||||
let k_apply: usize = (digits + di) * basek;
|
||||
test_gglwe_automorphism_key_automorphism_inplace(&module, -1, 5, basek, di, k_in, k_apply, sigma, rank);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn glwe_tensor_key_encrypt_sk() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
(1..4).for_each(|rank| {
|
||||
println!("test_glwe_tensor_key_encrypt_sk rank: {}", rank);
|
||||
test_glwe_tensor_key_encrypt_sk(&module, 16, 54, 3.2, rank);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn glwe_tensor_key_compressed_encrypt_sk() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
(1..4).for_each(|rank| {
|
||||
println!("test_glwe_tensor_key_compressed_encrypt_sk rank: {}", rank);
|
||||
test_glwe_tensor_key_compressed_encrypt_sk(&module, 16, 54, 3.2, rank);
|
||||
});
|
||||
}
|
||||
150
poulpy-core/src/tests/implementation/cpu_spqlios/fft64/ggws.rs
Normal file
150
poulpy-core/src/tests/implementation/cpu_spqlios/fft64/ggws.rs
Normal file
@@ -0,0 +1,150 @@
|
||||
use poulpy_backend::{
|
||||
hal::{api::ModuleNew, layouts::Module},
|
||||
implementation::cpu_spqlios::FFT64,
|
||||
};
|
||||
|
||||
use crate::tests::generics::{
|
||||
automorphism::{test_ggsw_automorphism, test_ggsw_automorphism_inplace},
|
||||
encryption::{test_ggsw_compressed_encrypt_sk, test_ggsw_encrypt_sk},
|
||||
external_product::{test_ggsw_external_product, test_ggsw_external_product_inplace},
|
||||
keyswitch::{test_ggsw_keyswitch, test_ggsw_keyswitch_inplace},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn ggsw_encrypt_sk() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_ct: usize = 54;
|
||||
let digits: usize = k_ct / basek;
|
||||
(1..4).for_each(|rank| {
|
||||
(1..digits + 1).for_each(|di| {
|
||||
println!("test_ggsw_encrypt_sk digits: {} rank: {}", di, rank);
|
||||
test_ggsw_encrypt_sk(&module, basek, k_ct, di, rank, 3.2);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ggsw_compressed_encrypt_sk() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_ct: usize = 54;
|
||||
let digits: usize = k_ct / basek;
|
||||
(1..4).for_each(|rank| {
|
||||
(1..digits + 1).for_each(|di| {
|
||||
println!(
|
||||
"test_ggsw_compressed_encrypt_sk digits: {} rank: {}",
|
||||
di, rank
|
||||
);
|
||||
test_ggsw_compressed_encrypt_sk(&module, basek, k_ct, di, rank, 3.2);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ggsw_keyswitch() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_in: usize = 54;
|
||||
let digits: usize = k_in.div_ceil(basek);
|
||||
(1..4).for_each(|rank| {
|
||||
(1..digits + 1).for_each(|di| {
|
||||
let k_ksk: usize = k_in + basek * di;
|
||||
let k_tsk: usize = k_ksk;
|
||||
println!("test_ggsw_keyswitch digits: {} rank: {}", di, rank);
|
||||
let k_out: usize = k_ksk; // Better capture noise.
|
||||
test_ggsw_keyswitch(&module, basek, k_out, k_in, k_ksk, k_tsk, di, rank, 3.2);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ggsw_keyswitch_inplace() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_ct: usize = 54;
|
||||
let digits: usize = k_ct.div_ceil(basek);
|
||||
(1..4).for_each(|rank| {
|
||||
(1..digits + 1).for_each(|di| {
|
||||
let k_ksk: usize = k_ct + basek * di;
|
||||
let k_tsk: usize = k_ksk;
|
||||
println!("test_ggsw_keyswitch_inplace digits: {} rank: {}", di, rank);
|
||||
test_ggsw_keyswitch_inplace(&module, basek, k_ct, k_ksk, k_tsk, di, rank, 3.2);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ggsw_automorphism() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_in: usize = 54;
|
||||
let digits: usize = k_in.div_ceil(basek);
|
||||
(1..4).for_each(|rank| {
|
||||
(1..digits + 1).for_each(|di| {
|
||||
let k_ksk: usize = k_in + basek * di;
|
||||
let k_tsk: usize = k_ksk;
|
||||
println!("test_ggsw_automorphism rank: {}", rank);
|
||||
let k_out: usize = k_ksk; // Better capture noise.
|
||||
test_ggsw_automorphism(-5, &module, basek, k_out, k_in, k_ksk, k_tsk, di, rank, 3.2);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ggsw_automorphism_inplace() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_ct: usize = 54;
|
||||
let digits: usize = k_ct.div_ceil(basek);
|
||||
(1..4).for_each(|rank| {
|
||||
(1..digits + 1).for_each(|di| {
|
||||
let k_ksk: usize = k_ct + basek * di;
|
||||
let k_tsk: usize = k_ksk;
|
||||
println!("test_ggsw_automorphism_inplace rank: {}", rank);
|
||||
test_ggsw_automorphism_inplace(-5, &module, basek, k_ct, k_ksk, k_tsk, di, rank, 3.2);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ggsw_external_product() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_in: usize = 60;
|
||||
let digits: usize = k_in.div_ceil(basek);
|
||||
(1..4).for_each(|rank| {
|
||||
(1..digits + 1).for_each(|di| {
|
||||
let k_ggsw: usize = k_in + basek * di;
|
||||
println!("test external_product digits: {} ranks: {}", di, rank);
|
||||
let k_out: usize = k_in; // Better capture noise.
|
||||
test_ggsw_external_product(&module, basek, k_in, k_out, k_ggsw, di, rank, 3.2);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ggsw_external_product_inplace() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_ct: usize = 60;
|
||||
let digits: usize = k_ct.div_ceil(basek);
|
||||
(1..4).for_each(|rank| {
|
||||
(1..digits).for_each(|di| {
|
||||
let k_ggsw: usize = k_ct + basek * di;
|
||||
println!(
|
||||
"test_ggsw_external_product_inplace digits: {} rank: {}",
|
||||
di, rank
|
||||
);
|
||||
test_ggsw_external_product_inplace(&module, basek, k_ct, k_ggsw, di, rank, 3.2);
|
||||
});
|
||||
});
|
||||
}
|
||||
181
poulpy-core/src/tests/implementation/cpu_spqlios/fft64/glwe.rs
Normal file
181
poulpy-core/src/tests/implementation/cpu_spqlios/fft64/glwe.rs
Normal file
@@ -0,0 +1,181 @@
|
||||
use poulpy_backend::{
|
||||
hal::{api::ModuleNew, layouts::Module},
|
||||
implementation::cpu_spqlios::FFT64,
|
||||
};
|
||||
|
||||
use crate::tests::generics::{
|
||||
automorphism::{test_glwe_automorphism, test_glwe_automorphism_inplace},
|
||||
encryption::{test_glwe_compressed_encrypt_sk, test_glwe_encrypt_pk, test_glwe_encrypt_sk, test_glwe_encrypt_zero_sk},
|
||||
external_product::{test_glwe_external_product, test_glwe_external_product_inplace},
|
||||
keyswitch::{test_glwe_keyswitch, test_glwe_keyswitch_inplace},
|
||||
test_glwe_packing, test_glwe_trace_inplace,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn glwe_encrypt_sk() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
(1..4).for_each(|rank| {
|
||||
println!("test_glwe_encrypt_sk rank: {}", rank);
|
||||
test_glwe_encrypt_sk(&module, 8, 54, 30, 3.2, rank);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn glwe_compressed_encrypt_sk() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
(1..4).for_each(|rank| {
|
||||
println!("test_glwe_compressed_encrypt_sk rank: {}", rank);
|
||||
test_glwe_compressed_encrypt_sk(&module, 8, 54, 30, 3.2, rank);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn glwe_encrypt_zero_sk() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
(1..4).for_each(|rank| {
|
||||
println!("test_glwe_encrypt_zero_sk rank: {}", rank);
|
||||
test_glwe_encrypt_zero_sk(&module, 8, 64, 3.2, rank);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn glwe_encrypt_pk() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
(1..4).for_each(|rank| {
|
||||
println!("test_glwe_encrypt_pk rank: {}", rank);
|
||||
test_glwe_encrypt_pk(&module, 8, 64, 64, 3.2, rank)
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn glwe_keyswitch() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_in: usize = 45;
|
||||
let digits: usize = k_in.div_ceil(basek);
|
||||
(1..4).for_each(|rank_in| {
|
||||
(1..4).for_each(|rank_out| {
|
||||
(1..digits + 1).for_each(|di| {
|
||||
let k_ksk: usize = k_in + basek * di;
|
||||
let k_out: usize = k_ksk; // better capture noise
|
||||
println!(
|
||||
"test_glwe_keyswitch digits: {} rank_in: {} rank_out: {}",
|
||||
di, rank_in, rank_out
|
||||
);
|
||||
test_glwe_keyswitch(
|
||||
&module, basek, k_out, k_in, k_ksk, di, rank_in, rank_out, 3.2,
|
||||
);
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn glwe_keyswitch_inplace() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_ct: usize = 45;
|
||||
let digits: usize = k_ct.div_ceil(basek);
|
||||
(1..4).for_each(|rank| {
|
||||
(1..digits + 1).for_each(|di| {
|
||||
let k_ksk: usize = k_ct + basek * di;
|
||||
println!("test_glwe_keyswitch_inplace digits: {} rank: {}", di, rank);
|
||||
test_glwe_keyswitch_inplace(&module, basek, k_ct, k_ksk, di, rank, 3.2);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn glwe_automorphism() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_in: usize = 60;
|
||||
let digits: usize = k_in.div_ceil(basek);
|
||||
(1..4).for_each(|rank| {
|
||||
(1..digits + 1).for_each(|di| {
|
||||
let k_ksk: usize = k_in + basek * di;
|
||||
let k_out: usize = k_ksk; // Better capture noise.
|
||||
println!("test_glwe_automorphism digits: {} rank: {}", di, rank);
|
||||
test_glwe_automorphism(&module, basek, -5, k_out, k_in, k_ksk, di, rank, 3.2);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn glwe_automorphism_inplace() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_ct: usize = 60;
|
||||
let digits: usize = k_ct.div_ceil(basek);
|
||||
(1..4).for_each(|rank| {
|
||||
(1..digits + 1).for_each(|di| {
|
||||
let k_ksk: usize = k_ct + basek * di;
|
||||
println!(
|
||||
"test_glwe_automorphism_inplace digits: {} rank: {}",
|
||||
di, rank
|
||||
);
|
||||
test_glwe_automorphism_inplace(&module, basek, -5, k_ct, k_ksk, di, rank, 3.2);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn glwe_external_product() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_in: usize = 45;
|
||||
let digits: usize = k_in.div_ceil(basek);
|
||||
(1..4).for_each(|rank| {
|
||||
(1..digits + 1).for_each(|di| {
|
||||
let k_ggsw: usize = k_in + basek * di;
|
||||
let k_out: usize = k_ggsw; // Better capture noise
|
||||
println!("test_glwe_external_product digits: {} rank: {}", di, rank);
|
||||
test_glwe_external_product(&module, basek, k_out, k_in, k_ggsw, di, rank, 3.2);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn glwe_external_product_inplace() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
let basek: usize = 12;
|
||||
let k_ct: usize = 60;
|
||||
let digits: usize = k_ct.div_ceil(basek);
|
||||
(1..4).for_each(|rank| {
|
||||
(1..digits + 1).for_each(|di| {
|
||||
let k_ggsw: usize = k_ct + basek * di;
|
||||
println!(
|
||||
"test_glwe_external_product_inplace digits: {} rank: {}",
|
||||
di, rank
|
||||
);
|
||||
test_glwe_external_product_inplace(&module, basek, k_ct, k_ggsw, di, rank, 3.2);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn glwe_trace_inplace() {
|
||||
let log_n: usize = 8;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
(1..4).for_each(|rank| {
|
||||
println!("test_glwe_trace_inplace rank: {}", rank);
|
||||
test_glwe_trace_inplace(&module, 8, 54, 3.2, rank);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn glwe_packing() {
|
||||
let log_n: usize = 5;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
test_glwe_packing(&module);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
use poulpy_backend::{
|
||||
hal::{api::ModuleNew, layouts::Module},
|
||||
implementation::cpu_spqlios::FFT64,
|
||||
};
|
||||
|
||||
use crate::tests::generics::{keyswitch::test_lwe_keyswitch, test_glwe_to_lwe, test_lwe_to_glwe};
|
||||
|
||||
#[test]
|
||||
fn lwe_to_glwe() {
|
||||
let log_n: usize = 5;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
test_lwe_to_glwe(&module)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn glwe_to_lwe() {
|
||||
let log_n: usize = 5;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
test_glwe_to_lwe(&module)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lwe_keyswitch() {
|
||||
let log_n: usize = 5;
|
||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||
test_lwe_keyswitch(&module)
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
mod gglwe;
|
||||
mod ggws;
|
||||
mod glwe;
|
||||
mod lwe;
|
||||
1
poulpy-core/src/tests/implementation/cpu_spqlios/mod.rs
Normal file
1
poulpy-core/src/tests/implementation/cpu_spqlios/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
mod fft64;
|
||||
1
poulpy-core/src/tests/implementation/mod.rs
Normal file
1
poulpy-core/src/tests/implementation/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
mod cpu_spqlios;
|
||||
7
poulpy-core/src/tests/mod.rs
Normal file
7
poulpy-core/src/tests/mod.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
pub mod generics;
|
||||
|
||||
#[cfg(test)]
|
||||
mod implementation;
|
||||
|
||||
#[cfg(test)]
|
||||
mod serialization;
|
||||
139
poulpy-core/src/tests/serialization.rs
Normal file
139
poulpy-core/src/tests/serialization.rs
Normal file
@@ -0,0 +1,139 @@
|
||||
use poulpy_backend::hal::tests::serialization::test_reader_writer_interface;
|
||||
|
||||
use crate::layouts::{
|
||||
GGLWEAutomorphismKey, GGLWECiphertext, GGLWESwitchingKey, GGLWETensorKey, GGSWCiphertext, GLWECiphertext,
|
||||
GLWEToLWESwitchingKey, LWECiphertext, LWESwitchingKey, LWEToGLWESwitchingKey,
|
||||
compressed::{
|
||||
GGLWEAutomorphismKeyCompressed, GGLWECiphertextCompressed, GGLWESwitchingKeyCompressed, GGLWETensorKeyCompressed,
|
||||
GGSWCiphertextCompressed, GLWECiphertextCompressed, GLWEToLWESwitchingKeyCompressed, LWECiphertextCompressed,
|
||||
LWESwitchingKeyCompressed, LWEToGLWESwitchingKeyCompressed,
|
||||
},
|
||||
};
|
||||
|
||||
const N_GLWE: usize = 64;
|
||||
const N_LWE: usize = 32;
|
||||
const BASEK: usize = 12;
|
||||
const K: usize = 33;
|
||||
const ROWS: usize = 2;
|
||||
const RANK: usize = 2;
|
||||
const DIGITS: usize = 1;
|
||||
|
||||
#[test]
|
||||
fn glwe_serialization() {
|
||||
let original: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(N_GLWE, BASEK, K, RANK);
|
||||
poulpy_backend::hal::tests::serialization::test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn glwe_compressed_serialization() {
|
||||
let original: GLWECiphertextCompressed<Vec<u8>> = GLWECiphertextCompressed::alloc(N_GLWE, BASEK, K, RANK);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lwe_serialization() {
|
||||
let original: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(N_LWE, BASEK, K);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lwe_compressed_serialization() {
|
||||
let original: LWECiphertextCompressed<Vec<u8>> = LWECiphertextCompressed::alloc(BASEK, K);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gglwe_serialization() {
|
||||
let original: GGLWECiphertext<Vec<u8>> = GGLWECiphertext::alloc(1024, 12, 54, 3, 1, 2, 2);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gglwe_compressed_serialization() {
|
||||
let original: GGLWECiphertextCompressed<Vec<u8>> = GGLWECiphertextCompressed::alloc(1024, 12, 54, 3, 1, 2, 2);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_glwe_switching_key_serialization() {
|
||||
let original: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(1024, 12, 54, 3, 1, 2, 2);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_glwe_switching_key_compressed_serialization() {
|
||||
let original: GGLWESwitchingKeyCompressed<Vec<u8>> = GGLWESwitchingKeyCompressed::alloc(1024, 12, 54, 3, 1, 2, 2);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_automorphism_key_serialization() {
|
||||
let original: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(1024, 12, 54, 3, 1, 2);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_automorphism_key_compressed_serialization() {
|
||||
let original: GGLWEAutomorphismKeyCompressed<Vec<u8>> = GGLWEAutomorphismKeyCompressed::alloc(1024, 12, 54, 3, 1, 2);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tensor_key_serialization() {
|
||||
let original: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(1024, 12, 54, 3, 1, 2);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tensor_key_compressed_serialization() {
|
||||
let original: GGLWETensorKeyCompressed<Vec<u8>> = GGLWETensorKeyCompressed::alloc(1024, 12, 54, 3, 1, 2);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn glwe_to_lwe_switching_key_serialization() {
|
||||
let original: GLWEToLWESwitchingKey<Vec<u8>> = GLWEToLWESwitchingKey::alloc(N_GLWE, BASEK, K, ROWS, RANK);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn glwe_to_lwe_switching_key_compressed_serialization() {
|
||||
let original: GLWEToLWESwitchingKeyCompressed<Vec<u8>> = GLWEToLWESwitchingKeyCompressed::alloc(N_GLWE, BASEK, K, ROWS, RANK);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lwe_to_glwe_switching_key_serialization() {
|
||||
let original: LWEToGLWESwitchingKey<Vec<u8>> = LWEToGLWESwitchingKey::alloc(N_GLWE, BASEK, K, ROWS, RANK);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lwe_to_glwe_switching_key_compressed_serialization() {
|
||||
let original: LWEToGLWESwitchingKeyCompressed<Vec<u8>> = LWEToGLWESwitchingKeyCompressed::alloc(N_GLWE, BASEK, K, ROWS, RANK);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lwe_switching_key_serialization() {
|
||||
let original: LWESwitchingKey<Vec<u8>> = LWESwitchingKey::alloc(N_GLWE, BASEK, K, ROWS);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lwe_switching_key_compressed_serialization() {
|
||||
let original: LWESwitchingKeyCompressed<Vec<u8>> = LWESwitchingKeyCompressed::alloc(N_GLWE, BASEK, K, ROWS);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ggsw_serialization() {
|
||||
let original: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(N_GLWE, BASEK, K, ROWS, DIGITS, RANK);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ggsw_compressed_serialization() {
|
||||
let original: GGSWCiphertextCompressed<Vec<u8>> = GGSWCiphertextCompressed::alloc(N_GLWE, BASEK, K, ROWS, DIGITS, RANK);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
Reference in New Issue
Block a user