Add cross-basek normalization (#90)

* added cross_basek_normalization

* updated method signatures to take layouts

* fixed cross-base normalization

fix #91
fix #93
This commit is contained in:
Jean-Philippe Bossuat
2025-09-30 14:40:10 +02:00
committed by GitHub
parent 4da790ea6a
commit 37e13b965c
216 changed files with 12481 additions and 7745 deletions

View File

@@ -4,7 +4,7 @@ use poulpy_hal::{
VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxBigAddInplace,
VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAllocBytes,
VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace,
VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubABInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd,
VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd,
VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, ZnAddNormal, ZnFillUniform, ZnNormalizeInplace,
},
layouts::{Backend, Module, ScratchOwned, ZnxView},
@@ -16,8 +16,9 @@ use poulpy_hal::{
};
use crate::layouts::{
GLWECiphertext, GLWEPlaintext, GLWESecret, GLWEToLWESwitchingKey, Infos, LWECiphertext, LWEPlaintext, LWESecret,
LWEToGLWESwitchingKey,
Base2K, Degree, GLWECiphertext, GLWECiphertextLayout, GLWEPlaintext, GLWESecret, GLWEToLWESwitchingKey,
GLWEToLWESwitchingKeyLayout, LWECiphertext, LWECiphertextLayout, LWEPlaintext, LWESecret, LWEToGLWESwitchingKey,
LWEToGLWESwitchingKeyLayout, Rank, Rows, TorusPrecision,
prepared::{GLWESecretPrepared, GLWEToLWESwitchingKeyPrepared, LWEToGLWESwitchingKeyPrepared, PrepareAlloc},
};
@@ -29,7 +30,7 @@ where
+ SvpApplyDftToDftInplace<B>
+ VecZnxIdftApplyConsume<B>
+ VecZnxFillUniform
+ VecZnxSubABInplace
+ VecZnxSubInplace
+ VecZnxAddInplace
+ VecZnxNormalizeInplace<B>
+ VecZnxAddNormal
@@ -64,30 +65,44 @@ where
+ TakeScalarZnxImpl<B>
+ TakeVecZnxImpl<B>,
{
let n: usize = module.n();
let basek: usize = 17;
let n_glwe: Degree = Degree(module.n() as u32);
let n_lwe: Degree = Degree(22);
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 rank: Rank = Rank(2);
let k_lwe_pt: TorusPrecision = TorusPrecision(8);
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 lwe_to_glwe_infos: LWEToGLWESwitchingKeyLayout = LWEToGLWESwitchingKeyLayout {
n: n_glwe,
base2k: Base2K(17),
k: TorusPrecision(51),
rows: Rows(2),
rank_out: rank,
};
let glwe_infos: GLWECiphertextLayout = GLWECiphertextLayout {
n: n_glwe,
base2k: Base2K(17),
k: TorusPrecision(34),
rank,
};
let lwe_infos: LWECiphertextLayout = LWECiphertextLayout {
n: n_lwe,
base2k: Base2K(17),
k: TorusPrecision(34),
};
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
LWEToGLWESwitchingKey::encrypt_sk_scratch_space(module, basek, k_ksk, rank)
| GLWECiphertext::from_lwe_scratch_space(module, basek, k_lwe_ct, k_glwe_ct, k_ksk, rank)
| GLWECiphertext::decrypt_scratch_space(module, basek, k_glwe_ct),
LWEToGLWESwitchingKey::encrypt_sk_scratch_space(module, &lwe_to_glwe_infos)
| GLWECiphertext::from_lwe_scratch_space(module, &glwe_infos, &lwe_infos, &lwe_to_glwe_infos)
| GLWECiphertext::decrypt_scratch_space(module, &glwe_infos),
);
let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_infos);
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());
@@ -97,13 +112,13 @@ where
let data: i64 = 17;
let mut lwe_pt: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_pt);
let mut lwe_pt: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(&lwe_infos);
lwe_pt.encode_i64(data, k_lwe_pt);
let mut lwe_ct: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe, basek, k_lwe_ct);
let mut lwe_ct: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(&lwe_infos);
lwe_ct.encrypt_sk(module, &lwe_pt, &sk_lwe, &mut source_xa, &mut source_xe);
let mut ksk: LWEToGLWESwitchingKey<Vec<u8>> = LWEToGLWESwitchingKey::alloc(n, basek, k_ksk, lwe_ct.size(), rank);
let mut ksk: LWEToGLWESwitchingKey<Vec<u8>> = LWEToGLWESwitchingKey::alloc(&lwe_to_glwe_infos);
ksk.encrypt_sk(
module,
@@ -114,13 +129,13 @@ where
scratch.borrow(),
);
let mut glwe_ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_glwe_ct, rank);
let mut glwe_ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_infos);
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);
let mut glwe_pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_infos);
glwe_ct.decrypt(module, &mut glwe_pt, &sk_glwe_prepared, scratch.borrow());
assert_eq!(glwe_pt.data.at(0, 0)[0], lwe_pt.data.at(0, 0)[0]);
@@ -134,7 +149,7 @@ where
+ SvpApplyDftToDftInplace<B>
+ VecZnxIdftApplyConsume<B>
+ VecZnxFillUniform
+ VecZnxSubABInplace
+ VecZnxSubInplace
+ VecZnxAddInplace
+ VecZnxNormalizeInplace<B>
+ VecZnxAddNormal
@@ -167,42 +182,56 @@ where
+ TakeScalarZnxImpl<B>
+ TakeVecZnxImpl<B>,
{
let n: usize = module.n();
let basek: usize = 17;
let n_glwe: Degree = Degree(module.n() as u32);
let n_lwe: Degree = Degree(22);
let rank: usize = 2;
let rank: Rank = Rank(2);
let k_lwe_pt: TorusPrecision = TorusPrecision(8);
let n_lwe: usize = 22;
let k_lwe_ct: usize = 2 * basek;
let k_lwe_pt: usize = 8;
let glwe_to_lwe_infos: GLWEToLWESwitchingKeyLayout = GLWEToLWESwitchingKeyLayout {
n: n_glwe,
base2k: Base2K(17),
k: TorusPrecision(51),
rows: Rows(2),
rank_in: rank,
};
let k_glwe_ct: usize = 3 * basek;
let glwe_infos: GLWECiphertextLayout = GLWECiphertextLayout {
n: n_glwe,
base2k: Base2K(17),
k: TorusPrecision(34),
rank,
};
let k_ksk: usize = k_lwe_ct + basek;
let lwe_infos: LWECiphertextLayout = LWECiphertextLayout {
n: n_lwe,
base2k: Base2K(17),
k: TorusPrecision(34),
};
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, basek, k_ksk, rank)
| LWECiphertext::from_glwe_scratch_space(module, basek, k_lwe_ct, k_glwe_ct, k_ksk, rank)
| GLWECiphertext::decrypt_scratch_space(module, basek, k_glwe_ct),
GLWEToLWESwitchingKey::encrypt_sk_scratch_space(module, &glwe_to_lwe_infos)
| LWECiphertext::from_glwe_scratch_space(module, &lwe_infos, &glwe_infos, &glwe_to_lwe_infos)
| GLWECiphertext::decrypt_scratch_space(module, &glwe_infos),
);
let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_infos);
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);
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 glwe_pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_glwe_ct);
let mut glwe_pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_infos);
glwe_pt.encode_coeff_i64(data, k_lwe_pt, 0);
let mut glwe_ct = GLWECiphertext::alloc(n, basek, k_glwe_ct, rank);
let mut glwe_ct = GLWECiphertext::alloc(&glwe_infos);
glwe_ct.encrypt_sk(
module,
&glwe_pt,
@@ -212,7 +241,7 @@ where
scratch.borrow(),
);
let mut ksk: GLWEToLWESwitchingKey<Vec<u8>> = GLWEToLWESwitchingKey::alloc(n, basek, k_ksk, glwe_ct.size(), rank);
let mut ksk: GLWEToLWESwitchingKey<Vec<u8>> = GLWEToLWESwitchingKey::alloc(&glwe_to_lwe_infos);
ksk.encrypt_sk(
module,
@@ -223,13 +252,13 @@ where
scratch.borrow(),
);
let mut lwe_ct: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe, basek, k_lwe_ct);
let mut lwe_ct: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(&lwe_infos);
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);
let mut lwe_pt: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(&lwe_infos);
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]);