mirror of
https://github.com/arnaucube/poulpy.git
synced 2026-02-10 13:16:44 +01:00
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:
committed by
GitHub
parent
4da790ea6a
commit
37e13b965c
@@ -4,34 +4,33 @@ use poulpy_hal::{
|
||||
ScratchAvailable, SvpApplyDftToDft, SvpPPolAllocBytes, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, TakeVecZnxDftSlice,
|
||||
TakeVecZnxSlice, VecZnxAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, VecZnxBigNormalize,
|
||||
VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAdd, VecZnxDftAddInplace, VecZnxDftAllocBytes, VecZnxDftApply,
|
||||
VecZnxDftSubABInplace, VecZnxDftZero, VecZnxIdftApply, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpBytes,
|
||||
VecZnxDftSubInplace, VecZnxDftZero, VecZnxIdftApply, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpBytes,
|
||||
VecZnxMulXpMinusOneInplace, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate,
|
||||
VecZnxSubABInplace, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes,
|
||||
VecZnxSubInplace, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes,
|
||||
},
|
||||
layouts::{Backend, DataMut, DataRef, Module, Scratch, SvpPPol, VecZnx, ZnxView, ZnxZero},
|
||||
};
|
||||
|
||||
use poulpy_core::{
|
||||
Distribution, GLWEOperations, TakeGLWECt,
|
||||
layouts::{GLWECiphertext, GLWECiphertextToMut, Infos, LWECiphertext, LWECiphertextToRef},
|
||||
layouts::{GGSWInfos, GLWECiphertext, GLWECiphertextToMut, GLWEInfos, LWECiphertext, LWECiphertextToRef, LWEInfos},
|
||||
};
|
||||
|
||||
use crate::tfhe::blind_rotation::{
|
||||
BlincRotationExecute, BlindRotationKeyPrepared, CGGI, LookUpTable, LookUpTableRotationDirection,
|
||||
BlincRotationExecute, BlindRotationKeyInfos, BlindRotationKeyPrepared, CGGI, LookUpTable, LookUpTableRotationDirection,
|
||||
};
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn cggi_blind_rotate_scratch_space<B: Backend>(
|
||||
pub fn cggi_blind_rotate_scratch_space<B: Backend, OUT, GGSW>(
|
||||
module: &Module<B>,
|
||||
block_size: usize,
|
||||
extension_factor: usize,
|
||||
basek: usize,
|
||||
k_res: usize,
|
||||
k_brk: usize,
|
||||
rows: usize,
|
||||
rank: usize,
|
||||
glwe_infos: &OUT,
|
||||
brk_infos: &GGSW,
|
||||
) -> usize
|
||||
where
|
||||
OUT: GLWEInfos,
|
||||
GGSW: GGSWInfos,
|
||||
Module<B>: VecZnxDftAllocBytes
|
||||
+ VmpApplyDftToDftTmpBytes
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
@@ -39,10 +38,11 @@ where
|
||||
+ VecZnxIdftApplyTmpBytes
|
||||
+ VecZnxBigNormalizeTmpBytes,
|
||||
{
|
||||
let brk_size: usize = k_brk.div_ceil(basek);
|
||||
let brk_size: usize = brk_infos.size();
|
||||
|
||||
if block_size > 1 {
|
||||
let cols: usize = rank + 1;
|
||||
let cols: usize = (brk_infos.rank() + 1).into();
|
||||
let rows: usize = brk_infos.rows().into();
|
||||
let acc_dft: usize = module.vec_znx_dft_alloc_bytes(cols, rows) * extension_factor;
|
||||
let acc_big: usize = module.vec_znx_big_alloc_bytes(1, brk_size);
|
||||
let vmp_res: usize = module.vec_znx_dft_alloc_bytes(cols, brk_size) * extension_factor;
|
||||
@@ -50,7 +50,7 @@ where
|
||||
let acc_dft_add: usize = vmp_res;
|
||||
let vmp: usize = module.vmp_apply_dft_to_dft_tmp_bytes(brk_size, rows, rows, 2, 2, brk_size); // GGSW product: (1 x 2) x (2 x 2)
|
||||
let acc: usize = if extension_factor > 1 {
|
||||
VecZnx::alloc_bytes(module.n(), cols, k_res.div_ceil(basek)) * extension_factor
|
||||
VecZnx::alloc_bytes(module.n(), cols, glwe_infos.size()) * extension_factor
|
||||
} else {
|
||||
0
|
||||
};
|
||||
@@ -61,8 +61,8 @@ where
|
||||
+ vmp_xai
|
||||
+ (vmp | (acc_big + (module.vec_znx_big_normalize_tmp_bytes() | module.vec_znx_idft_apply_tmp_bytes())))
|
||||
} else {
|
||||
GLWECiphertext::bytes_of(module.n(), basek, k_res, rank)
|
||||
+ GLWECiphertext::external_product_scratch_space(module, basek, k_res, k_res, k_brk, 1, rank)
|
||||
GLWECiphertext::alloc_bytes(glwe_infos)
|
||||
+ GLWECiphertext::external_product_inplace_scratch_space(module, glwe_infos, brk_infos)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,11 +80,11 @@ where
|
||||
+ VecZnxDftApply<B>
|
||||
+ VecZnxDftZero<B>
|
||||
+ SvpApplyDftToDft<B>
|
||||
+ VecZnxDftSubABInplace<B>
|
||||
+ VecZnxDftSubInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxRotate
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxSubInplace
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxCopy
|
||||
@@ -142,11 +142,11 @@ fn execute_block_binary_extended<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
+ VecZnxDftApply<B>
|
||||
+ VecZnxDftZero<B>
|
||||
+ SvpApplyDftToDft<B>
|
||||
+ VecZnxDftSubABInplace<B>
|
||||
+ VecZnxDftSubInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxRotate
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxSubInplace
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxCopy
|
||||
@@ -155,11 +155,11 @@ fn execute_block_binary_extended<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
+ VmpApplyDftToDft<B>,
|
||||
Scratch<B>: TakeVecZnxDftSlice<B> + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnxSlice + ScratchAvailable + TakeVecZnx,
|
||||
{
|
||||
let n_glwe: usize = brk.n();
|
||||
let n_glwe: usize = brk.n_glwe().into();
|
||||
let extension_factor: usize = lut.extension_factor();
|
||||
let basek: usize = res.basek();
|
||||
let rows: usize = brk.rows();
|
||||
let cols: usize = res.rank() + 1;
|
||||
let base2k: usize = res.base2k().into();
|
||||
let rows: usize = brk.rows().into();
|
||||
let cols: usize = (res.rank() + 1).into();
|
||||
|
||||
let (mut acc, scratch_1) = scratch.take_vec_znx_slice(extension_factor, n_glwe, cols, res.size());
|
||||
let (mut acc_dft, scratch_2) = scratch_1.take_vec_znx_dft_slice(extension_factor, n_glwe, cols, rows);
|
||||
@@ -178,7 +178,7 @@ fn execute_block_binary_extended<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
panic!("invalid key: x_pow_a has not been initialized")
|
||||
}
|
||||
|
||||
let mut lwe_2n: Vec<i64> = vec![0i64; lwe.n() + 1]; // TODO: from scratch space
|
||||
let mut lwe_2n: Vec<i64> = vec![0i64; (lwe.n() + 1).as_usize()]; // TODO: from scratch space
|
||||
let lwe_ref: LWECiphertext<&[u8]> = lwe.to_ref();
|
||||
|
||||
let two_n: usize = 2 * n_glwe;
|
||||
@@ -233,7 +233,7 @@ fn execute_block_binary_extended<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
(0..cols).for_each(|i| {
|
||||
module.svp_apply_dft_to_dft(&mut vmp_xai, 0, &x_pow_a[ai_hi], 0, &vmp_res[j], i);
|
||||
module.vec_znx_dft_add_inplace(&mut acc_add_dft[j], i, &vmp_xai, 0);
|
||||
module.vec_znx_dft_sub_ab_inplace(&mut acc_add_dft[j], i, &vmp_res[j], i);
|
||||
module.vec_znx_dft_sub_inplace(&mut acc_add_dft[j], i, &vmp_res[j], i);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -249,7 +249,7 @@ fn execute_block_binary_extended<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
(0..cols).for_each(|k| {
|
||||
module.svp_apply_dft_to_dft(&mut vmp_xai, 0, &x_pow_a[ai_hi + 1], 0, &vmp_res[j], k);
|
||||
module.vec_znx_dft_add_inplace(&mut acc_add_dft[i], k, &vmp_xai, 0);
|
||||
module.vec_znx_dft_sub_ab_inplace(&mut acc_add_dft[i], k, &vmp_res[i], k);
|
||||
module.vec_znx_dft_sub_inplace(&mut acc_add_dft[i], k, &vmp_res[i], k);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -261,7 +261,7 @@ fn execute_block_binary_extended<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
(0..cols).for_each(|k| {
|
||||
module.svp_apply_dft_to_dft(&mut vmp_xai, 0, &x_pow_a[ai_hi], 0, &vmp_res[j], k);
|
||||
module.vec_znx_dft_add_inplace(&mut acc_add_dft[i], k, &vmp_xai, 0);
|
||||
module.vec_znx_dft_sub_ab_inplace(&mut acc_add_dft[i], k, &vmp_res[i], k);
|
||||
module.vec_znx_dft_sub_inplace(&mut acc_add_dft[i], k, &vmp_res[i], k);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -275,14 +275,14 @@ fn execute_block_binary_extended<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
(0..cols).for_each(|i| {
|
||||
module.vec_znx_idft_apply(&mut acc_add_big, 0, &acc_add_dft[j], i, scratch7);
|
||||
module.vec_znx_big_add_small_inplace(&mut acc_add_big, 0, &acc[j], i);
|
||||
module.vec_znx_big_normalize(basek, &mut acc[j], i, &acc_add_big, 0, scratch7);
|
||||
module.vec_znx_big_normalize(base2k, &mut acc[j], i, base2k, &acc_add_big, 0, scratch7);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
(0..cols).for_each(|i| {
|
||||
module.vec_znx_copy(&mut res.data, i, &acc[0], i);
|
||||
module.vec_znx_copy(res.data_mut(), i, &acc[0], i);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -309,11 +309,11 @@ fn execute_block_binary<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
+ VecZnxDftApply<B>
|
||||
+ VecZnxDftZero<B>
|
||||
+ SvpApplyDftToDft<B>
|
||||
+ VecZnxDftSubABInplace<B>
|
||||
+ VecZnxDftSubInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxRotate
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxSubInplace
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxCopy
|
||||
@@ -322,15 +322,15 @@ fn execute_block_binary<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
+ VecZnxBigNormalize<B>,
|
||||
Scratch<B>: TakeVecZnxDftSlice<B> + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnxSlice + ScratchAvailable + TakeVecZnx,
|
||||
{
|
||||
let n_glwe: usize = brk.n();
|
||||
let mut lwe_2n: Vec<i64> = vec![0i64; lwe.n() + 1]; // TODO: from scratch space
|
||||
let n_glwe: usize = brk.n_glwe().into();
|
||||
let mut lwe_2n: Vec<i64> = vec![0i64; (lwe.n() + 1).into()]; // TODO: from scratch space
|
||||
let mut out_mut: GLWECiphertext<&mut [u8]> = res.to_mut();
|
||||
let lwe_ref: LWECiphertext<&[u8]> = lwe.to_ref();
|
||||
let two_n: usize = n_glwe << 1;
|
||||
let basek: usize = brk.basek();
|
||||
let rows: usize = brk.rows();
|
||||
let base2k: usize = brk.base2k().into();
|
||||
let rows: usize = brk.rows().into();
|
||||
|
||||
let cols: usize = out_mut.rank() + 1;
|
||||
let cols: usize = (out_mut.rank() + 1).into();
|
||||
|
||||
mod_switch_2n(
|
||||
2 * lut.domain_size(),
|
||||
@@ -342,10 +342,10 @@ fn execute_block_binary<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
let a: &[i64] = &lwe_2n[1..];
|
||||
let b: i64 = lwe_2n[0];
|
||||
|
||||
out_mut.data.zero();
|
||||
out_mut.data_mut().zero();
|
||||
|
||||
// Initialize out to X^{b} * LUT(X)
|
||||
module.vec_znx_rotate(b, &mut out_mut.data, 0, &lut.data[0], 0);
|
||||
module.vec_znx_rotate(b, out_mut.data_mut(), 0, &lut.data[0], 0);
|
||||
|
||||
let block_size: usize = brk.block_size();
|
||||
|
||||
@@ -369,7 +369,7 @@ fn execute_block_binary<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
)
|
||||
.for_each(|(ai, ski)| {
|
||||
(0..cols).for_each(|j| {
|
||||
module.vec_znx_dft_apply(1, 0, &mut acc_dft, j, &out_mut.data, j);
|
||||
module.vec_znx_dft_apply(1, 0, &mut acc_dft, j, out_mut.data_mut(), j);
|
||||
});
|
||||
|
||||
module.vec_znx_dft_zero(&mut acc_add_dft);
|
||||
@@ -384,7 +384,7 @@ fn execute_block_binary<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
(0..cols).for_each(|i| {
|
||||
module.svp_apply_dft_to_dft(&mut vmp_xai, 0, &x_pow_a[ai_pos], 0, &vmp_res, i);
|
||||
module.vec_znx_dft_add_inplace(&mut acc_add_dft, i, &vmp_xai, 0);
|
||||
module.vec_znx_dft_sub_ab_inplace(&mut acc_add_dft, i, &vmp_res, i);
|
||||
module.vec_znx_dft_sub_inplace(&mut acc_add_dft, i, &vmp_res, i);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -393,8 +393,16 @@ fn execute_block_binary<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
|
||||
(0..cols).for_each(|i| {
|
||||
module.vec_znx_idft_apply(&mut acc_add_big, 0, &acc_add_dft, i, scratch_5);
|
||||
module.vec_znx_big_add_small_inplace(&mut acc_add_big, 0, &out_mut.data, i);
|
||||
module.vec_znx_big_normalize(basek, &mut out_mut.data, i, &acc_add_big, 0, scratch_5);
|
||||
module.vec_znx_big_add_small_inplace(&mut acc_add_big, 0, out_mut.data_mut(), i);
|
||||
module.vec_znx_big_normalize(
|
||||
base2k,
|
||||
out_mut.data_mut(),
|
||||
i,
|
||||
base2k,
|
||||
&acc_add_big,
|
||||
0,
|
||||
scratch_5,
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -423,11 +431,11 @@ fn execute_standard<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
+ VecZnxDftApply<B>
|
||||
+ VecZnxDftZero<B>
|
||||
+ SvpApplyDftToDft<B>
|
||||
+ VecZnxDftSubABInplace<B>
|
||||
+ VecZnxDftSubInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxRotate
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxSubInplace
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxCopy
|
||||
@@ -450,10 +458,10 @@ fn execute_standard<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
);
|
||||
assert_eq!(
|
||||
lut.domain_size(),
|
||||
brk.n(),
|
||||
brk.n_glwe().as_usize(),
|
||||
"lut.n(): {} != brk.n(): {}",
|
||||
lut.domain_size(),
|
||||
brk.n()
|
||||
brk.n_glwe().as_usize()
|
||||
);
|
||||
assert_eq!(
|
||||
res.rank(),
|
||||
@@ -464,17 +472,16 @@ fn execute_standard<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
);
|
||||
assert_eq!(
|
||||
lwe.n(),
|
||||
brk.data.len(),
|
||||
brk.n_lwe(),
|
||||
"lwe.n(): {} != brk.data.len(): {}",
|
||||
lwe.n(),
|
||||
brk.data.len()
|
||||
brk.n_lwe()
|
||||
);
|
||||
}
|
||||
|
||||
let mut lwe_2n: Vec<i64> = vec![0i64; lwe.n() + 1]; // TODO: from scratch space
|
||||
let mut lwe_2n: Vec<i64> = vec![0i64; (lwe.n() + 1).into()]; // TODO: from scratch space
|
||||
let mut out_mut: GLWECiphertext<&mut [u8]> = res.to_mut();
|
||||
let lwe_ref: LWECiphertext<&[u8]> = lwe.to_ref();
|
||||
let basek: usize = brk.basek();
|
||||
|
||||
mod_switch_2n(
|
||||
2 * lut.domain_size(),
|
||||
@@ -486,13 +493,13 @@ fn execute_standard<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
let a: &[i64] = &lwe_2n[1..];
|
||||
let b: i64 = lwe_2n[0];
|
||||
|
||||
out_mut.data.zero();
|
||||
out_mut.data_mut().zero();
|
||||
|
||||
// Initialize out to X^{b} * LUT(X)
|
||||
module.vec_znx_rotate(b, &mut out_mut.data, 0, &lut.data[0], 0);
|
||||
module.vec_znx_rotate(b, out_mut.data_mut(), 0, &lut.data[0], 0);
|
||||
|
||||
// ACC + [sum DFT(X^ai -1) * (DFT(ACC) x BRKi)]
|
||||
let (mut acc_tmp, scratch_1) = scratch.take_glwe_ct(out_mut.n(), basek, out_mut.k(), out_mut.rank());
|
||||
let (mut acc_tmp, scratch_1) = scratch.take_glwe_ct(&out_mut);
|
||||
|
||||
// TODO: see if faster by skipping normalization in external product and keeping acc in big coeffs
|
||||
// TODO: first iteration can be optimized to be a gglwe product
|
||||
@@ -507,13 +514,13 @@ fn execute_standard<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
out_mut.add_inplace(module, &acc_tmp);
|
||||
});
|
||||
|
||||
// We can normalize only at the end because we add normalized values in [-2^{basek-1}, 2^{basek-1}]
|
||||
// on top of each others, thus ~ 2^{63-basek} additions are supported before overflow.
|
||||
// We can normalize only at the end because we add normalized values in [-2^{base2k-1}, 2^{base2k-1}]
|
||||
// on top of each others, thus ~ 2^{63-base2k} additions are supported before overflow.
|
||||
out_mut.normalize_inplace(module, scratch_1);
|
||||
}
|
||||
|
||||
pub fn mod_switch_2n(n: usize, res: &mut [i64], lwe: &LWECiphertext<&[u8]>, rot_dir: LookUpTableRotationDirection) {
|
||||
let basek: usize = lwe.basek();
|
||||
let base2k: usize = lwe.base2k().into();
|
||||
|
||||
let log2n: usize = usize::BITS as usize - (n - 1).leading_zeros() as usize + 1;
|
||||
|
||||
@@ -526,23 +533,23 @@ pub fn mod_switch_2n(n: usize, res: &mut [i64], lwe: &LWECiphertext<&[u8]>, rot_
|
||||
LookUpTableRotationDirection::Right => {}
|
||||
}
|
||||
|
||||
if basek > log2n {
|
||||
let diff: usize = basek - (log2n - 1); // additional -1 because we map to [-N/2, N/2) instead of [0, N)
|
||||
if base2k > log2n {
|
||||
let diff: usize = base2k - (log2n - 1); // additional -1 because we map to [-N/2, N/2) instead of [0, N)
|
||||
res.iter_mut().for_each(|x| {
|
||||
*x = div_round_by_pow2(x, diff);
|
||||
})
|
||||
} else {
|
||||
let rem: usize = basek - (log2n % basek);
|
||||
let size: usize = log2n.div_ceil(basek);
|
||||
let rem: usize = base2k - (log2n % base2k);
|
||||
let size: usize = log2n.div_ceil(base2k);
|
||||
(1..size).for_each(|i| {
|
||||
if i == size - 1 && rem != basek {
|
||||
let k_rem: usize = basek - rem;
|
||||
if i == size - 1 && rem != base2k {
|
||||
let k_rem: usize = base2k - rem;
|
||||
izip!(lwe.data().at(0, i).iter(), res.iter_mut()).for_each(|(x, y)| {
|
||||
*y = (*y << k_rem) + (x >> rem);
|
||||
});
|
||||
} else {
|
||||
izip!(lwe.data().at(0, i).iter(), res.iter_mut()).for_each(|(x, y)| {
|
||||
*y = (*y << basek) + x;
|
||||
*y = (*y << base2k) + x;
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
@@ -2,7 +2,7 @@ use poulpy_hal::{
|
||||
api::{
|
||||
ScratchAvailable, SvpApplyDftToDftInplace, TakeVecZnx, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal,
|
||||
VecZnxAddScalarInplace, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform,
|
||||
VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubABInplace,
|
||||
VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace,
|
||||
VmpPMatAlloc, VmpPrepare,
|
||||
},
|
||||
layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, ScalarZnxToRef, Scratch, ZnxView, ZnxViewMut},
|
||||
@@ -14,21 +14,27 @@ use std::marker::PhantomData;
|
||||
use poulpy_core::{
|
||||
Distribution,
|
||||
layouts::{
|
||||
GGSWCiphertext, LWESecret,
|
||||
GGSWCiphertext, GGSWInfos, LWESecret,
|
||||
compressed::GGSWCiphertextCompressed,
|
||||
prepared::{GGSWCiphertextPrepared, GLWESecretPrepared},
|
||||
},
|
||||
};
|
||||
|
||||
use crate::tfhe::blind_rotation::{
|
||||
BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyCompressed, BlindRotationKeyEncryptSk, BlindRotationKeyPrepared,
|
||||
BlindRotationKeyPreparedAlloc, CGGI,
|
||||
BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyCompressed, BlindRotationKeyEncryptSk, BlindRotationKeyInfos,
|
||||
BlindRotationKeyPrepared, BlindRotationKeyPreparedAlloc, CGGI,
|
||||
};
|
||||
|
||||
impl BlindRotationKeyAlloc for BlindRotationKey<Vec<u8>, CGGI> {
|
||||
fn alloc(n_gglwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self {
|
||||
let mut data: Vec<GGSWCiphertext<Vec<u8>>> = Vec::with_capacity(n_lwe);
|
||||
(0..n_lwe).for_each(|_| data.push(GGSWCiphertext::alloc(n_gglwe, basek, k, rows, 1, rank)));
|
||||
fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: BlindRotationKeyInfos,
|
||||
{
|
||||
let mut data: Vec<GGSWCiphertext<Vec<u8>>> = Vec::with_capacity(infos.n_lwe().into());
|
||||
for _ in 0..infos.n_lwe().as_usize() {
|
||||
data.push(GGSWCiphertext::alloc(infos));
|
||||
}
|
||||
|
||||
Self {
|
||||
keys: data,
|
||||
dist: Distribution::NONE,
|
||||
@@ -38,11 +44,12 @@ impl BlindRotationKeyAlloc for BlindRotationKey<Vec<u8>, CGGI> {
|
||||
}
|
||||
|
||||
impl BlindRotationKey<Vec<u8>, CGGI> {
|
||||
pub fn generate_from_sk_scratch_space<B: Backend>(module: &Module<B>, basek: usize, k: usize, rank: usize) -> usize
|
||||
pub fn generate_from_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
|
||||
where
|
||||
A: GGSWInfos,
|
||||
Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes,
|
||||
{
|
||||
GGSWCiphertext::encrypt_sk_scratch_space(module, basek, k, rank)
|
||||
GGSWCiphertext::encrypt_sk_scratch_space(module, infos)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +63,7 @@ where
|
||||
+ VecZnxIdftApplyConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxSubInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
@@ -78,9 +85,11 @@ where
|
||||
{
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
assert_eq!(self.keys.len(), sk_lwe.n());
|
||||
assert!(sk_glwe.n() <= module.n());
|
||||
assert_eq!(sk_glwe.rank(), self.keys[0].rank());
|
||||
use poulpy_core::layouts::{GLWEInfos, LWEInfos};
|
||||
|
||||
assert_eq!(self.keys.len() as u32, sk_lwe.n());
|
||||
assert!(sk_glwe.n() <= module.n() as u32);
|
||||
assert_eq!(sk_glwe.rank(), self.rank());
|
||||
match sk_lwe.dist() {
|
||||
Distribution::BinaryBlock(_)
|
||||
| Distribution::BinaryFixed(_)
|
||||
@@ -94,7 +103,7 @@ where
|
||||
|
||||
self.dist = sk_lwe.dist();
|
||||
|
||||
let mut pt: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(sk_glwe.n(), 1);
|
||||
let mut pt: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(sk_glwe.n().into(), 1);
|
||||
let sk_ref: ScalarZnx<&[u8]> = sk_lwe.data().to_ref();
|
||||
|
||||
self.keys.iter_mut().enumerate().for_each(|(i, ggsw)| {
|
||||
@@ -108,13 +117,12 @@ impl<B: Backend> BlindRotationKeyPreparedAlloc<B> for BlindRotationKeyPrepared<V
|
||||
where
|
||||
Module<B>: VmpPMatAlloc<B> + VmpPrepare<B>,
|
||||
{
|
||||
fn alloc(module: &Module<B>, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self {
|
||||
let mut data: Vec<GGSWCiphertextPrepared<Vec<u8>, B>> = Vec::with_capacity(n_lwe);
|
||||
(0..n_lwe).for_each(|_| {
|
||||
data.push(GGSWCiphertextPrepared::alloc(
|
||||
module, basek, k, rows, 1, rank,
|
||||
))
|
||||
});
|
||||
fn alloc<A>(module: &Module<B>, infos: &A) -> Self
|
||||
where
|
||||
A: BlindRotationKeyInfos,
|
||||
{
|
||||
let mut data: Vec<GGSWCiphertextPrepared<Vec<u8>, B>> = Vec::with_capacity(infos.n_lwe().into());
|
||||
(0..infos.n_lwe().as_usize()).for_each(|_| data.push(GGSWCiphertextPrepared::alloc(module, infos)));
|
||||
Self {
|
||||
data,
|
||||
dist: Distribution::NONE,
|
||||
@@ -125,13 +133,12 @@ where
|
||||
}
|
||||
|
||||
impl BlindRotationKeyCompressed<Vec<u8>, CGGI> {
|
||||
pub fn alloc(n_gglwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self {
|
||||
let mut data: Vec<GGSWCiphertextCompressed<Vec<u8>>> = Vec::with_capacity(n_lwe);
|
||||
(0..n_lwe).for_each(|_| {
|
||||
data.push(GGSWCiphertextCompressed::alloc(
|
||||
n_gglwe, basek, k, rows, 1, rank,
|
||||
))
|
||||
});
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: BlindRotationKeyInfos,
|
||||
{
|
||||
let mut data: Vec<GGSWCiphertextCompressed<Vec<u8>>> = Vec::with_capacity(infos.n_lwe().into());
|
||||
(0..infos.n_lwe().as_usize()).for_each(|_| data.push(GGSWCiphertextCompressed::alloc(infos)));
|
||||
Self {
|
||||
keys: data,
|
||||
dist: Distribution::NONE,
|
||||
@@ -139,11 +146,12 @@ impl BlindRotationKeyCompressed<Vec<u8>, CGGI> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_from_sk_scratch_space<B: Backend>(module: &Module<B>, basek: usize, k: usize, rank: usize) -> usize
|
||||
pub fn generate_from_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
|
||||
where
|
||||
A: GGSWInfos,
|
||||
Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes,
|
||||
{
|
||||
GGSWCiphertextCompressed::encrypt_sk_scratch_space(module, basek, k, rank)
|
||||
GGSWCiphertextCompressed::encrypt_sk_scratch_space(module, infos)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,7 +176,7 @@ impl<D: DataMut> BlindRotationKeyCompressed<D, CGGI> {
|
||||
+ VecZnxIdftApplyConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxSubInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
@@ -178,9 +186,11 @@ impl<D: DataMut> BlindRotationKeyCompressed<D, CGGI> {
|
||||
{
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
assert_eq!(self.keys.len(), sk_lwe.n());
|
||||
assert!(sk_glwe.n() <= module.n());
|
||||
assert_eq!(sk_glwe.rank(), self.keys[0].rank());
|
||||
use poulpy_core::layouts::{GLWEInfos, LWEInfos};
|
||||
|
||||
assert_eq!(self.n_lwe(), sk_lwe.n());
|
||||
assert!(sk_glwe.n() <= module.n() as u32);
|
||||
assert_eq!(sk_glwe.rank(), self.rank());
|
||||
match sk_lwe.dist() {
|
||||
Distribution::BinaryBlock(_)
|
||||
| Distribution::BinaryFixed(_)
|
||||
@@ -194,7 +204,7 @@ impl<D: DataMut> BlindRotationKeyCompressed<D, CGGI> {
|
||||
|
||||
self.dist = sk_lwe.dist();
|
||||
|
||||
let mut pt: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(sk_glwe.n(), 1);
|
||||
let mut pt: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(sk_glwe.n().into(), 1);
|
||||
let sk_ref: ScalarZnx<&[u8]> = sk_lwe.data().to_ref();
|
||||
|
||||
let mut source_xa: Source = Source::new(seed_xa);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use poulpy_hal::{
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, Reset, Scratch, WriterTo},
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, Scratch, WriterTo},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
@@ -7,15 +7,78 @@ use std::{fmt, marker::PhantomData};
|
||||
|
||||
use poulpy_core::{
|
||||
Distribution,
|
||||
layouts::{GGSWCiphertext, Infos, LWESecret, prepared::GLWESecretPrepared},
|
||||
layouts::{
|
||||
Base2K, Degree, Digits, GGSWCiphertext, GGSWInfos, GLWEInfos, LWEInfos, LWESecret, Rank, Rows, TorusPrecision,
|
||||
prepared::GLWESecretPrepared,
|
||||
},
|
||||
};
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use crate::tfhe::blind_rotation::BlindRotationAlgo;
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct BlindRotationKeyLayout {
|
||||
pub n_glwe: Degree,
|
||||
pub n_lwe: Degree,
|
||||
pub base2k: Base2K,
|
||||
pub k: TorusPrecision,
|
||||
pub rows: Rows,
|
||||
pub rank: Rank,
|
||||
}
|
||||
|
||||
impl BlindRotationKeyInfos for BlindRotationKeyLayout {
|
||||
fn n_glwe(&self) -> Degree {
|
||||
self.n_glwe
|
||||
}
|
||||
|
||||
fn n_lwe(&self) -> Degree {
|
||||
self.n_lwe
|
||||
}
|
||||
}
|
||||
|
||||
impl GGSWInfos for BlindRotationKeyLayout {
|
||||
fn digits(&self) -> Digits {
|
||||
Digits(1)
|
||||
}
|
||||
|
||||
fn rows(&self) -> Rows {
|
||||
self.rows
|
||||
}
|
||||
}
|
||||
|
||||
impl GLWEInfos for BlindRotationKeyLayout {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank
|
||||
}
|
||||
}
|
||||
|
||||
impl LWEInfos for BlindRotationKeyLayout {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.base2k
|
||||
}
|
||||
|
||||
fn k(&self) -> TorusPrecision {
|
||||
self.k
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
self.n_glwe
|
||||
}
|
||||
}
|
||||
|
||||
pub trait BlindRotationKeyInfos
|
||||
where
|
||||
Self: GGSWInfos,
|
||||
{
|
||||
fn n_glwe(&self) -> Degree;
|
||||
fn n_lwe(&self) -> Degree;
|
||||
}
|
||||
|
||||
pub trait BlindRotationKeyAlloc {
|
||||
fn alloc(n_gglwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self;
|
||||
fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: BlindRotationKeyInfos;
|
||||
}
|
||||
|
||||
pub trait BlindRotationKeyEncryptSk<B: Backend> {
|
||||
@@ -42,7 +105,7 @@ pub struct BlindRotationKey<D: Data, BRT: BlindRotationAlgo> {
|
||||
|
||||
impl<D: DataRef, BRT: BlindRotationAlgo> fmt::Debug for BlindRotationKey<D, BRT> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self)
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,19 +129,12 @@ impl<D: Data, BRT: BlindRotationAlgo> Eq for BlindRotationKey<D, BRT> {}
|
||||
impl<D: DataRef, BRT: BlindRotationAlgo> fmt::Display for BlindRotationKey<D, BRT> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
for (i, key) in self.keys.iter().enumerate() {
|
||||
write!(f, "key[{}]: {}", i, key)?;
|
||||
write!(f, "key[{i}]: {key}")?;
|
||||
}
|
||||
writeln!(f, "{:?}", self.dist)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, BRT: BlindRotationAlgo> Reset for BlindRotationKey<D, BRT> {
|
||||
fn reset(&mut self) {
|
||||
self.keys.iter_mut().for_each(|key| key.reset());
|
||||
self.dist = Distribution::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, BRT: BlindRotationAlgo> FillUniform for BlindRotationKey<D, BRT> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.keys
|
||||
@@ -121,41 +177,55 @@ impl<D: DataRef, BRT: BlindRotationAlgo> WriterTo for BlindRotationKey<D, BRT> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, BRT: BlindRotationAlgo> BlindRotationKeyInfos for BlindRotationKey<D, BRT> {
|
||||
fn n_glwe(&self) -> Degree {
|
||||
self.n()
|
||||
}
|
||||
|
||||
fn n_lwe(&self) -> Degree {
|
||||
Degree(self.keys.len() as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, BRT: BlindRotationAlgo> BlindRotationKey<D, BRT> {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn n(&self) -> usize {
|
||||
self.keys[0].n()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn rows(&self) -> usize {
|
||||
self.keys[0].rows()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn k(&self) -> usize {
|
||||
self.keys[0].k()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn size(&self) -> usize {
|
||||
self.keys[0].size()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn rank(&self) -> usize {
|
||||
self.keys[0].rank()
|
||||
}
|
||||
|
||||
pub(crate) fn basek(&self) -> usize {
|
||||
self.keys[0].basek()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn block_size(&self) -> usize {
|
||||
fn block_size(&self) -> usize {
|
||||
match self.dist {
|
||||
Distribution::BinaryBlock(value) => value,
|
||||
_ => 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, BRT: BlindRotationAlgo> LWEInfos for BlindRotationKey<D, BRT> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.keys[0].base2k()
|
||||
}
|
||||
|
||||
fn k(&self) -> TorusPrecision {
|
||||
self.keys[0].k()
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
self.keys[0].n()
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
self.keys[0].size()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, BRT: BlindRotationAlgo> GLWEInfos for BlindRotationKey<D, BRT> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.keys[0].rank()
|
||||
}
|
||||
}
|
||||
impl<D: DataRef, BRT: BlindRotationAlgo> GGSWInfos for BlindRotationKey<D, BRT> {
|
||||
fn digits(&self) -> poulpy_core::layouts::Digits {
|
||||
Digits(1)
|
||||
}
|
||||
|
||||
fn rows(&self) -> Rows {
|
||||
self.keys[0].rows()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use poulpy_hal::{
|
||||
layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, Reset, WriterTo},
|
||||
layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
@@ -8,10 +8,10 @@ use std::{fmt, marker::PhantomData};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use poulpy_core::{
|
||||
Distribution,
|
||||
layouts::{Infos, compressed::GGSWCiphertextCompressed},
|
||||
layouts::{Base2K, Degree, Digits, GGSWInfos, GLWEInfos, LWEInfos, TorusPrecision, compressed::GGSWCiphertextCompressed},
|
||||
};
|
||||
|
||||
use crate::tfhe::blind_rotation::BlindRotationAlgo;
|
||||
use crate::tfhe::blind_rotation::{BlindRotationAlgo, BlindRotationKeyInfos};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BlindRotationKeyCompressed<D: Data, BRT: BlindRotationAlgo> {
|
||||
@@ -22,7 +22,7 @@ pub struct BlindRotationKeyCompressed<D: Data, BRT: BlindRotationAlgo> {
|
||||
|
||||
impl<D: DataRef, BRT: BlindRotationAlgo> fmt::Debug for BlindRotationKeyCompressed<D, BRT> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self)
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,19 +45,12 @@ impl<D: Data, BRT: BlindRotationAlgo> Eq for BlindRotationKeyCompressed<D, BRT>
|
||||
impl<D: DataRef, BRT: BlindRotationAlgo> fmt::Display for BlindRotationKeyCompressed<D, BRT> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
for (i, key) in self.keys.iter().enumerate() {
|
||||
write!(f, "key[{}]: {}", i, key)?;
|
||||
write!(f, "key[{i}]: {key}")?;
|
||||
}
|
||||
writeln!(f, "{:?}", self.dist)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, BRT: BlindRotationAlgo> Reset for BlindRotationKeyCompressed<D, BRT> {
|
||||
fn reset(&mut self) {
|
||||
self.keys.iter_mut().for_each(|key| key.reset());
|
||||
self.dist = Distribution::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, BRT: BlindRotationAlgo> FillUniform for BlindRotationKeyCompressed<D, BRT> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.keys
|
||||
@@ -100,37 +93,51 @@ impl<D: DataRef, BRT: BlindRotationAlgo> WriterTo for BlindRotationKeyCompressed
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, BRA: BlindRotationAlgo> BlindRotationKeyCompressed<D, BRA> {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn n(&self) -> usize {
|
||||
impl<D: DataRef, BRA: BlindRotationAlgo> BlindRotationKeyInfos for BlindRotationKeyCompressed<D, BRA> {
|
||||
fn n_glwe(&self) -> Degree {
|
||||
self.n()
|
||||
}
|
||||
|
||||
fn n_lwe(&self) -> Degree {
|
||||
Degree(self.keys.len() as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, BRA: BlindRotationAlgo> LWEInfos for BlindRotationKeyCompressed<D, BRA> {
|
||||
fn n(&self) -> Degree {
|
||||
self.keys[0].n()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn rows(&self) -> usize {
|
||||
self.keys[0].rows()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn k(&self) -> usize {
|
||||
self.keys[0].k()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn size(&self) -> usize {
|
||||
fn size(&self) -> usize {
|
||||
self.keys[0].size()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn rank(&self) -> usize {
|
||||
fn k(&self) -> TorusPrecision {
|
||||
self.keys[0].k()
|
||||
}
|
||||
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.keys[0].base2k()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, BRA: BlindRotationAlgo> GLWEInfos for BlindRotationKeyCompressed<D, BRA> {
|
||||
fn rank(&self) -> poulpy_core::layouts::Rank {
|
||||
self.keys[0].rank()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn basek(&self) -> usize {
|
||||
self.keys[0].basek()
|
||||
impl<D: DataRef, BRA: BlindRotationAlgo> GGSWInfos for BlindRotationKeyCompressed<D, BRA> {
|
||||
fn rows(&self) -> poulpy_core::layouts::Rows {
|
||||
self.keys[0].rows()
|
||||
}
|
||||
|
||||
fn digits(&self) -> poulpy_core::layouts::Digits {
|
||||
Digits(1)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, BRA: BlindRotationAlgo> BlindRotationKeyCompressed<D, BRA> {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn block_size(&self) -> usize {
|
||||
match self.dist {
|
||||
|
||||
@@ -8,15 +8,17 @@ use std::marker::PhantomData;
|
||||
use poulpy_core::{
|
||||
Distribution,
|
||||
layouts::{
|
||||
Infos,
|
||||
Base2K, Degree, Digits, GGSWInfos, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision,
|
||||
prepared::{GGSWCiphertextPrepared, Prepare, PrepareAlloc},
|
||||
},
|
||||
};
|
||||
|
||||
use crate::tfhe::blind_rotation::{BlindRotationAlgo, BlindRotationKey, utils::set_xai_plus_y};
|
||||
use crate::tfhe::blind_rotation::{BlindRotationAlgo, BlindRotationKey, BlindRotationKeyInfos, utils::set_xai_plus_y};
|
||||
|
||||
pub trait BlindRotationKeyPreparedAlloc<B: Backend> {
|
||||
fn alloc(module: &Module<B>, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self;
|
||||
fn alloc<A>(module: &Module<B>, infos: &A) -> Self
|
||||
where
|
||||
A: BlindRotationKeyInfos;
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
@@ -27,37 +29,51 @@ pub struct BlindRotationKeyPrepared<D: Data, BRT: BlindRotationAlgo, B: Backend>
|
||||
pub(crate) _phantom: PhantomData<BRT>,
|
||||
}
|
||||
|
||||
impl<D: Data, BRT: BlindRotationAlgo, B: Backend> BlindRotationKeyPrepared<D, BRT, B> {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn n(&self) -> usize {
|
||||
self.data[0].n()
|
||||
impl<D: Data, BRT: BlindRotationAlgo, B: Backend> BlindRotationKeyInfos for BlindRotationKeyPrepared<D, BRT, B> {
|
||||
fn n_glwe(&self) -> Degree {
|
||||
self.n()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn rows(&self) -> usize {
|
||||
self.data[0].rows()
|
||||
fn n_lwe(&self) -> Degree {
|
||||
Degree(self.data.len() as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, BRT: BlindRotationAlgo, B: Backend> LWEInfos for BlindRotationKeyPrepared<D, BRT, B> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.data[0].base2k()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn k(&self) -> usize {
|
||||
fn k(&self) -> TorusPrecision {
|
||||
self.data[0].k()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn size(&self) -> usize {
|
||||
fn n(&self) -> Degree {
|
||||
self.data[0].n()
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
self.data[0].size()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn rank(&self) -> usize {
|
||||
impl<D: Data, BRT: BlindRotationAlgo, B: Backend> GLWEInfos for BlindRotationKeyPrepared<D, BRT, B> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.data[0].rank()
|
||||
}
|
||||
|
||||
pub(crate) fn basek(&self) -> usize {
|
||||
self.data[0].basek()
|
||||
}
|
||||
impl<D: Data, BRT: BlindRotationAlgo, B: Backend> GGSWInfos for BlindRotationKeyPrepared<D, BRT, B> {
|
||||
fn digits(&self) -> poulpy_core::layouts::Digits {
|
||||
Digits(1)
|
||||
}
|
||||
|
||||
pub(crate) fn block_size(&self) -> usize {
|
||||
fn rows(&self) -> Rows {
|
||||
self.data[0].rows()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, BRT: BlindRotationAlgo, B: Backend> BlindRotationKeyPrepared<D, BRT, B> {
|
||||
pub fn block_size(&self) -> usize {
|
||||
match self.dist {
|
||||
Distribution::BinaryBlock(value) => value,
|
||||
_ => 1,
|
||||
@@ -72,14 +88,7 @@ where
|
||||
BlindRotationKeyPrepared<Vec<u8>, BRA, B>: Prepare<B, BlindRotationKey<D, BRA>>,
|
||||
{
|
||||
fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> BlindRotationKeyPrepared<Vec<u8>, BRA, B> {
|
||||
let mut brk: BlindRotationKeyPrepared<Vec<u8>, BRA, B> = BlindRotationKeyPrepared::alloc(
|
||||
module,
|
||||
self.keys.len(),
|
||||
self.basek(),
|
||||
self.k(),
|
||||
self.rows(),
|
||||
self.rank(),
|
||||
);
|
||||
let mut brk: BlindRotationKeyPrepared<Vec<u8>, BRA, B> = BlindRotationKeyPrepared::alloc(module, self);
|
||||
brk.prepare(module, self, scratch);
|
||||
brk
|
||||
}
|
||||
@@ -96,7 +105,7 @@ where
|
||||
assert_eq!(self.data.len(), other.keys.len());
|
||||
}
|
||||
|
||||
let n: usize = other.n();
|
||||
let n: usize = other.n().as_usize();
|
||||
|
||||
self.data
|
||||
.iter_mut()
|
||||
|
||||
@@ -15,29 +15,28 @@ pub enum LookUpTableRotationDirection {
|
||||
pub struct LookUpTable {
|
||||
pub(crate) data: Vec<VecZnx<Vec<u8>>>,
|
||||
pub(crate) rot_dir: LookUpTableRotationDirection,
|
||||
pub(crate) basek: usize,
|
||||
pub(crate) base2k: usize,
|
||||
pub(crate) k: usize,
|
||||
pub(crate) drift: usize,
|
||||
}
|
||||
|
||||
impl LookUpTable {
|
||||
pub fn alloc<B: Backend>(module: &Module<B>, basek: usize, k: usize, extension_factor: usize) -> Self {
|
||||
pub fn alloc<B: Backend>(module: &Module<B>, base2k: usize, k: usize, extension_factor: usize) -> Self {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
assert!(
|
||||
extension_factor & (extension_factor - 1) == 0,
|
||||
"extension_factor must be a power of two but is: {}",
|
||||
extension_factor
|
||||
"extension_factor must be a power of two but is: {extension_factor}"
|
||||
);
|
||||
}
|
||||
let size: usize = k.div_ceil(basek);
|
||||
let size: usize = k.div_ceil(base2k);
|
||||
let mut data: Vec<VecZnx<Vec<u8>>> = Vec::with_capacity(extension_factor);
|
||||
(0..extension_factor).for_each(|_| {
|
||||
data.push(VecZnx::alloc(module.n(), 1, size));
|
||||
});
|
||||
Self {
|
||||
data,
|
||||
basek,
|
||||
base2k,
|
||||
k,
|
||||
drift: 0,
|
||||
rot_dir: LookUpTableRotationDirection::Left,
|
||||
@@ -80,27 +79,27 @@ impl LookUpTable {
|
||||
{
|
||||
assert!(f.len() <= module.n());
|
||||
|
||||
let basek: usize = self.basek;
|
||||
let base2k: usize = self.base2k;
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(module.vec_znx_normalize_tmp_bytes());
|
||||
|
||||
// Get the number minimum limb to store the message modulus
|
||||
let limbs: usize = k.div_ceil(basek);
|
||||
let limbs: usize = k.div_ceil(base2k);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
assert!(f.len() <= module.n());
|
||||
assert!(
|
||||
(max_bit_size(f) + (k % basek) as u32) < i64::BITS,
|
||||
"overflow: max(|f|) << (k%basek) > i64::BITS"
|
||||
(max_bit_size(f) + (k % base2k) as u32) < i64::BITS,
|
||||
"overflow: max(|f|) << (k%base2k) > i64::BITS"
|
||||
);
|
||||
assert!(limbs <= self.data[0].size());
|
||||
}
|
||||
|
||||
// Scaling factor
|
||||
let mut scale = 1;
|
||||
if !k.is_multiple_of(basek) {
|
||||
scale <<= basek - (k % basek);
|
||||
if !k.is_multiple_of(base2k) {
|
||||
scale <<= base2k - (k % base2k);
|
||||
}
|
||||
|
||||
// #elements in lookup table
|
||||
@@ -109,7 +108,7 @@ impl LookUpTable {
|
||||
// If LUT size > TakeScalarZnx
|
||||
let domain_size: usize = self.domain_size();
|
||||
|
||||
let size: usize = self.k.div_ceil(self.basek);
|
||||
let size: usize = self.k.div_ceil(self.base2k);
|
||||
|
||||
// Equivalent to AUTO([f(0), -f(n-1), -f(n-2), ..., -f(1)], -1)
|
||||
let mut lut_full: VecZnx<Vec<u8>> = VecZnx::alloc(domain_size, 1, size);
|
||||
@@ -140,7 +139,7 @@ impl LookUpTable {
|
||||
}
|
||||
|
||||
self.data.iter_mut().for_each(|a| {
|
||||
module.vec_znx_normalize_inplace(self.basek, a, 0, scratch.borrow());
|
||||
module.vec_znx_normalize_inplace(self.base2k, a, 0, scratch.borrow());
|
||||
});
|
||||
|
||||
self.rotate(module, -(drift as i64));
|
||||
|
||||
@@ -3,9 +3,9 @@ use poulpy_hal::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes,
|
||||
SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace,
|
||||
VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAdd, VecZnxDftAddInplace,
|
||||
VecZnxDftAllocBytes, VecZnxDftApply, VecZnxDftSubABInplace, VecZnxDftZero, VecZnxFillUniform, VecZnxIdftApply,
|
||||
VecZnxDftAllocBytes, VecZnxDftApply, VecZnxDftSubInplace, VecZnxDftZero, VecZnxFillUniform, VecZnxIdftApply,
|
||||
VecZnxIdftApplyConsume, VecZnxIdftApplyTmpBytes, VecZnxMulXpMinusOneInplace, VecZnxNormalize, VecZnxNormalizeInplace,
|
||||
VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxRotateInplaceTmpBytes, VecZnxSub, VecZnxSubABInplace,
|
||||
VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxRotateInplaceTmpBytes, VecZnxSub, VecZnxSubInplace,
|
||||
VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, ZnAddNormal,
|
||||
ZnFillUniform, ZnNormalizeInplace,
|
||||
},
|
||||
@@ -18,12 +18,13 @@ use poulpy_hal::{
|
||||
};
|
||||
|
||||
use crate::tfhe::blind_rotation::{
|
||||
BlincRotationExecute, BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyEncryptSk, BlindRotationKeyPrepared, CGGI,
|
||||
LookUpTable, cggi_blind_rotate_scratch_space, mod_switch_2n,
|
||||
BlincRotationExecute, BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyEncryptSk, BlindRotationKeyLayout,
|
||||
BlindRotationKeyPrepared, CGGI, LookUpTable, cggi_blind_rotate_scratch_space, mod_switch_2n,
|
||||
};
|
||||
|
||||
use poulpy_core::layouts::{
|
||||
GLWECiphertext, GLWEPlaintext, GLWESecret, Infos, LWECiphertext, LWECiphertextToRef, LWEPlaintext, LWESecret,
|
||||
GLWECiphertext, GLWECiphertextLayout, GLWEPlaintext, GLWESecret, LWECiphertext, LWECiphertextLayout, LWECiphertextToRef,
|
||||
LWEInfos, LWEPlaintext, LWESecret,
|
||||
prepared::{GLWESecretPrepared, PrepareAlloc},
|
||||
};
|
||||
|
||||
@@ -41,11 +42,11 @@ where
|
||||
+ VecZnxDftApply<B>
|
||||
+ VecZnxDftZero<B>
|
||||
+ SvpApplyDftToDft<B>
|
||||
+ VecZnxDftSubABInplace<B>
|
||||
+ VecZnxDftSubInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxRotate
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxSubABInplace
|
||||
+ VecZnxSubInplace
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxCopy
|
||||
@@ -83,16 +84,16 @@ where
|
||||
+ TakeVecZnxImpl<B>
|
||||
+ TakeVecZnxSliceImpl<B>,
|
||||
{
|
||||
let n: usize = module.n();
|
||||
let basek: usize = 19;
|
||||
let n_glwe: usize = module.n();
|
||||
let base2k: usize = 19;
|
||||
let k_lwe: usize = 24;
|
||||
let k_brk: usize = 3 * basek;
|
||||
let k_brk: usize = 3 * base2k;
|
||||
let rows_brk: usize = 2; // Ensures first limb is noise-free.
|
||||
let k_lut: usize = basek;
|
||||
let k_res: usize = 2 * basek;
|
||||
let k_lut: usize = base2k;
|
||||
let k_res: usize = 2 * base2k;
|
||||
let rank: usize = 1;
|
||||
|
||||
let log_message_modulus = 4;
|
||||
let log_message_modulus: usize = 4;
|
||||
|
||||
let message_modulus: usize = 1 << log_message_modulus;
|
||||
|
||||
@@ -100,30 +101,48 @@ where
|
||||
let mut source_xe: Source = Source::new([2u8; 32]);
|
||||
let mut source_xa: Source = Source::new([1u8; 32]);
|
||||
|
||||
let brk_infos: BlindRotationKeyLayout = BlindRotationKeyLayout {
|
||||
n_glwe: n_glwe.into(),
|
||||
n_lwe: n_lwe.into(),
|
||||
base2k: base2k.into(),
|
||||
k: k_brk.into(),
|
||||
rows: rows_brk.into(),
|
||||
rank: rank.into(),
|
||||
};
|
||||
|
||||
let glwe_infos: GLWECiphertextLayout = GLWECiphertextLayout {
|
||||
n: n_glwe.into(),
|
||||
base2k: base2k.into(),
|
||||
k: k_res.into(),
|
||||
rank: rank.into(),
|
||||
};
|
||||
|
||||
let lwe_infos: LWECiphertextLayout = LWECiphertextLayout {
|
||||
n: n_lwe.into(),
|
||||
k: k_lwe.into(),
|
||||
base2k: base2k.into(),
|
||||
};
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::<B>::alloc(BlindRotationKey::generate_from_sk_scratch_space(
|
||||
module, basek, k_brk, rank,
|
||||
module, &brk_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_dft: GLWESecretPrepared<Vec<u8>, B> = sk_glwe.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe);
|
||||
let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe.into());
|
||||
sk_lwe.fill_binary_block(block_size, &mut source_xs);
|
||||
|
||||
let mut scratch_br: ScratchOwned<B> = ScratchOwned::<B>::alloc(cggi_blind_rotate_scratch_space(
|
||||
module,
|
||||
block_size,
|
||||
extension_factor,
|
||||
basek,
|
||||
k_res,
|
||||
k_brk,
|
||||
rows_brk,
|
||||
rank,
|
||||
&glwe_infos,
|
||||
&brk_infos,
|
||||
));
|
||||
|
||||
let mut brk: BlindRotationKey<Vec<u8>, CGGI> =
|
||||
BlindRotationKey::<Vec<u8>, CGGI>::alloc(n, n_lwe, basek, k_brk, rows_brk, rank);
|
||||
let mut brk: BlindRotationKey<Vec<u8>, CGGI> = BlindRotationKey::<Vec<u8>, CGGI>::alloc(&brk_infos);
|
||||
|
||||
brk.encrypt_sk(
|
||||
module,
|
||||
@@ -134,13 +153,13 @@ where
|
||||
scratch.borrow(),
|
||||
);
|
||||
|
||||
let mut lwe: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe, basek, k_lwe);
|
||||
let mut lwe: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(&lwe_infos);
|
||||
|
||||
let mut pt_lwe: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe);
|
||||
let mut pt_lwe: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(&lwe_infos);
|
||||
|
||||
let x: i64 = 15 % (message_modulus as i64);
|
||||
|
||||
pt_lwe.encode_i64(x, log_message_modulus + 1);
|
||||
pt_lwe.encode_i64(x, (log_message_modulus + 1).into());
|
||||
|
||||
lwe.encrypt_sk(module, &pt_lwe, &sk_lwe, &mut source_xa, &mut source_xe);
|
||||
|
||||
@@ -152,20 +171,20 @@ where
|
||||
.enumerate()
|
||||
.for_each(|(i, x)| *x = f(i as i64));
|
||||
|
||||
let mut lut: LookUpTable = LookUpTable::alloc(module, basek, k_lut, extension_factor);
|
||||
let mut lut: LookUpTable = LookUpTable::alloc(module, base2k, k_lut, extension_factor);
|
||||
lut.set(module, &f_vec, log_message_modulus + 1);
|
||||
|
||||
let mut res: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_res, rank);
|
||||
let mut res: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_infos);
|
||||
|
||||
let brk_prepared: BlindRotationKeyPrepared<Vec<u8>, CGGI, B> = brk.prepare_alloc(module, scratch.borrow());
|
||||
|
||||
brk_prepared.execute(module, &mut res, &lwe, &lut, scratch_br.borrow());
|
||||
|
||||
let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_res);
|
||||
let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_infos);
|
||||
|
||||
res.decrypt(module, &mut pt_have, &sk_glwe_dft, scratch.borrow());
|
||||
|
||||
let mut lwe_2n: Vec<i64> = vec![0i64; lwe.n() + 1]; // TODO: from scratch space
|
||||
let mut lwe_2n: Vec<i64> = vec![0i64; (lwe.n() + 1).into()]; // TODO: from scratch space
|
||||
|
||||
mod_switch_2n(
|
||||
2 * lut.domain_size(),
|
||||
@@ -189,7 +208,7 @@ where
|
||||
assert_eq!(pt_have.data.at(0, 0), lut.data[0].at(0, 0));
|
||||
|
||||
// Verify that it effectively compute f(x)
|
||||
let mut have: i64 = pt_have.decode_coeff_i64(log_message_modulus + 1, 0);
|
||||
let mut have: i64 = pt_have.decode_coeff_i64((log_message_modulus + 1).into(), 0);
|
||||
|
||||
// Get positive representative and assert equality
|
||||
have = (have + message_modulus as i64) % (message_modulus as i64);
|
||||
|
||||
@@ -21,19 +21,19 @@ where
|
||||
+ VecZnxRotateInplaceTmpBytes,
|
||||
B: Backend + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>,
|
||||
{
|
||||
let basek: usize = 20;
|
||||
let base2k: usize = 20;
|
||||
let k_lut: usize = 40;
|
||||
let message_modulus: usize = 16;
|
||||
let extension_factor: usize = 1;
|
||||
|
||||
let log_scale: usize = basek + 1;
|
||||
let log_scale: usize = base2k + 1;
|
||||
|
||||
let mut f: Vec<i64> = vec![0i64; message_modulus];
|
||||
f.iter_mut()
|
||||
.enumerate()
|
||||
.for_each(|(i, x)| *x = (i as i64) - 8);
|
||||
|
||||
let mut lut: LookUpTable = LookUpTable::alloc(module, basek, k_lut, extension_factor);
|
||||
let mut lut: LookUpTable = LookUpTable::alloc(module, base2k, k_lut, extension_factor);
|
||||
lut.set(module, &f, log_scale);
|
||||
|
||||
let half_step: i64 = lut.domain_size().div_round(message_modulus << 1) as i64;
|
||||
@@ -42,7 +42,7 @@ where
|
||||
let step: usize = lut.domain_size().div_round(message_modulus);
|
||||
|
||||
let mut lut_dec: Vec<i64> = vec![0i64; module.n()];
|
||||
lut.data[0].decode_vec_i64(basek, 0, log_scale, &mut lut_dec);
|
||||
lut.data[0].decode_vec_i64(base2k, 0, log_scale, &mut lut_dec);
|
||||
|
||||
(0..lut.domain_size()).step_by(step).for_each(|i| {
|
||||
(0..step).for_each(|_| {
|
||||
@@ -61,19 +61,19 @@ where
|
||||
+ VecZnxRotateInplaceTmpBytes,
|
||||
B: Backend + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>,
|
||||
{
|
||||
let basek: usize = 20;
|
||||
let base2k: usize = 20;
|
||||
let k_lut: usize = 40;
|
||||
let message_modulus: usize = 16;
|
||||
let extension_factor: usize = 4;
|
||||
|
||||
let log_scale: usize = basek + 1;
|
||||
let log_scale: usize = base2k + 1;
|
||||
|
||||
let mut f: Vec<i64> = vec![0i64; message_modulus];
|
||||
f.iter_mut()
|
||||
.enumerate()
|
||||
.for_each(|(i, x)| *x = (i as i64) - 8);
|
||||
|
||||
let mut lut: LookUpTable = LookUpTable::alloc(module, basek, k_lut, extension_factor);
|
||||
let mut lut: LookUpTable = LookUpTable::alloc(module, base2k, k_lut, extension_factor);
|
||||
lut.set(module, &f, log_scale);
|
||||
|
||||
let half_step: i64 = lut.domain_size().div_round(message_modulus << 1) as i64;
|
||||
@@ -84,7 +84,7 @@ where
|
||||
let mut lut_dec: Vec<i64> = vec![0i64; module.n()];
|
||||
|
||||
(0..extension_factor).for_each(|ext| {
|
||||
lut.data[ext].decode_vec_i64(basek, 0, log_scale, &mut lut_dec);
|
||||
lut.data[ext].decode_vec_i64(base2k, 0, log_scale, &mut lut_dec);
|
||||
(0..module.n()).step_by(step).for_each(|i| {
|
||||
(0..step).for_each(|_| {
|
||||
assert_eq!(f[i / step] % message_modulus as i64, lut_dec[i]);
|
||||
|
||||
@@ -1,15 +1,35 @@
|
||||
use poulpy_hal::test_suite::serialization::test_reader_writer_interface;
|
||||
|
||||
use crate::tfhe::blind_rotation::{BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyCompressed, CGGI};
|
||||
use crate::tfhe::blind_rotation::{
|
||||
BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyCompressed, BlindRotationKeyLayout, CGGI,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_cggi_blind_rotation_key_serialization() {
|
||||
let original: BlindRotationKey<Vec<u8>, CGGI> = BlindRotationKey::alloc(256, 64, 12, 54, 2, 2);
|
||||
let layout: BlindRotationKeyLayout = BlindRotationKeyLayout {
|
||||
n_glwe: 256_u32.into(),
|
||||
n_lwe: 64_usize.into(),
|
||||
base2k: 12_usize.into(),
|
||||
k: 54_usize.into(),
|
||||
rows: 2_usize.into(),
|
||||
rank: 2_usize.into(),
|
||||
};
|
||||
|
||||
let original: BlindRotationKey<Vec<u8>, CGGI> = BlindRotationKey::alloc(&layout);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cggi_blind_rotation_key_compressed_serialization() {
|
||||
let original: BlindRotationKeyCompressed<Vec<u8>, CGGI> = BlindRotationKeyCompressed::alloc(256, 64, 12, 54, 2, 2);
|
||||
let layout: BlindRotationKeyLayout = BlindRotationKeyLayout {
|
||||
n_glwe: 256_u32.into(),
|
||||
n_lwe: 64_usize.into(),
|
||||
base2k: 12_usize.into(),
|
||||
k: 54_usize.into(),
|
||||
rows: 2_usize.into(),
|
||||
rank: 2_usize.into(),
|
||||
};
|
||||
|
||||
let original: BlindRotationKeyCompressed<Vec<u8>, CGGI> = BlindRotationKeyCompressed::alloc(&layout);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user