mirror of
https://github.com/arnaucube/poulpy.git
synced 2026-02-10 05:06:44 +01:00
fix blind rotation
This commit is contained in:
@@ -4,6 +4,7 @@ use poulpy_hal::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
GetDistribution,
|
||||
dist::Distribution,
|
||||
layouts::{Base2K, Degree, LWEInfos, TorusPrecision},
|
||||
};
|
||||
@@ -22,6 +23,12 @@ impl LWESecret<Vec<u8>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GetDistribution for LWESecret<D> {
|
||||
fn dist(&self) -> &Distribution {
|
||||
&self.dist
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> LWESecret<D> {
|
||||
pub fn raw(&self) -> &[i64] {
|
||||
self.data.at(0, 0)
|
||||
|
||||
@@ -23,9 +23,8 @@ pub use external_product::*;
|
||||
pub use glwe_packing::*;
|
||||
pub use keyswitching::*;
|
||||
pub use noise::*;
|
||||
pub use scratch::*;
|
||||
|
||||
pub use encryption::SIGMA;
|
||||
|
||||
pub use scratch::*;
|
||||
|
||||
pub mod tests;
|
||||
|
||||
@@ -217,6 +217,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<BE: Backend> GLWEMulXpMinusOne<BE> for Module<BE> where Self: ModuleN + VecZnxMulXpMinusOne + VecZnxMulXpMinusOneInplace<BE> {}
|
||||
|
||||
pub trait GLWEMulXpMinusOne<BE: Backend>
|
||||
where
|
||||
Self: ModuleN + VecZnxMulXpMinusOne + VecZnxMulXpMinusOneInplace<BE>,
|
||||
|
||||
@@ -34,13 +34,9 @@ pub trait ScratchTakeBasic
|
||||
where
|
||||
Self: TakeSlice,
|
||||
{
|
||||
fn take_scalar_znx(&mut self, n: usize, cols: usize) -> (ScalarZnx<&mut [u8]>, &mut Self)
|
||||
{
|
||||
fn take_scalar_znx(&mut self, n: usize, cols: usize) -> (ScalarZnx<&mut [u8]>, &mut Self) {
|
||||
let (take_slice, rem_slice) = self.take_slice(ScalarZnx::bytes_of(n, cols));
|
||||
(
|
||||
ScalarZnx::from_data(take_slice, n, cols),
|
||||
rem_slice,
|
||||
)
|
||||
(ScalarZnx::from_data(take_slice, n, cols), rem_slice)
|
||||
}
|
||||
|
||||
fn take_svp_ppol<M, B: Backend>(&mut self, module: &M, cols: usize) -> (SvpPPol<&mut [u8], B>, &mut Self)
|
||||
@@ -53,10 +49,7 @@ where
|
||||
|
||||
fn take_vec_znx(&mut self, n: usize, cols: usize, size: usize) -> (VecZnx<&mut [u8]>, &mut Self) {
|
||||
let (take_slice, rem_slice) = self.take_slice(VecZnx::bytes_of(n, cols, size));
|
||||
(
|
||||
VecZnx::from_data(take_slice, n, cols, size),
|
||||
rem_slice,
|
||||
)
|
||||
(VecZnx::from_data(take_slice, n, cols, size), rem_slice)
|
||||
}
|
||||
|
||||
fn take_vec_znx_big<M, B: Backend>(&mut self, module: &M, cols: usize, size: usize) -> (VecZnxBig<&mut [u8], B>, &mut Self)
|
||||
@@ -102,7 +95,7 @@ where
|
||||
(slice, scratch)
|
||||
}
|
||||
|
||||
fn take_vec_znx_slice(&mut self, n: usize, len: usize, cols: usize, size: usize) -> (Vec<VecZnx<&mut [u8]>>, &mut Self){
|
||||
fn take_vec_znx_slice(&mut self, len: usize, n: usize, cols: usize, size: usize) -> (Vec<VecZnx<&mut [u8]>>, &mut Self) {
|
||||
let mut scratch: &mut Self = self;
|
||||
let mut slice: Vec<VecZnx<&mut [u8]>> = Vec::with_capacity(len);
|
||||
for _ in 0..len {
|
||||
@@ -138,8 +131,7 @@ where
|
||||
cols_in: usize,
|
||||
cols_out: usize,
|
||||
size: usize,
|
||||
) -> (MatZnx<&mut [u8]>, &mut Self)
|
||||
{
|
||||
) -> (MatZnx<&mut [u8]>, &mut Self) {
|
||||
let (take_slice, rem_slice) = self.take_slice(MatZnx::bytes_of(n, rows, cols_in, cols_out, size));
|
||||
(
|
||||
MatZnx::from_data(take_slice, n, rows, cols_in, cols_out, size),
|
||||
|
||||
@@ -2,17 +2,19 @@ use std::marker::PhantomData;
|
||||
|
||||
use poulpy_core::layouts::{Base2K, GLWE, GLWEInfos, GLWEPlaintextLayout, LWEInfos, Rank, TorusPrecision};
|
||||
|
||||
use poulpy_core::{TakeGLWEPlaintext, layouts::prepared::GLWESecretPrepared};
|
||||
#[cfg(test)]
|
||||
use poulpy_core::ScratchTakeCore;
|
||||
use poulpy_core::{layouts::prepared::GLWESecretPrepared};
|
||||
use poulpy_hal::api::VecZnxBigBytesOf;
|
||||
#[cfg(test)]
|
||||
use poulpy_hal::api::{
|
||||
ScratchAvailable, TakeVecZnx, VecZnxAddInplace, VecZnxAddNormal, VecZnxFillUniform, VecZnxNormalize, VecZnxSub,
|
||||
VecZnxAddInplace, VecZnxAddNormal, VecZnxFillUniform, VecZnxNormalize, VecZnxSub,
|
||||
};
|
||||
#[cfg(test)]
|
||||
use poulpy_hal::source::Source;
|
||||
use poulpy_hal::{
|
||||
api::{
|
||||
TakeVecZnxBig, TakeVecZnxDft, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxDftApply,
|
||||
VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxDftApply,
|
||||
VecZnxDftBytesOf, VecZnxIdftApplyConsume, VecZnxNormalizeTmpBytes,
|
||||
},
|
||||
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch},
|
||||
@@ -96,7 +98,7 @@ impl<D: DataMut, T: UnsignedInteger + ToBits> FheUintBlocks<D, T> {
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<BE>
|
||||
+ VecZnxSub,
|
||||
Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx + TakeGLWEPlaintext<BE>,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
use poulpy_core::layouts::GLWEPlaintextLayout;
|
||||
|
||||
@@ -136,7 +138,7 @@ impl<D: DataRef, T: UnsignedInteger + FromBits + ToBits> FheUintBlocks<D, T> {
|
||||
+ VecZnxBigAddInplace<BE>
|
||||
+ VecZnxBigAddSmallInplace<BE>
|
||||
+ VecZnxBigNormalize<BE>,
|
||||
Scratch<BE>: TakeVecZnxDft<BE> + TakeVecZnxBig<BE> + TakeGLWEPlaintext<BE>,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
@@ -186,7 +188,7 @@ impl<D: DataRef, T: UnsignedInteger + FromBits + ToBits> FheUintBlocks<D, T> {
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxSubInplace
|
||||
+ VecZnxNormalizeInplace<BE>,
|
||||
Scratch<BE>: TakeGLWEPlaintext<BE> + TakeVecZnxDft<BE> + TakeVecZnxBig<BE>,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
|
||||
@@ -144,7 +144,7 @@ impl<D: DataMut, T: UnsignedInteger + ToBits, BE: Backend> FheUintBlocksPrep<D,
|
||||
assert_eq!(sk.n(), module.n() as u32);
|
||||
}
|
||||
|
||||
let (mut tmp_ggsw, scratch_1) = scratch.take_ggsw(module, self);
|
||||
let (mut tmp_ggsw, scratch_1) = scratch.take_ggsw(self);
|
||||
let (mut pt, scratch_2) = scratch_1.take_scalar_znx(module.n(), 1);
|
||||
|
||||
for i in 0..T::WORD_SIZE {
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
use itertools::Itertools;
|
||||
use poulpy_core::{
|
||||
GLWEOperations, TakeGLWEPlaintext, TakeGLWESlice, glwe_packing,
|
||||
layouts::{
|
||||
GLWE, GLWEInfos, GLWEPlaintextLayout, LWEInfos, TorusPrecision,
|
||||
prepared::{GLWEAutomorphismKeyPrepared, GLWESecretPrepared},
|
||||
},
|
||||
prepared::{GLWEAutomorphismKeyPrepared, GLWESecretPrepared}, GLWEInfos, GLWEPlaintextLayout, LWEInfos, TorusPrecision, GLWE
|
||||
}, ScratchTakeCore,
|
||||
};
|
||||
use poulpy_hal::{
|
||||
api::{
|
||||
ScratchAvailable, SvpApplyDftToDftInplace, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal,
|
||||
ScratchAvailable, SvpApplyDftToDftInplace, VecZnxAddInplace, VecZnxAddNormal,
|
||||
VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace,
|
||||
VecZnxBigAutomorphismInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallNegateInplace, VecZnxCopy,
|
||||
VecZnxDftApply, VecZnxDftBytesOf, VecZnxDftCopy, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA,
|
||||
@@ -62,7 +60,7 @@ impl<D: DataMut, T: UnsignedInteger> FheUintWord<D, T> {
|
||||
+ VecZnxAutomorphismInplace<BE>
|
||||
+ VecZnxBigSubSmallNegateInplace<BE>
|
||||
+ VecZnxRotate,
|
||||
Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx + TakeGLWESlice,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
// Repacks the GLWE ciphertexts bits
|
||||
let gap: usize = module.n() / T::WORD_SIZE;
|
||||
@@ -122,7 +120,7 @@ impl<D: DataMut, T: UnsignedInteger + ToBits> FheUintWord<D, T> {
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<BE>
|
||||
+ VecZnxSub,
|
||||
Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx + TakeGLWEPlaintext<BE>,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
@@ -167,7 +165,7 @@ impl<D: DataRef, T: UnsignedInteger + FromBits> FheUintWord<D, T> {
|
||||
+ VecZnxBigAddInplace<BE>
|
||||
+ VecZnxBigAddSmallInplace<BE>
|
||||
+ VecZnxBigNormalize<BE>,
|
||||
Scratch<BE>: TakeVecZnxDft<BE> + TakeVecZnxBig<BE> + TakeGLWEPlaintext<BE>,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
use itertools::Itertools;
|
||||
use poulpy_core::{
|
||||
GLWEExternalProductInplace, GLWEOperations, TakeGLWESlice,
|
||||
layouts::{
|
||||
GLWE, GLWEToMut, LWEInfos,
|
||||
prepared::{GGSWPrepared, GGSWPreparedToRef},
|
||||
},
|
||||
prepared::{GGSWPrepared, GGSWPreparedToRef}, GLWEToMut, LWEInfos, GLWE
|
||||
}, GLWEExternalProduct, ScratchTakeCore
|
||||
};
|
||||
use poulpy_hal::{
|
||||
api::{VecZnxAddInplace, VecZnxCopy, VecZnxNegateInplace, VecZnxSub},
|
||||
@@ -49,7 +47,7 @@ impl<C: BitCircuitInfo, const N: usize, T: UnsignedInteger, BE: Backend> Circuit
|
||||
where
|
||||
Self: GetBitCircuitInfo<T>,
|
||||
Module<BE>: Cmux<BE> + VecZnxCopy,
|
||||
Scratch<BE>: TakeGLWESlice,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
fn execute<O>(
|
||||
&self,
|
||||
@@ -169,7 +167,7 @@ pub trait Cmux<BE: Backend> {
|
||||
|
||||
impl<BE: Backend> Cmux<BE> for Module<BE>
|
||||
where
|
||||
Module<BE>: GLWEExternalProductInplace<BE> + VecZnxSub + VecZnxCopy + VecZnxNegateInplace + VecZnxAddInplace,
|
||||
Module<BE>: GLWEExternalProduct<BE> + VecZnxSub + VecZnxCopy + VecZnxNegateInplace + VecZnxAddInplace,
|
||||
{
|
||||
fn cmux<O, T, F, S>(&self, out: &mut GLWE<O>, t: &GLWE<T>, f: &GLWE<F>, s: &GGSWPrepared<S, BE>, scratch: &mut Scratch<BE>)
|
||||
where
|
||||
|
||||
@@ -9,16 +9,13 @@ use crate::tfhe::{
|
||||
},
|
||||
};
|
||||
use poulpy_core::{
|
||||
TakeGGSW, TakeGLWE,
|
||||
layouts::{
|
||||
GLWESecret, GLWEToLWEKeyLayout, GLWEToLWESwitchingKey, LWE, LWESecret,
|
||||
prepared::{GLWEToLWESwitchingKeyPrepared, Prepare, PrepareAlloc},
|
||||
},
|
||||
prepared::GLWEToLWESwitchingKeyPrepared, GLWESecret, GLWEToLWEKeyLayout, GLWEToLWESwitchingKey, LWESecret
|
||||
}, ScratchTakeCore,
|
||||
};
|
||||
use poulpy_hal::{
|
||||
api::{
|
||||
ScratchAvailable, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, TakeScalarZnx,
|
||||
TakeSvpPPol, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace,
|
||||
ScratchAvailable, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace,
|
||||
VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes,
|
||||
VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize,
|
||||
VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing,
|
||||
@@ -96,7 +93,7 @@ impl<BRA: BlindRotationAlgo> BDDKey<Vec<u8>, Vec<u8>, BRA> {
|
||||
+ SvpPPolAlloc<BE>
|
||||
+ VecZnxAutomorphism
|
||||
+ VecZnxAutomorphismInplace<BE>,
|
||||
Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx + TakeScalarZnx + TakeSvpPPol<BE> + TakeVecZnxBig<BE>,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
let mut ks: GLWEToLWESwitchingKey<Vec<u8>> = GLWEToLWESwitchingKey::alloc(&infos.ks_infos());
|
||||
ks.encrypt_sk(module, sk_lwe, sk_glwe, source_xa, source_xe, scratch);
|
||||
@@ -217,7 +214,7 @@ where
|
||||
+ VecZnxBigNormalize<BE>
|
||||
+ VecZnxNormalize<BE>
|
||||
+ VecZnxNormalizeTmpBytes,
|
||||
Scratch<BE>: ScratchAvailable + TakeVecZnxDft<BE> + TakeGLWE + TakeVecZnx + TakeGGSW,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
CircuitBootstrappingKeyPrepared<CBT, BRA, BE>: CirtuitBootstrappingExecute<BE>,
|
||||
{
|
||||
fn prepare(
|
||||
|
||||
@@ -1,56 +1,71 @@
|
||||
use itertools::izip;
|
||||
use poulpy_hal::{
|
||||
api::{
|
||||
ScratchAvailable, SvpApplyDftToDft, SvpPPolBytesOf, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, TakeVecZnxDftSlice,
|
||||
TakeVecZnxSlice, VecZnxAddInplace, VecZnxBigAddSmallInplace, VecZnxBigBytesOf, VecZnxBigNormalize,
|
||||
VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAdd, VecZnxDftAddInplace, VecZnxDftApply, VecZnxDftBytesOf,
|
||||
VecZnxDftSubInplace, VecZnxDftZero, VecZnxIdftApply, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpBytes,
|
||||
VecZnxMulXpMinusOneInplace, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate,
|
||||
VecZnxSubInplace, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes,
|
||||
ModuleN, ScratchTakeBasic, SvpApplyDftToDft, VecZnxBigAddSmallInplace, VecZnxBigBytesOf, VecZnxBigNormalize,
|
||||
VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAddInplace, VecZnxDftApply, VecZnxDftBytesOf, VecZnxDftSubInplace,
|
||||
VecZnxDftZero, VecZnxIdftApply, VecZnxIdftApplyTmpBytes, VecZnxRotate, VmpApplyDftToDft, VmpApplyDftToDftTmpBytes,
|
||||
},
|
||||
layouts::{Backend, DataMut, DataRef, Module, Scratch, SvpPPol, VecZnx, ZnxView, ZnxZero},
|
||||
layouts::{Backend, DataMut, DataRef, Module, Scratch, SvpPPol, VecZnx, ZnxZero},
|
||||
};
|
||||
|
||||
use poulpy_core::{
|
||||
Distribution, GLWEOperations, TakeGLWE,
|
||||
Distribution, GLWEAdd, GLWEExternalProduct, GLWEMulXpMinusOne, GLWENormalize, ScratchTakeCore,
|
||||
layouts::{GGSWInfos, GLWE, GLWEInfos, GLWEToMut, LWE, LWEInfos, LWEToRef},
|
||||
};
|
||||
|
||||
use crate::tfhe::blind_rotation::{
|
||||
BlincRotationExecute, BlindRotationKeyInfos, BlindRotationKeyPrepared, CGGI, LookUpTable, LookUpTableRotationDirection,
|
||||
BlindRotationExecute, BlindRotationKeyInfos, BlindRotationKeyPrepared, CGGI, LookupTable, mod_switch_2n,
|
||||
};
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn cggi_blind_rotate_tmp_bytes<B: Backend, OUT, GGSW>(
|
||||
module: &Module<B>,
|
||||
impl<BE: Backend> BlindRotationExecute<CGGI, BE> for Module<BE>
|
||||
where
|
||||
Self: VecZnxDftBytesOf
|
||||
+ VecZnxBigBytesOf
|
||||
+ VmpApplyDftToDftTmpBytes
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxIdftApplyTmpBytes
|
||||
+ GLWEExternalProduct<BE>
|
||||
+ ModuleN
|
||||
+ VecZnxRotate
|
||||
+ VecZnxDftApply<BE>
|
||||
+ VecZnxDftZero<BE>
|
||||
+ VmpApplyDftToDft<BE>
|
||||
+ SvpApplyDftToDft<BE>
|
||||
+ VecZnxDftAddInplace<BE>
|
||||
+ VecZnxDftSubInplace<BE>
|
||||
+ VecZnxIdftApply<BE>
|
||||
+ VecZnxBigAddSmallInplace<BE>
|
||||
+ VecZnxBigNormalize<BE>
|
||||
+ VecZnxCopy
|
||||
+ GLWEMulXpMinusOne<BE>
|
||||
+ GLWEAdd
|
||||
+ GLWENormalize<BE>,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
fn blind_rotation_execute_tmp_bytes<G, B>(
|
||||
&self,
|
||||
block_size: usize,
|
||||
extension_factor: usize,
|
||||
glwe_infos: &OUT,
|
||||
brk_infos: &GGSW,
|
||||
glwe_infos: &G,
|
||||
brk_infos: &B,
|
||||
) -> usize
|
||||
where
|
||||
OUT: GLWEInfos,
|
||||
GGSW: GGSWInfos,
|
||||
Module<B>: VecZnxDftBytesOf
|
||||
+ VmpApplyDftToDftTmpBytes
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxBigBytesOf
|
||||
+ VecZnxIdftApplyTmpBytes
|
||||
+ VecZnxBigNormalizeTmpBytes,
|
||||
G: GLWEInfos,
|
||||
B: GGSWInfos,
|
||||
{
|
||||
let brk_size: usize = brk_infos.size();
|
||||
|
||||
if block_size > 1 {
|
||||
let cols: usize = (brk_infos.rank() + 1).into();
|
||||
let dnum: usize = brk_infos.dnum().into();
|
||||
let acc_dft: usize = module.bytes_of_vec_znx_dft(cols, dnum) * extension_factor;
|
||||
let acc_big: usize = module.bytes_of_vec_znx_big(1, brk_size);
|
||||
let vmp_res: usize = module.bytes_of_vec_znx_dft(cols, brk_size) * extension_factor;
|
||||
let vmp_xai: usize = module.bytes_of_vec_znx_dft(1, brk_size);
|
||||
let acc_dft: usize = self.bytes_of_vec_znx_dft(cols, dnum) * extension_factor;
|
||||
let acc_big: usize = self.bytes_of_vec_znx_big(1, brk_size);
|
||||
let vmp_res: usize = self.bytes_of_vec_znx_dft(cols, brk_size) * extension_factor;
|
||||
let vmp_xai: usize = self.bytes_of_vec_znx_dft(1, brk_size);
|
||||
let acc_dft_add: usize = vmp_res;
|
||||
let vmp: usize = module.vmp_apply_dft_to_dft_tmp_bytes(brk_size, dnum, dnum, 2, 2, brk_size); // GGSW product: (1 x 2) x (2 x 2)
|
||||
let vmp: usize = self.vmp_apply_dft_to_dft_tmp_bytes(brk_size, dnum, dnum, 2, 2, brk_size); // GGSW product: (1 x 2) x (2 x 2)
|
||||
let acc: usize = if extension_factor > 1 {
|
||||
VecZnx::bytes_of(module.n(), cols, glwe_infos.size()) * extension_factor
|
||||
VecZnx::bytes_of(self.n(), cols, glwe_infos.size()) * extension_factor
|
||||
} else {
|
||||
0
|
||||
};
|
||||
@@ -59,100 +74,69 @@ where
|
||||
+ acc_dft_add
|
||||
+ vmp_res
|
||||
+ vmp_xai
|
||||
+ (vmp | (acc_big + (module.vec_znx_big_normalize_tmp_bytes() | module.vec_znx_idft_apply_tmp_bytes())))
|
||||
+ (vmp
|
||||
| (acc_big
|
||||
+ (self
|
||||
.vec_znx_big_normalize_tmp_bytes()
|
||||
.max(self.vec_znx_idft_apply_tmp_bytes()))))
|
||||
} else {
|
||||
GLWE::bytes_of(glwe_infos) + GLWE::external_product_inplace_tmp_bytes(module, glwe_infos, brk_infos)
|
||||
GLWE::bytes_of_from_infos(glwe_infos) + GLWE::external_product_tmp_bytes(self, glwe_infos, glwe_infos, brk_infos)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> BlincRotationExecute<B> for BlindRotationKeyPrepared<D, CGGI, B>
|
||||
where
|
||||
Module<B>: VecZnxBigBytesOf
|
||||
+ VecZnxDftBytesOf
|
||||
+ SvpPPolBytesOf
|
||||
+ VmpApplyDftToDftTmpBytes
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxIdftApplyTmpBytes
|
||||
+ VecZnxIdftApply<B>
|
||||
+ VecZnxDftAdd<B>
|
||||
+ VecZnxDftAddInplace<B>
|
||||
+ VecZnxDftApply<B>
|
||||
+ VecZnxDftZero<B>
|
||||
+ SvpApplyDftToDft<B>
|
||||
+ VecZnxDftSubInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxRotate
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxSubInplace
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxCopy
|
||||
+ VecZnxMulXpMinusOneInplace<B>
|
||||
+ VmpApplyDftToDft<B>
|
||||
+ VmpApplyDftToDftAdd<B>
|
||||
+ VecZnxIdftApplyConsume<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxNormalizeTmpBytes,
|
||||
Scratch<B>: TakeVecZnxDftSlice<B> + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnxSlice + TakeVecZnx + ScratchAvailable,
|
||||
{
|
||||
fn execute<DR: DataMut, DI: DataRef>(
|
||||
fn blind_rotation_execute<DR, DL, DB>(
|
||||
&self,
|
||||
module: &Module<B>,
|
||||
res: &mut GLWE<DR>,
|
||||
lwe: &LWE<DI>,
|
||||
lut: &LookUpTable,
|
||||
scratch: &mut Scratch<B>,
|
||||
) {
|
||||
match self.dist {
|
||||
lwe: &LWE<DL>,
|
||||
lut: &LookupTable,
|
||||
brk: &BlindRotationKeyPrepared<DB, CGGI, BE>,
|
||||
scratch: &mut Scratch<BE>,
|
||||
) where
|
||||
DR: DataMut,
|
||||
DL: DataRef,
|
||||
DB: DataRef,
|
||||
{
|
||||
match brk.dist {
|
||||
Distribution::BinaryBlock(_) | Distribution::BinaryFixed(_) | Distribution::BinaryProb(_) | Distribution::ZERO => {
|
||||
if lut.extension_factor() > 1 {
|
||||
execute_block_binary_extended(module, res, lwe, lut, self, scratch)
|
||||
} else if self.block_size() > 1 {
|
||||
execute_block_binary(module, res, lwe, lut, self, scratch);
|
||||
execute_block_binary_extended(self, res, lwe, lut, brk, scratch)
|
||||
} else if brk.block_size() > 1 {
|
||||
execute_block_binary(self, res, lwe, lut, brk, scratch);
|
||||
} else {
|
||||
execute_standard(module, res, lwe, lut, self, scratch);
|
||||
execute_standard(self, res, lwe, lut, brk, scratch);
|
||||
}
|
||||
}
|
||||
_ => panic!("invalid CGGI distribution"),
|
||||
_ => panic!("invalid CGGI distribution (have you prepared the key?)"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn execute_block_binary_extended<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
module: &Module<B>,
|
||||
fn execute_block_binary_extended<DataRes, DataIn, DataBrk, M, BE: Backend>(
|
||||
module: &M,
|
||||
res: &mut GLWE<DataRes>,
|
||||
lwe: &LWE<DataIn>,
|
||||
lut: &LookUpTable,
|
||||
brk: &BlindRotationKeyPrepared<DataBrk, CGGI, B>,
|
||||
scratch: &mut Scratch<B>,
|
||||
lut: &LookupTable,
|
||||
brk: &BlindRotationKeyPrepared<DataBrk, CGGI, BE>,
|
||||
scratch: &mut Scratch<BE>,
|
||||
) where
|
||||
DataRes: DataMut,
|
||||
DataIn: DataRef,
|
||||
DataBrk: DataRef,
|
||||
Module<B>: VecZnxBigBytesOf
|
||||
+ VecZnxDftBytesOf
|
||||
+ SvpPPolBytesOf
|
||||
+ VmpApplyDftToDftTmpBytes
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxIdftApplyTmpBytes
|
||||
+ VecZnxIdftApply<B>
|
||||
+ VecZnxDftAdd<B>
|
||||
+ VecZnxDftAddInplace<B>
|
||||
+ VecZnxDftApply<B>
|
||||
+ VecZnxDftZero<B>
|
||||
+ SvpApplyDftToDft<B>
|
||||
+ VecZnxDftSubInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
M: VecZnxDftBytesOf
|
||||
+ ModuleN
|
||||
+ VecZnxRotate
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxSubInplace
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxDftApply<BE>
|
||||
+ VecZnxDftZero<BE>
|
||||
+ VmpApplyDftToDft<BE>
|
||||
+ SvpApplyDftToDft<BE>
|
||||
+ VecZnxDftAddInplace<BE>
|
||||
+ VecZnxDftSubInplace<BE>
|
||||
+ VecZnxIdftApply<BE>
|
||||
+ VecZnxBigAddSmallInplace<BE>
|
||||
+ VecZnxBigNormalize<BE>
|
||||
+ VecZnxCopy
|
||||
+ VecZnxMulXpMinusOneInplace<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VmpApplyDftToDft<B>,
|
||||
Scratch<B>: TakeVecZnxDftSlice<B> + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnxSlice + ScratchAvailable + TakeVecZnx,
|
||||
+ VecZnxBigBytesOf,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
let n_glwe: usize = brk.n_glwe().into();
|
||||
let extension_factor: usize = lut.extension_factor();
|
||||
@@ -161,16 +145,16 @@ fn execute_block_binary_extended<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
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, dnum);
|
||||
let (mut vmp_res, scratch_3) = scratch_2.take_vec_znx_dft_slice(extension_factor, n_glwe, cols, brk.size());
|
||||
let (mut acc_add_dft, scratch_4) = scratch_3.take_vec_znx_dft_slice(extension_factor, n_glwe, cols, brk.size());
|
||||
let (mut vmp_xai, scratch_5) = scratch_4.take_vec_znx_dft(n_glwe, 1, brk.size());
|
||||
let (mut acc_dft, scratch_2) = scratch_1.take_vec_znx_dft_slice(module, extension_factor, cols, dnum);
|
||||
let (mut vmp_res, scratch_3) = scratch_2.take_vec_znx_dft_slice(module, extension_factor, cols, brk.size());
|
||||
let (mut acc_add_dft, scratch_4) = scratch_3.take_vec_znx_dft_slice(module, extension_factor, cols, brk.size());
|
||||
let (mut vmp_xai, scratch_5) = scratch_4.take_vec_znx_dft(module, 1, brk.size());
|
||||
|
||||
(0..extension_factor).for_each(|i| {
|
||||
acc[i].zero();
|
||||
});
|
||||
|
||||
let x_pow_a: &Vec<SvpPPol<Vec<u8>, B>>;
|
||||
let x_pow_a: &Vec<SvpPPol<Vec<u8>, BE>>;
|
||||
if let Some(b) = &brk.x_pow_a {
|
||||
x_pow_a = b
|
||||
} else {
|
||||
@@ -268,7 +252,7 @@ fn execute_block_binary_extended<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
});
|
||||
|
||||
{
|
||||
let (mut acc_add_big, scratch7) = scratch_5.take_vec_znx_big(n_glwe, 1, brk.size());
|
||||
let (mut acc_add_big, scratch7) = scratch_5.take_vec_znx_big(module, 1, brk.size());
|
||||
|
||||
(0..extension_factor).for_each(|j| {
|
||||
(0..cols).for_each(|i| {
|
||||
@@ -285,41 +269,32 @@ fn execute_block_binary_extended<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
});
|
||||
}
|
||||
|
||||
fn execute_block_binary<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
module: &Module<B>,
|
||||
fn execute_block_binary<DataRes, DataIn, DataBrk, M, BE: Backend>(
|
||||
module: &M,
|
||||
res: &mut GLWE<DataRes>,
|
||||
lwe: &LWE<DataIn>,
|
||||
lut: &LookUpTable,
|
||||
brk: &BlindRotationKeyPrepared<DataBrk, CGGI, B>,
|
||||
scratch: &mut Scratch<B>,
|
||||
lut: &LookupTable,
|
||||
brk: &BlindRotationKeyPrepared<DataBrk, CGGI, BE>,
|
||||
scratch: &mut Scratch<BE>,
|
||||
) where
|
||||
DataRes: DataMut,
|
||||
DataIn: DataRef,
|
||||
DataBrk: DataRef,
|
||||
Module<B>: VecZnxBigBytesOf
|
||||
+ VecZnxDftBytesOf
|
||||
+ SvpPPolBytesOf
|
||||
+ VmpApplyDftToDftTmpBytes
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxIdftApplyTmpBytes
|
||||
+ VecZnxIdftApply<B>
|
||||
+ VecZnxDftAdd<B>
|
||||
+ VecZnxDftAddInplace<B>
|
||||
+ VecZnxDftApply<B>
|
||||
+ VecZnxDftZero<B>
|
||||
+ SvpApplyDftToDft<B>
|
||||
+ VecZnxDftSubInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
M: VecZnxDftBytesOf
|
||||
+ ModuleN
|
||||
+ VecZnxRotate
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxSubInplace
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxDftApply<BE>
|
||||
+ VecZnxDftZero<BE>
|
||||
+ VmpApplyDftToDft<BE>
|
||||
+ SvpApplyDftToDft<BE>
|
||||
+ VecZnxDftAddInplace<BE>
|
||||
+ VecZnxDftSubInplace<BE>
|
||||
+ VecZnxIdftApply<BE>
|
||||
+ VecZnxBigAddSmallInplace<BE>
|
||||
+ VecZnxBigNormalize<BE>
|
||||
+ VecZnxCopy
|
||||
+ VecZnxMulXpMinusOneInplace<B>
|
||||
+ VmpApplyDftToDft<B>
|
||||
+ VecZnxBigNormalize<B>,
|
||||
Scratch<B>: TakeVecZnxDftSlice<B> + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnxSlice + ScratchAvailable + TakeVecZnx,
|
||||
+ VecZnxBigBytesOf,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
let n_glwe: usize = brk.n_glwe().into();
|
||||
let mut lwe_2n: Vec<i64> = vec![0i64; (lwe.n() + 1).into()]; // TODO: from scratch space
|
||||
@@ -350,12 +325,12 @@ fn execute_block_binary<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
|
||||
// ACC + [sum DFT(X^ai -1) * (DFT(ACC) x BRKi)]
|
||||
|
||||
let (mut acc_dft, scratch_1) = scratch.take_vec_znx_dft(n_glwe, cols, dnum);
|
||||
let (mut vmp_res, scratch_2) = scratch_1.take_vec_znx_dft(n_glwe, cols, brk.size());
|
||||
let (mut acc_add_dft, scratch_3) = scratch_2.take_vec_znx_dft(n_glwe, cols, brk.size());
|
||||
let (mut vmp_xai, scratch_4) = scratch_3.take_vec_znx_dft(n_glwe, 1, brk.size());
|
||||
let (mut acc_dft, scratch_1) = scratch.take_vec_znx_dft(module, cols, dnum);
|
||||
let (mut vmp_res, scratch_2) = scratch_1.take_vec_znx_dft(module, cols, brk.size());
|
||||
let (mut acc_add_dft, scratch_3) = scratch_2.take_vec_znx_dft(module, cols, brk.size());
|
||||
let (mut vmp_xai, scratch_4) = scratch_3.take_vec_znx_dft(module, 1, brk.size());
|
||||
|
||||
let x_pow_a: &Vec<SvpPPol<Vec<u8>, B>>;
|
||||
let x_pow_a: &Vec<SvpPPol<Vec<u8>, BE>>;
|
||||
if let Some(b) = &brk.x_pow_a {
|
||||
x_pow_a = b
|
||||
} else {
|
||||
@@ -388,7 +363,7 @@ fn execute_block_binary<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
});
|
||||
|
||||
{
|
||||
let (mut acc_add_big, scratch_5) = scratch_4.take_vec_znx_big(n_glwe, 1, brk.size());
|
||||
let (mut acc_add_big, scratch_5) = scratch_4.take_vec_znx_big(module, 1, brk.size());
|
||||
|
||||
(0..cols).for_each(|i| {
|
||||
module.vec_znx_idft_apply(&mut acc_add_big, 0, &acc_add_dft, i, scratch_5);
|
||||
@@ -407,44 +382,19 @@ fn execute_block_binary<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
});
|
||||
}
|
||||
|
||||
fn execute_standard<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
module: &Module<B>,
|
||||
fn execute_standard<DataRes, DataIn, DataBrk, M, BE: Backend>(
|
||||
module: &M,
|
||||
res: &mut GLWE<DataRes>,
|
||||
lwe: &LWE<DataIn>,
|
||||
lut: &LookUpTable,
|
||||
brk: &BlindRotationKeyPrepared<DataBrk, CGGI, B>,
|
||||
scratch: &mut Scratch<B>,
|
||||
lut: &LookupTable,
|
||||
brk: &BlindRotationKeyPrepared<DataBrk, CGGI, BE>,
|
||||
scratch: &mut Scratch<BE>,
|
||||
) where
|
||||
DataRes: DataMut,
|
||||
DataIn: DataRef,
|
||||
DataBrk: DataRef,
|
||||
Module<B>: VecZnxBigBytesOf
|
||||
+ VecZnxDftBytesOf
|
||||
+ SvpPPolBytesOf
|
||||
+ VmpApplyDftToDftTmpBytes
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxIdftApplyTmpBytes
|
||||
+ VecZnxIdftApply<B>
|
||||
+ VecZnxDftAdd<B>
|
||||
+ VecZnxDftAddInplace<B>
|
||||
+ VecZnxDftApply<B>
|
||||
+ VecZnxDftZero<B>
|
||||
+ SvpApplyDftToDft<B>
|
||||
+ VecZnxDftSubInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxRotate
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxSubInplace
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxCopy
|
||||
+ VecZnxMulXpMinusOneInplace<B>
|
||||
+ VmpApplyDftToDft<B>
|
||||
+ VmpApplyDftToDftAdd<B>
|
||||
+ VecZnxIdftApplyConsume<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxNormalizeTmpBytes,
|
||||
Scratch<B>: TakeVecZnxDftSlice<B> + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnxSlice + ScratchAvailable + TakeVecZnx,
|
||||
M: VecZnxRotate + GLWEExternalProduct<BE> + GLWEMulXpMinusOne<BE> + GLWEAdd + GLWENormalize<BE>,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
@@ -498,7 +448,7 @@ fn execute_standard<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
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);
|
||||
let (mut acc_tmp, scratch_1) = scratch.take_glwe(&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,55 +457,13 @@ fn execute_standard<DataRes, DataIn, DataBrk, B: Backend>(
|
||||
acc_tmp.external_product(module, &out_mut, ski, scratch_1);
|
||||
|
||||
// acc_tmp = (sk[i] * acc) * (X^{ai} - 1)
|
||||
acc_tmp.mul_xp_minus_one_inplace(module, *ai, scratch_1);
|
||||
module.glwe_mul_xp_minus_one_inplace(*ai, &mut acc_tmp, scratch_1);
|
||||
|
||||
// acc = acc + (sk[i] * acc) * (X^{ai} - 1)
|
||||
out_mut.add_inplace(module, &acc_tmp);
|
||||
module.glwe_add_inplace(&mut out_mut, &acc_tmp);
|
||||
});
|
||||
|
||||
// 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: &LWE<&[u8]>, rot_dir: LookUpTableRotationDirection) {
|
||||
let base2k: usize = lwe.base2k().into();
|
||||
|
||||
let log2n: usize = usize::BITS as usize - (n - 1).leading_zeros() as usize + 1;
|
||||
|
||||
res.copy_from_slice(lwe.data().at(0, 0));
|
||||
|
||||
match rot_dir {
|
||||
LookUpTableRotationDirection::Left => {
|
||||
res.iter_mut().for_each(|x| *x = -*x);
|
||||
}
|
||||
LookUpTableRotationDirection::Right => {}
|
||||
}
|
||||
|
||||
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 = base2k - (log2n % base2k);
|
||||
let size: usize = log2n.div_ceil(base2k);
|
||||
(1..size).for_each(|i| {
|
||||
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 << base2k) + x;
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn div_round_by_pow2(x: &i64, k: usize) -> i64 {
|
||||
(x + (1 << (k - 1))) >> k
|
||||
module.glwe_normalize_inplace(&mut out_mut, scratch_1);
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
use poulpy_hal::{
|
||||
layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, ScalarZnxToRef, Scratch, ZnxView, ZnxViewMut},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use poulpy_core::{
|
||||
Distribution, GGSWEncryptSk, GetDistribution, ScratchTakeCore,
|
||||
layouts::{GGSW, GGSWInfos, GLWEInfos, GLWESecretPreparedToRef, LWEInfos, LWESecret, LWESecretToRef},
|
||||
};
|
||||
|
||||
use crate::tfhe::blind_rotation::{
|
||||
BlindRotationKey, BlindRotationKeyEncryptSk, BlindRotationKeyFactory, BlindRotationKeyInfos, CGGI,
|
||||
};
|
||||
|
||||
impl<D: DataRef> BlindRotationKeyFactory<CGGI> for BlindRotationKey<D, CGGI> {
|
||||
fn blind_rotation_key_alloc<A>(infos: &A) -> BlindRotationKey<Vec<u8>, CGGI>
|
||||
where
|
||||
A: BlindRotationKeyInfos,
|
||||
{
|
||||
BlindRotationKey {
|
||||
keys: (0..infos.n_lwe().as_usize())
|
||||
.map(|_| GGSW::alloc_from_infos(infos))
|
||||
.collect(),
|
||||
dist: Distribution::NONE,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<BE: Backend> BlindRotationKeyEncryptSk<BE, CGGI> for Module<BE>
|
||||
where
|
||||
Self: GGSWEncryptSk<BE>,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
fn blind_rotation_key_encrypt_sk_tmp_bytes<A: GGSWInfos>(&self, infos: &A) -> usize {
|
||||
self.ggsw_encrypt_sk_tmp_bytes(infos)
|
||||
}
|
||||
|
||||
fn blind_rotation_key_encrypt_sk<D, S0, S1>(
|
||||
&self,
|
||||
res: &mut BlindRotationKey<D, CGGI>,
|
||||
sk_glwe: &S0,
|
||||
sk_lwe: &S1,
|
||||
source_xa: &mut Source,
|
||||
source_xe: &mut Source,
|
||||
scratch: &mut Scratch<BE>,
|
||||
) where
|
||||
D: DataMut,
|
||||
S0: GLWESecretPreparedToRef<BE> + GLWEInfos,
|
||||
S1: LWESecretToRef + LWEInfos + GetDistribution,
|
||||
{
|
||||
assert_eq!(res.keys.len() as u32, sk_lwe.n());
|
||||
assert!(sk_glwe.n() <= self.n() as u32);
|
||||
assert_eq!(sk_glwe.rank(), res.rank());
|
||||
|
||||
match sk_lwe.dist() {
|
||||
Distribution::BinaryBlock(_) | Distribution::BinaryFixed(_) | Distribution::BinaryProb(_) | Distribution::ZERO => {}
|
||||
_ => {
|
||||
panic!("invalid GLWESecret distribution: must be BinaryBlock, BinaryFixed or BinaryProb (or ZERO for debugging)")
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let sk_lwe: &LWESecret<&[u8]> = &sk_lwe.to_ref();
|
||||
|
||||
res.dist = sk_lwe.dist();
|
||||
|
||||
let mut pt: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(sk_glwe.n().into(), 1);
|
||||
let sk_ref: ScalarZnx<&[u8]> = sk_lwe.data().to_ref();
|
||||
|
||||
for (i, ggsw) in res.keys.iter_mut().enumerate() {
|
||||
pt.at_mut(0, 0)[0] = sk_ref.at(0, 0)[i];
|
||||
ggsw.encrypt_sk(self, &pt, sk_glwe, source_xa, source_xe, scratch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use poulpy_core::{
|
||||
Distribution, GGSWCompressedEncryptSk, GetDistribution, ScratchTakeCore,
|
||||
layouts::{GGSWCompressed, GGSWInfos, GLWEInfos, GLWESecretPreparedToRef, LWEInfos, LWESecret, LWESecretToRef},
|
||||
};
|
||||
use poulpy_hal::{
|
||||
layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, ScalarZnxToRef, Scratch, ZnxView, ZnxViewMut},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::tfhe::blind_rotation::{
|
||||
BlindRotationKeyCompressed, BlindRotationKeyCompressedEncryptSk, BlindRotationKeyCompressedFactory, BlindRotationKeyInfos,
|
||||
CGGI,
|
||||
};
|
||||
|
||||
impl<D: DataRef> BlindRotationKeyCompressedFactory<CGGI> for BlindRotationKeyCompressed<D, CGGI> {
|
||||
fn blind_rotation_key_compressed_alloc<A>(infos: &A) -> BlindRotationKeyCompressed<Vec<u8>, CGGI>
|
||||
where
|
||||
A: BlindRotationKeyInfos,
|
||||
{
|
||||
let mut data: Vec<GGSWCompressed<Vec<u8>>> = Vec::with_capacity(infos.n_lwe().into());
|
||||
(0..infos.n_lwe().as_usize()).for_each(|_| data.push(GGSWCompressed::alloc_from_infos(infos)));
|
||||
BlindRotationKeyCompressed {
|
||||
keys: data,
|
||||
dist: Distribution::NONE,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<BE: Backend> BlindRotationKeyCompressedEncryptSk<BE, CGGI> for Module<BE>
|
||||
where
|
||||
Self: GGSWCompressedEncryptSk<BE>,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
fn blind_rotation_key_compressed_encrypt_sk_tmp_bytes<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGSWInfos,
|
||||
{
|
||||
self.ggsw_compressed_encrypt_sk_tmp_bytes(infos)
|
||||
}
|
||||
|
||||
fn blind_rotation_key_compressed_encrypt_sk<D, S0, S1>(
|
||||
&self,
|
||||
res: &mut BlindRotationKeyCompressed<D, CGGI>,
|
||||
sk_glwe: &S0,
|
||||
sk_lwe: &S1,
|
||||
seed_xa: [u8; 32],
|
||||
source_xe: &mut Source,
|
||||
scratch: &mut Scratch<BE>,
|
||||
) where
|
||||
D: DataMut,
|
||||
S0: GLWESecretPreparedToRef<BE> + GLWEInfos,
|
||||
S1: LWESecretToRef + LWEInfos + GetDistribution,
|
||||
{
|
||||
assert_eq!(res.keys.len() as u32, sk_lwe.n());
|
||||
assert!(sk_glwe.n() <= self.n() as u32);
|
||||
assert_eq!(sk_glwe.rank(), res.rank());
|
||||
|
||||
match sk_lwe.dist() {
|
||||
Distribution::BinaryBlock(_) | Distribution::BinaryFixed(_) | Distribution::BinaryProb(_) | Distribution::ZERO => {}
|
||||
_ => {
|
||||
panic!("invalid GLWESecret distribution: must be BinaryBlock, BinaryFixed or BinaryProb (or ZERO for debugging)")
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let sk_lwe: &LWESecret<&[u8]> = &sk_lwe.to_ref();
|
||||
|
||||
let mut source_xa: Source = Source::new(seed_xa);
|
||||
|
||||
res.dist = sk_lwe.dist();
|
||||
|
||||
let mut pt: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(sk_glwe.n().into(), 1);
|
||||
let sk_ref: ScalarZnx<&[u8]> = sk_lwe.data().to_ref();
|
||||
|
||||
for (i, ggsw) in res.keys.iter_mut().enumerate() {
|
||||
pt.at_mut(0, 0)[0] = sk_ref.at(0, 0)[i];
|
||||
ggsw.encrypt_sk(self, &pt, sk_glwe, source_xa.new_seed(), source_xe, scratch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
use poulpy_hal::{
|
||||
api::{SvpPPolAlloc, SvpPrepare},
|
||||
layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch, SvpPPol},
|
||||
};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use poulpy_core::{
|
||||
Distribution,
|
||||
layouts::{GGSWPreparedFactory, LWEInfos, prepared::GGSWPrepared},
|
||||
};
|
||||
|
||||
use crate::tfhe::blind_rotation::{
|
||||
BlindRotationKey, BlindRotationKeyInfos, BlindRotationKeyPrepared, BlindRotationKeyPreparedFactory, CGGI,
|
||||
utils::set_xai_plus_y,
|
||||
};
|
||||
|
||||
impl<BE: Backend> BlindRotationKeyPreparedFactory<BE, CGGI> for Module<BE>
|
||||
where
|
||||
Self: GGSWPreparedFactory<BE> + SvpPPolAlloc<BE> + SvpPrepare<BE>,
|
||||
{
|
||||
fn blind_rotation_key_prepared_alloc<A>(&self, infos: &A) -> BlindRotationKeyPrepared<Vec<u8>, CGGI, BE>
|
||||
where
|
||||
A: BlindRotationKeyInfos,
|
||||
{
|
||||
BlindRotationKeyPrepared {
|
||||
data: (0..infos.n_lwe().as_usize())
|
||||
.map(|_| GGSWPrepared::alloc_from_infos(self, infos))
|
||||
.collect(),
|
||||
dist: Distribution::NONE,
|
||||
x_pow_a: None,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn blind_rotation_key_prepare<DM, DR>(
|
||||
&self,
|
||||
res: &mut BlindRotationKeyPrepared<DM, CGGI, BE>,
|
||||
other: &BlindRotationKey<DR, CGGI>,
|
||||
scratch: &mut Scratch<BE>,
|
||||
) where
|
||||
DM: DataMut,
|
||||
DR: DataRef,
|
||||
{
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
assert_eq!(res.data.len(), other.keys.len());
|
||||
}
|
||||
|
||||
let n: usize = other.n().as_usize();
|
||||
|
||||
for (a, b) in res.data.iter_mut().zip(other.keys.iter()) {
|
||||
a.prepare(self, b, scratch);
|
||||
}
|
||||
|
||||
res.dist = other.dist;
|
||||
|
||||
if let Distribution::BinaryBlock(_) = other.dist {
|
||||
let mut x_pow_a: Vec<SvpPPol<Vec<u8>, BE>> = Vec::with_capacity(n << 1);
|
||||
let mut buf: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
|
||||
(0..n << 1).for_each(|i| {
|
||||
let mut res: SvpPPol<Vec<u8>, BE> = self.svp_ppol_alloc(1);
|
||||
set_xai_plus_y(self, i, 0, &mut res, &mut buf);
|
||||
x_pow_a.push(res);
|
||||
});
|
||||
res.x_pow_a = Some(x_pow_a);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
mod algorithm;
|
||||
mod key;
|
||||
mod key_compressed;
|
||||
mod key_prepared;
|
||||
|
||||
use crate::tfhe::blind_rotation::BlindRotationAlgo;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CGGI {}
|
||||
impl BlindRotationAlgo for CGGI {}
|
||||
116
poulpy-schemes/src/tfhe/blind_rotation/algorithms/mod.rs
Normal file
116
poulpy-schemes/src/tfhe/blind_rotation/algorithms/mod.rs
Normal file
@@ -0,0 +1,116 @@
|
||||
mod cggi;
|
||||
|
||||
pub use cggi::*;
|
||||
|
||||
use itertools::izip;
|
||||
use poulpy_core::{
|
||||
ScratchTakeCore,
|
||||
layouts::{GGSWInfos, GLWE, GLWEInfos, LWE, LWEInfos},
|
||||
};
|
||||
use poulpy_hal::layouts::{Backend, DataMut, DataRef, Scratch, ZnxView};
|
||||
|
||||
use crate::tfhe::blind_rotation::{BlindRotationKeyInfos, BlindRotationKeyPrepared, LookUpTableRotationDirection, LookupTable};
|
||||
|
||||
pub trait BlindRotationAlgo {}
|
||||
|
||||
pub trait BlindRotationExecute<BRA: BlindRotationAlgo, BE: Backend> {
|
||||
fn blind_rotation_execute_tmp_bytes<G, B>(
|
||||
&self,
|
||||
block_size: usize,
|
||||
extension_factor: usize,
|
||||
glwe_infos: &G,
|
||||
brk_infos: &B,
|
||||
) -> usize
|
||||
where
|
||||
G: GLWEInfos,
|
||||
B: GGSWInfos;
|
||||
|
||||
fn blind_rotation_execute<DR, DL, DB>(
|
||||
&self,
|
||||
res: &mut GLWE<DR>,
|
||||
lwe: &LWE<DL>,
|
||||
lut: &LookupTable,
|
||||
brk: &BlindRotationKeyPrepared<DB, BRA, BE>,
|
||||
scratch: &mut Scratch<BE>,
|
||||
) where
|
||||
DR: DataMut,
|
||||
DL: DataRef,
|
||||
DB: DataRef;
|
||||
}
|
||||
|
||||
impl<D: DataRef, BRA: BlindRotationAlgo, BE: Backend> BlindRotationKeyPrepared<D, BRA, BE>
|
||||
where
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
pub fn execute<DR: DataMut, DI: DataRef, M>(
|
||||
&self,
|
||||
module: &M,
|
||||
res: &mut GLWE<DR>,
|
||||
lwe: &LWE<DI>,
|
||||
lut: &LookupTable,
|
||||
scratch: &mut Scratch<BE>,
|
||||
) where
|
||||
M: BlindRotationExecute<BRA, BE>,
|
||||
{
|
||||
module.blind_rotation_execute(res, lwe, lut, self, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
impl<BE: Backend, BRA: BlindRotationAlgo> BlindRotationKeyPrepared<Vec<u8>, BRA, BE> {
|
||||
pub fn execute_tmp_bytes<A, B, M>(
|
||||
module: &M,
|
||||
block_size: usize,
|
||||
extension_factor: usize,
|
||||
glwe_infos: &A,
|
||||
brk_infos: &B,
|
||||
) -> usize
|
||||
where
|
||||
A: GLWEInfos,
|
||||
B: BlindRotationKeyInfos,
|
||||
M: BlindRotationExecute<BRA, BE>,
|
||||
{
|
||||
module.blind_rotation_execute_tmp_bytes(block_size, extension_factor, glwe_infos, brk_infos)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mod_switch_2n(n: usize, res: &mut [i64], lwe: &LWE<&[u8]>, rot_dir: LookUpTableRotationDirection) {
|
||||
let base2k: usize = lwe.base2k().into();
|
||||
|
||||
let log2n: usize = usize::BITS as usize - (n - 1).leading_zeros() as usize + 1;
|
||||
|
||||
res.copy_from_slice(lwe.data().at(0, 0));
|
||||
|
||||
match rot_dir {
|
||||
LookUpTableRotationDirection::Left => {
|
||||
res.iter_mut().for_each(|x| *x = -*x);
|
||||
}
|
||||
LookUpTableRotationDirection::Right => {}
|
||||
}
|
||||
|
||||
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 = base2k - (log2n % base2k);
|
||||
let size: usize = log2n.div_ceil(base2k);
|
||||
(1..size).for_each(|i| {
|
||||
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 << base2k) + x;
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn div_round_by_pow2(x: &i64, k: usize) -> i64 {
|
||||
(x + (1 << (k - 1))) >> k
|
||||
}
|
||||
@@ -1,223 +0,0 @@
|
||||
use poulpy_hal::{
|
||||
api::{
|
||||
ScratchAvailable, SvpApplyDftToDftInplace, TakeVecZnx, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal,
|
||||
VecZnxAddScalarInplace, VecZnxBigNormalize, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume,
|
||||
VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VmpPMatAlloc, VmpPrepare,
|
||||
},
|
||||
layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, ScalarZnxToRef, Scratch, ZnxView, ZnxViewMut},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use poulpy_core::{
|
||||
Distribution,
|
||||
layouts::{
|
||||
GGSW, GGSWInfos, LWESecret,
|
||||
compressed::GGSWCompressed,
|
||||
prepared::{GGSWPrepared, GLWESecretPrepared},
|
||||
},
|
||||
};
|
||||
|
||||
use crate::tfhe::blind_rotation::{
|
||||
BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyCompressed, BlindRotationKeyEncryptSk, BlindRotationKeyInfos,
|
||||
BlindRotationKeyPrepared, BlindRotationKeyPreparedAlloc, CGGI,
|
||||
};
|
||||
|
||||
impl BlindRotationKeyAlloc for BlindRotationKey<Vec<u8>, CGGI> {
|
||||
fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: BlindRotationKeyInfos,
|
||||
{
|
||||
let mut data: Vec<GGSW<Vec<u8>>> = Vec::with_capacity(infos.n_lwe().into());
|
||||
for _ in 0..infos.n_lwe().as_usize() {
|
||||
data.push(GGSW::alloc_from_infos(infos));
|
||||
}
|
||||
|
||||
Self {
|
||||
keys: data,
|
||||
dist: Distribution::NONE,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BlindRotationKey<Vec<u8>, CGGI> {
|
||||
pub fn generate_from_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
|
||||
where
|
||||
A: GGSWInfos,
|
||||
Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftBytesOf,
|
||||
{
|
||||
GGSW::encrypt_sk_tmp_bytes(module, infos)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> BlindRotationKeyEncryptSk<B> for BlindRotationKey<D, CGGI>
|
||||
where
|
||||
Module<B>: VecZnxAddScalarInplace
|
||||
+ VecZnxDftBytesOf
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftApply<B>
|
||||
+ SvpApplyDftToDftInplace<B>
|
||||
+ VecZnxIdftApplyConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub,
|
||||
Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx,
|
||||
{
|
||||
fn encrypt_sk<DataSkGLWE, DataSkLWE>(
|
||||
&mut self,
|
||||
module: &Module<B>,
|
||||
sk_glwe: &GLWESecretPrepared<DataSkGLWE, B>,
|
||||
sk_lwe: &LWESecret<DataSkLWE>,
|
||||
source_xa: &mut Source,
|
||||
source_xe: &mut Source,
|
||||
scratch: &mut Scratch<B>,
|
||||
) where
|
||||
DataSkGLWE: DataRef,
|
||||
DataSkLWE: DataRef,
|
||||
{
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
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(_)
|
||||
| Distribution::BinaryProb(_)
|
||||
| Distribution::ZERO => {}
|
||||
_ => panic!(
|
||||
"invalid GLWESecret distribution: must be BinaryBlock, BinaryFixed or BinaryProb (or ZERO for debugging)"
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
self.dist = sk_lwe.dist();
|
||||
|
||||
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)| {
|
||||
pt.at_mut(0, 0)[0] = sk_ref.at(0, 0)[i];
|
||||
ggsw.encrypt_sk(module, &pt, sk_glwe, source_xa, source_xe, scratch);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> BlindRotationKeyPreparedAlloc<B> for BlindRotationKeyPrepared<Vec<u8>, CGGI, B>
|
||||
where
|
||||
Module<B>: VmpPMatAlloc<B> + VmpPrepare<B>,
|
||||
{
|
||||
fn alloc<A>(module: &Module<B>, infos: &A) -> Self
|
||||
where
|
||||
A: BlindRotationKeyInfos,
|
||||
{
|
||||
let mut data: Vec<GGSWPrepared<Vec<u8>, B>> = Vec::with_capacity(infos.n_lwe().into());
|
||||
(0..infos.n_lwe().as_usize()).for_each(|_| data.push(GGSWPrepared::alloc_from_infos(module, infos)));
|
||||
Self {
|
||||
data,
|
||||
dist: Distribution::NONE,
|
||||
x_pow_a: None,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BlindRotationKeyCompressed<Vec<u8>, CGGI> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: BlindRotationKeyInfos,
|
||||
{
|
||||
let mut data: Vec<GGSWCompressed<Vec<u8>>> = Vec::with_capacity(infos.n_lwe().into());
|
||||
(0..infos.n_lwe().as_usize()).for_each(|_| data.push(GGSWCompressed::alloc_from_infos(infos)));
|
||||
Self {
|
||||
keys: data,
|
||||
dist: Distribution::NONE,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_from_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
|
||||
where
|
||||
A: GGSWInfos,
|
||||
Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftBytesOf,
|
||||
{
|
||||
GGSWCompressed::encrypt_sk_tmp_bytes(module, infos)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> BlindRotationKeyCompressed<D, CGGI> {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn encrypt_sk<DataSkGLWE, DataSkLWE, B: Backend>(
|
||||
&mut self,
|
||||
module: &Module<B>,
|
||||
sk_glwe: &GLWESecretPrepared<DataSkGLWE, B>,
|
||||
sk_lwe: &LWESecret<DataSkLWE>,
|
||||
seed_xa: [u8; 32],
|
||||
source_xe: &mut Source,
|
||||
scratch: &mut Scratch<B>,
|
||||
) where
|
||||
DataSkGLWE: DataRef,
|
||||
DataSkLWE: DataRef,
|
||||
Module<B>: VecZnxAddScalarInplace
|
||||
+ VecZnxDftBytesOf
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxDftApply<B>
|
||||
+ SvpApplyDftToDftInplace<B>
|
||||
+ VecZnxIdftApplyConsume<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxSubInplace
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxSub,
|
||||
Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx,
|
||||
{
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
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(_)
|
||||
| Distribution::BinaryProb(_)
|
||||
| Distribution::ZERO => {}
|
||||
_ => panic!(
|
||||
"invalid GLWESecret distribution: must be BinaryBlock, BinaryFixed or BinaryProb (or ZERO for debugging)"
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
self.dist = sk_lwe.dist();
|
||||
|
||||
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);
|
||||
|
||||
self.keys.iter_mut().enumerate().for_each(|(i, ggsw)| {
|
||||
pt.at_mut(0, 0)[0] = sk_ref.at(0, 0)[i];
|
||||
ggsw.encrypt_sk(
|
||||
module,
|
||||
&pt,
|
||||
sk_glwe,
|
||||
source_xa.new_seed(),
|
||||
source_xe,
|
||||
scratch,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
60
poulpy-schemes/src/tfhe/blind_rotation/encryption/key.rs
Normal file
60
poulpy-schemes/src/tfhe/blind_rotation/encryption/key.rs
Normal file
@@ -0,0 +1,60 @@
|
||||
use poulpy_hal::{
|
||||
layouts::{Backend, DataMut, Scratch},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use poulpy_core::{
|
||||
GetDistribution, ScratchTakeCore,
|
||||
layouts::{GGSWInfos, GLWEInfos, GLWESecretPreparedToRef, LWEInfos, LWESecretToRef},
|
||||
};
|
||||
|
||||
use crate::tfhe::blind_rotation::{BlindRotationAlgo, BlindRotationKey};
|
||||
|
||||
pub trait BlindRotationKeyEncryptSk<B: Backend, BRA: BlindRotationAlgo> {
|
||||
fn blind_rotation_key_encrypt_sk_tmp_bytes<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGSWInfos;
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn blind_rotation_key_encrypt_sk<D, S0, S1>(
|
||||
&self,
|
||||
res: &mut BlindRotationKey<D, BRA>,
|
||||
sk_glwe: &S0,
|
||||
sk_lwe: &S1,
|
||||
source_xa: &mut Source,
|
||||
source_xe: &mut Source,
|
||||
scratch: &mut Scratch<B>,
|
||||
) where
|
||||
D: DataMut,
|
||||
S0: GLWESecretPreparedToRef<B> + GLWEInfos,
|
||||
S1: LWESecretToRef + LWEInfos + GetDistribution;
|
||||
}
|
||||
|
||||
impl<D: DataMut, BRA: BlindRotationAlgo> BlindRotationKey<D, BRA> {
|
||||
pub fn encrypt_sk<M, S0, S1, BE: Backend>(
|
||||
&mut self,
|
||||
module: &M,
|
||||
sk_glwe: &S0,
|
||||
sk_lwe: &S1,
|
||||
source_xa: &mut Source,
|
||||
source_xe: &mut Source,
|
||||
scratch: &mut Scratch<BE>,
|
||||
) where
|
||||
S0: GLWESecretPreparedToRef<BE> + GLWEInfos,
|
||||
S1: LWESecretToRef + LWEInfos + GetDistribution,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
M: BlindRotationKeyEncryptSk<BE, BRA>,
|
||||
{
|
||||
module.blind_rotation_key_encrypt_sk(self, sk_glwe, sk_lwe, source_xa, source_xe, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
impl<BRA: BlindRotationAlgo> BlindRotationKey<Vec<u8>, BRA> {
|
||||
pub fn encrypt_sk_tmp_bytes<A, M, BE: Backend>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGSWInfos,
|
||||
M: BlindRotationKeyEncryptSk<BE, BRA>,
|
||||
{
|
||||
module.blind_rotation_key_encrypt_sk_tmp_bytes(infos)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
use poulpy_core::{
|
||||
GetDistribution,
|
||||
layouts::{GGSWInfos, GLWEInfos, GLWESecretPreparedToRef, LWEInfos, LWESecretToRef},
|
||||
};
|
||||
use poulpy_hal::{
|
||||
layouts::{Backend, DataMut, Scratch},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::tfhe::blind_rotation::{BlindRotationAlgo, BlindRotationKeyCompressed};
|
||||
|
||||
pub trait BlindRotationKeyCompressedEncryptSk<B: Backend, BRA: BlindRotationAlgo> {
|
||||
fn blind_rotation_key_compressed_encrypt_sk_tmp_bytes<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGSWInfos;
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn blind_rotation_key_compressed_encrypt_sk<D, S0, S1>(
|
||||
&self,
|
||||
res: &mut BlindRotationKeyCompressed<D, BRA>,
|
||||
sk_glwe: &S0,
|
||||
sk_lwe: &S1,
|
||||
seed_xa: [u8; 32],
|
||||
source_xe: &mut Source,
|
||||
scratch: &mut Scratch<B>,
|
||||
) where
|
||||
D: DataMut,
|
||||
S0: GLWESecretPreparedToRef<B> + GLWEInfos,
|
||||
S1: LWESecretToRef + LWEInfos + GetDistribution;
|
||||
}
|
||||
5
poulpy-schemes/src/tfhe/blind_rotation/encryption/mod.rs
Normal file
5
poulpy-schemes/src/tfhe/blind_rotation/encryption/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
mod key;
|
||||
mod key_compressed;
|
||||
|
||||
pub use key::*;
|
||||
pub use key_compressed::*;
|
||||
@@ -1,130 +0,0 @@
|
||||
use poulpy_hal::{
|
||||
api::{SvpPPolAlloc, SvpPrepare, VmpPMatAlloc, VmpPrepare},
|
||||
layouts::{Backend, Data, DataMut, DataRef, Module, ScalarZnx, Scratch, SvpPPol},
|
||||
};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use poulpy_core::{
|
||||
Distribution,
|
||||
layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGSWInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision,
|
||||
prepared::{GGSWPrepared, Prepare, PrepareAlloc},
|
||||
},
|
||||
};
|
||||
|
||||
use crate::tfhe::blind_rotation::{BlindRotationAlgo, BlindRotationKey, BlindRotationKeyInfos, utils::set_xai_plus_y};
|
||||
|
||||
pub trait BlindRotationKeyPreparedAlloc<B: Backend> {
|
||||
fn alloc<A>(module: &Module<B>, infos: &A) -> Self
|
||||
where
|
||||
A: BlindRotationKeyInfos;
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct BlindRotationKeyPrepared<D: Data, BRT: BlindRotationAlgo, B: Backend> {
|
||||
pub(crate) data: Vec<GGSWPrepared<D, B>>,
|
||||
pub(crate) dist: Distribution,
|
||||
pub(crate) x_pow_a: Option<Vec<SvpPPol<Vec<u8>, B>>>,
|
||||
pub(crate) _phantom: PhantomData<BRT>,
|
||||
}
|
||||
|
||||
impl<D: Data, BRT: BlindRotationAlgo, B: Backend> BlindRotationKeyInfos for BlindRotationKeyPrepared<D, BRT, B> {
|
||||
fn n_glwe(&self) -> Degree {
|
||||
self.n()
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
fn k(&self) -> TorusPrecision {
|
||||
self.data[0].k()
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
self.data[0].n()
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
self.data[0].size()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, BRT: BlindRotationAlgo, B: Backend> GLWEInfos for BlindRotationKeyPrepared<D, BRT, B> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.data[0].rank()
|
||||
}
|
||||
}
|
||||
impl<D: Data, BRT: BlindRotationAlgo, B: Backend> GGSWInfos for BlindRotationKeyPrepared<D, BRT, B> {
|
||||
fn dsize(&self) -> poulpy_core::layouts::Dsize {
|
||||
Dsize(1)
|
||||
}
|
||||
|
||||
fn dnum(&self) -> Dnum {
|
||||
self.data[0].dnum()
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, BRA: BlindRotationAlgo, B: Backend> PrepareAlloc<B, BlindRotationKeyPrepared<Vec<u8>, BRA, B>>
|
||||
for BlindRotationKey<D, BRA>
|
||||
where
|
||||
BlindRotationKeyPrepared<Vec<u8>, BRA, B>: BlindRotationKeyPreparedAlloc<B>,
|
||||
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);
|
||||
brk.prepare(module, self, scratch);
|
||||
brk
|
||||
}
|
||||
}
|
||||
|
||||
impl<DM: DataMut, DR: DataRef, BRA: BlindRotationAlgo, B: Backend> Prepare<B, BlindRotationKey<DR, BRA>>
|
||||
for BlindRotationKeyPrepared<DM, BRA, B>
|
||||
where
|
||||
Module<B>: VmpPMatAlloc<B> + VmpPrepare<B> + SvpPPolAlloc<B> + SvpPrepare<B>,
|
||||
{
|
||||
fn prepare(&mut self, module: &Module<B>, other: &BlindRotationKey<DR, BRA>, scratch: &mut Scratch<B>) {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
assert_eq!(self.data.len(), other.keys.len());
|
||||
}
|
||||
|
||||
let n: usize = other.n().as_usize();
|
||||
|
||||
self.data
|
||||
.iter_mut()
|
||||
.zip(other.keys.iter())
|
||||
.for_each(|(ggsw_prepared, other)| {
|
||||
ggsw_prepared.prepare(module, other, scratch);
|
||||
});
|
||||
|
||||
self.dist = other.dist;
|
||||
|
||||
if let Distribution::BinaryBlock(_) = other.dist {
|
||||
let mut x_pow_a: Vec<SvpPPol<Vec<u8>, B>> = Vec::with_capacity(n << 1);
|
||||
let mut buf: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
|
||||
(0..n << 1).for_each(|i| {
|
||||
let mut res: SvpPPol<Vec<u8>, B> = module.svp_ppol_alloc(1);
|
||||
set_xai_plus_y(module, i, 0, &mut res, &mut buf);
|
||||
x_pow_a.push(res);
|
||||
});
|
||||
self.x_pow_a = Some(x_pow_a);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
use poulpy_hal::{
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, Scratch, WriterTo},
|
||||
layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
@@ -7,10 +7,7 @@ use std::{fmt, marker::PhantomData};
|
||||
|
||||
use poulpy_core::{
|
||||
Distribution,
|
||||
layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGSW, GGSWInfos, GLWEInfos, LWEInfos, LWESecret, Rank, TorusPrecision,
|
||||
prepared::GLWESecretPrepared,
|
||||
},
|
||||
layouts::{Base2K, Degree, Dnum, Dsize, GGSW, GGSWInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision},
|
||||
};
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
@@ -81,21 +78,6 @@ pub trait BlindRotationKeyAlloc {
|
||||
A: BlindRotationKeyInfos;
|
||||
}
|
||||
|
||||
pub trait BlindRotationKeyEncryptSk<B: Backend> {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn encrypt_sk<DataSkGLWE, DataSkLWE>(
|
||||
&mut self,
|
||||
module: &Module<B>,
|
||||
sk_glwe: &GLWESecretPrepared<DataSkGLWE, B>,
|
||||
sk_lwe: &LWESecret<DataSkLWE>,
|
||||
source_xa: &mut Source,
|
||||
source_xe: &mut Source,
|
||||
scratch: &mut Scratch<B>,
|
||||
) where
|
||||
DataSkGLWE: DataRef,
|
||||
DataSkLWE: DataRef;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BlindRotationKey<D: Data, BRT: BlindRotationAlgo> {
|
||||
pub(crate) keys: Vec<GGSW<D>>,
|
||||
@@ -103,6 +85,24 @@ pub struct BlindRotationKey<D: Data, BRT: BlindRotationAlgo> {
|
||||
pub(crate) _phantom: PhantomData<BRT>,
|
||||
}
|
||||
|
||||
pub trait BlindRotationKeyFactory<BRA: BlindRotationAlgo> {
|
||||
fn blind_rotation_key_alloc<A>(infos: &A) -> BlindRotationKey<Vec<u8>, BRA>
|
||||
where
|
||||
A: BlindRotationKeyInfos;
|
||||
}
|
||||
|
||||
impl<BRA: BlindRotationAlgo> BlindRotationKey<Vec<u8>, BRA>
|
||||
where
|
||||
Self: BlindRotationKeyFactory<BRA>,
|
||||
{
|
||||
pub fn alloc<A>(infos: &A) -> BlindRotationKey<Vec<u8>, BRA>
|
||||
where
|
||||
A: BlindRotationKeyInfos,
|
||||
{
|
||||
Self::blind_rotation_key_alloc(infos)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, BRT: BlindRotationAlgo> fmt::Debug for BlindRotationKey<D, BRT> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
@@ -20,6 +20,24 @@ pub struct BlindRotationKeyCompressed<D: Data, BRT: BlindRotationAlgo> {
|
||||
pub(crate) _phantom: PhantomData<BRT>,
|
||||
}
|
||||
|
||||
pub trait BlindRotationKeyCompressedFactory<BRA: BlindRotationAlgo> {
|
||||
fn blind_rotation_key_compressed_alloc<A>(infos: &A) -> BlindRotationKeyCompressed<Vec<u8>, BRA>
|
||||
where
|
||||
A: BlindRotationKeyInfos;
|
||||
}
|
||||
|
||||
impl<BRA: BlindRotationAlgo> BlindRotationKeyCompressed<Vec<u8>, BRA>
|
||||
where
|
||||
Self: BlindRotationKeyCompressedFactory<BRA>,
|
||||
{
|
||||
pub fn alloc<A>(infos: &A) -> BlindRotationKeyCompressed<Vec<u8>, BRA>
|
||||
where
|
||||
A: BlindRotationKeyInfos,
|
||||
{
|
||||
Self::blind_rotation_key_compressed_alloc(infos)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, BRT: BlindRotationAlgo> fmt::Debug for BlindRotationKeyCompressed<D, BRT> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
108
poulpy-schemes/src/tfhe/blind_rotation/layouts/key_prepared.rs
Normal file
108
poulpy-schemes/src/tfhe/blind_rotation/layouts/key_prepared.rs
Normal file
@@ -0,0 +1,108 @@
|
||||
use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Scratch, SvpPPol};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use poulpy_core::{
|
||||
Distribution, ScratchTakeCore,
|
||||
layouts::{Base2K, Degree, Dnum, Dsize, GGSWInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision, prepared::GGSWPrepared},
|
||||
};
|
||||
|
||||
use crate::tfhe::blind_rotation::{BlindRotationAlgo, BlindRotationKey, BlindRotationKeyInfos};
|
||||
|
||||
pub trait BlindRotationKeyPreparedFactory<BE: Backend, BRA: BlindRotationAlgo> {
|
||||
fn blind_rotation_key_prepared_alloc<A>(&self, infos: &A) -> BlindRotationKeyPrepared<Vec<u8>, BRA, BE>
|
||||
where
|
||||
A: BlindRotationKeyInfos;
|
||||
|
||||
fn blind_rotation_key_prepare<DM, DR>(
|
||||
&self,
|
||||
res: &mut BlindRotationKeyPrepared<DM, BRA, BE>,
|
||||
other: &BlindRotationKey<DR, BRA>,
|
||||
scratch: &mut Scratch<BE>,
|
||||
) where
|
||||
DM: DataMut,
|
||||
DR: DataRef,
|
||||
Scratch<BE>: ScratchTakeCore<BE>;
|
||||
}
|
||||
|
||||
impl<BE: Backend, BRA: BlindRotationAlgo> BlindRotationKeyPrepared<Vec<u8>, BRA, BE> {
|
||||
pub fn alloc<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: BlindRotationKeyInfos,
|
||||
M: BlindRotationKeyPreparedFactory<BE, BRA>,
|
||||
{
|
||||
module.blind_rotation_key_prepared_alloc(infos)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, BRA: BlindRotationAlgo, BE: Backend> BlindRotationKeyPrepared<D, BRA, BE>
|
||||
where
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
pub fn prepare<DR: DataRef, M>(&mut self, module: &M, other: &BlindRotationKey<DR, BRA>, scratch: &mut Scratch<BE>)
|
||||
where
|
||||
M: BlindRotationKeyPreparedFactory<BE, BRA>,
|
||||
{
|
||||
module.blind_rotation_key_prepare(self, other, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct BlindRotationKeyPrepared<D: Data, BRT: BlindRotationAlgo, B: Backend> {
|
||||
pub(crate) data: Vec<GGSWPrepared<D, B>>,
|
||||
pub(crate) dist: Distribution,
|
||||
pub(crate) x_pow_a: Option<Vec<SvpPPol<Vec<u8>, B>>>,
|
||||
pub(crate) _phantom: PhantomData<BRT>,
|
||||
}
|
||||
|
||||
impl<D: Data, BRT: BlindRotationAlgo, B: Backend> BlindRotationKeyInfos for BlindRotationKeyPrepared<D, BRT, B> {
|
||||
fn n_glwe(&self) -> Degree {
|
||||
self.n()
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
fn k(&self) -> TorusPrecision {
|
||||
self.data[0].k()
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
self.data[0].n()
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
self.data[0].size()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, BRT: BlindRotationAlgo, B: Backend> GLWEInfos for BlindRotationKeyPrepared<D, BRT, B> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.data[0].rank()
|
||||
}
|
||||
}
|
||||
impl<D: Data, BRT: BlindRotationAlgo, B: Backend> GGSWInfos for BlindRotationKeyPrepared<D, BRT, B> {
|
||||
fn dsize(&self) -> poulpy_core::layouts::Dsize {
|
||||
Dsize(1)
|
||||
}
|
||||
|
||||
fn dnum(&self) -> Dnum {
|
||||
self.data[0].dnum()
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
6
poulpy-schemes/src/tfhe/blind_rotation/layouts/mod.rs
Normal file
6
poulpy-schemes/src/tfhe/blind_rotation/layouts/mod.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
mod key;
|
||||
mod key_compressed;
|
||||
mod key_prepared;
|
||||
pub use key::*;
|
||||
pub use key_compressed::*;
|
||||
pub use key_prepared::*;
|
||||
@@ -1,3 +1,4 @@
|
||||
use poulpy_core::layouts::{Base2K, Degree, TorusPrecision};
|
||||
use poulpy_hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, TakeSlice, VecZnxCopy, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes,
|
||||
@@ -13,32 +14,97 @@ pub enum LookUpTableRotationDirection {
|
||||
Right,
|
||||
}
|
||||
|
||||
pub struct LookUpTable {
|
||||
pub struct LookUpTableLayout {
|
||||
pub n: Degree,
|
||||
pub extension_factor: usize,
|
||||
pub k: TorusPrecision,
|
||||
pub base2k: Base2K,
|
||||
}
|
||||
|
||||
pub trait LookupTableInfos {
|
||||
fn n(&self) -> Degree;
|
||||
fn extension_factor(&self) -> usize;
|
||||
fn k(&self) -> TorusPrecision;
|
||||
fn base2k(&self) -> Base2K;
|
||||
fn size(&self) -> usize;
|
||||
}
|
||||
|
||||
impl LookupTableInfos for LookUpTableLayout {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.base2k
|
||||
}
|
||||
|
||||
fn extension_factor(&self) -> usize {
|
||||
self.extension_factor
|
||||
}
|
||||
|
||||
fn k(&self) -> TorusPrecision {
|
||||
self.k
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
self.k().as_usize().div_ceil(self.base2k().as_usize())
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
self.n
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LookupTable {
|
||||
pub(crate) data: Vec<VecZnx<Vec<u8>>>,
|
||||
pub(crate) rot_dir: LookUpTableRotationDirection,
|
||||
pub(crate) base2k: usize,
|
||||
pub(crate) k: usize,
|
||||
pub(crate) base2k: Base2K,
|
||||
pub(crate) k: TorusPrecision,
|
||||
pub(crate) drift: usize,
|
||||
}
|
||||
|
||||
impl LookUpTable {
|
||||
pub fn alloc<B: Backend>(module: &Module<B>, base2k: usize, k: usize, extension_factor: usize) -> Self {
|
||||
impl LookupTableInfos for LookupTable {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.base2k
|
||||
}
|
||||
|
||||
fn extension_factor(&self) -> usize {
|
||||
self.data.len()
|
||||
}
|
||||
|
||||
fn k(&self) -> TorusPrecision {
|
||||
self.k
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
self.data[0].n().into()
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
self.data[0].size()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LookupTableFactory {
|
||||
fn lookup_table_set(&self, res: &mut LookupTable, f: &[i64], k: usize);
|
||||
fn lookup_table_rotate(&self, k: i64, res: &mut LookupTable);
|
||||
}
|
||||
|
||||
impl LookupTable {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: LookupTableInfos,
|
||||
{
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
assert!(
|
||||
extension_factor & (extension_factor - 1) == 0,
|
||||
"extension_factor must be a power of two but is: {extension_factor}"
|
||||
infos.extension_factor() & (infos.extension_factor() - 1) == 0,
|
||||
"extension_factor must be a power of two but is: {}",
|
||||
infos.extension_factor()
|
||||
);
|
||||
}
|
||||
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,
|
||||
base2k,
|
||||
k,
|
||||
data: (0..infos.extension_factor())
|
||||
.map(|_| VecZnx::alloc(infos.n().into(), 1, infos.size()))
|
||||
.collect(),
|
||||
base2k: infos.base2k(),
|
||||
k: infos.k(),
|
||||
drift: 0,
|
||||
rot_dir: LookUpTableRotationDirection::Left,
|
||||
}
|
||||
@@ -68,115 +134,18 @@ impl LookUpTable {
|
||||
self.rot_dir = rot_dir
|
||||
}
|
||||
|
||||
pub fn set<B: Backend>(&mut self, module: &Module<B>, f: &[i64], k: usize)
|
||||
pub fn set<M>(&mut self, module: &M, f: &[i64], k: usize)
|
||||
where
|
||||
Module<B>: VecZnxRotateInplace<B>
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxSwitchRing
|
||||
+ VecZnxCopy
|
||||
+ VecZnxRotateInplaceTmpBytes,
|
||||
ScratchOwned<B>: ScratchOwnedAlloc<B> + ScratchOwnedBorrow<B>,
|
||||
Scratch<B>: TakeSlice,
|
||||
M: LookupTableFactory,
|
||||
{
|
||||
assert!(f.len() <= module.n());
|
||||
|
||||
let base2k: usize = self.base2k;
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(module.vec_znx_normalize_tmp_bytes() | (self.domain_size() << 3));
|
||||
|
||||
// Get the number minimum limb to store the message modulus
|
||||
let limbs: usize = k.div_ceil(base2k);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
assert!(f.len() <= module.n());
|
||||
assert!(
|
||||
(max_bit_size(f) + (k % base2k) as u32) < i64::BITS,
|
||||
"overflow: max(|f|) << (k%base2k) > i64::BITS"
|
||||
);
|
||||
assert!(limbs <= self.data[0].size());
|
||||
module.lookup_table_set(self, f, k);
|
||||
}
|
||||
|
||||
// Scaling factor
|
||||
let mut scale = 1;
|
||||
if !k.is_multiple_of(base2k) {
|
||||
scale <<= base2k - (k % base2k);
|
||||
}
|
||||
|
||||
// #elements in lookup table
|
||||
let f_len: usize = f.len();
|
||||
|
||||
// If LUT size > TakeScalarZnx
|
||||
let domain_size: usize = self.domain_size();
|
||||
|
||||
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);
|
||||
|
||||
let lut_at: &mut [i64] = lut_full.at_mut(0, limbs - 1);
|
||||
|
||||
let step: usize = domain_size.div_round(f_len);
|
||||
|
||||
f.iter().enumerate().for_each(|(i, fi)| {
|
||||
let start: usize = i * step;
|
||||
let end: usize = start + step;
|
||||
lut_at[start..end].fill(fi * scale);
|
||||
});
|
||||
|
||||
let drift: usize = step >> 1;
|
||||
|
||||
// Rotates half the step to the left
|
||||
|
||||
if self.extension_factor() > 1 {
|
||||
let (tmp, _) = scratch.borrow().take_slice(lut_full.n());
|
||||
|
||||
for i in 0..self.extension_factor() {
|
||||
module.vec_znx_switch_ring(&mut self.data[i], 0, &lut_full, 0);
|
||||
if i < self.extension_factor() {
|
||||
vec_znx_rotate_inplace::<_, ZnxRef>(-1, &mut lut_full, 0, tmp);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
module.vec_znx_copy(&mut self.data[0], 0, &lut_full, 0);
|
||||
}
|
||||
|
||||
for a in self.data.iter_mut() {
|
||||
module.vec_znx_normalize_inplace(self.base2k, a, 0, scratch.borrow());
|
||||
}
|
||||
|
||||
self.rotate(module, -(drift as i64));
|
||||
|
||||
self.drift = drift
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn rotate<B: Backend>(&mut self, module: &Module<B>, k: i64)
|
||||
pub(crate) fn rotate<M>(&mut self, module: &M, k: i64)
|
||||
where
|
||||
Module<B>: VecZnxRotateInplace<B> + VecZnxRotateInplaceTmpBytes,
|
||||
ScratchOwned<B>: ScratchOwnedAlloc<B> + ScratchOwnedBorrow<B>,
|
||||
M: LookupTableFactory,
|
||||
{
|
||||
let extension_factor: usize = self.extension_factor();
|
||||
let two_n: usize = 2 * self.data[0].n();
|
||||
let two_n_ext: usize = two_n * extension_factor;
|
||||
|
||||
let mut scratch: ScratchOwned<_> = ScratchOwned::alloc(module.vec_znx_rotate_inplace_tmp_bytes());
|
||||
|
||||
let k_pos: usize = ((k + two_n_ext as i64) % two_n_ext as i64) as usize;
|
||||
|
||||
let k_hi: usize = k_pos / extension_factor;
|
||||
let k_lo: usize = k_pos % extension_factor;
|
||||
|
||||
(0..extension_factor - k_lo).for_each(|i| {
|
||||
module.vec_znx_rotate_inplace(k_hi as i64, &mut self.data[i], 0, scratch.borrow());
|
||||
});
|
||||
|
||||
(extension_factor - k_lo..extension_factor).for_each(|i| {
|
||||
module.vec_znx_rotate_inplace(k_hi as i64 + 1, &mut self.data[i], 0, scratch.borrow());
|
||||
});
|
||||
|
||||
self.data.rotate_right(k_lo);
|
||||
module.lookup_table_rotate(k, self);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,3 +173,116 @@ fn max_bit_size(vec: &[i64]) -> u32 {
|
||||
.max()
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
impl<BE: Backend> LookupTableFactory for Module<BE>
|
||||
where
|
||||
Self: VecZnxRotateInplace<BE>
|
||||
+ VecZnxNormalizeInplace<BE>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxSwitchRing
|
||||
+ VecZnxCopy
|
||||
+ VecZnxRotateInplaceTmpBytes
|
||||
+ VecZnxRotateInplace<BE>
|
||||
+ VecZnxRotateInplaceTmpBytes,
|
||||
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||
Scratch<BE>: TakeSlice,
|
||||
{
|
||||
fn lookup_table_set(&self, res: &mut LookupTable, f: &[i64], k: usize) {
|
||||
assert!(f.len() <= self.n());
|
||||
|
||||
let base2k: usize = res.base2k.into();
|
||||
|
||||
let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(
|
||||
self.vec_znx_normalize_tmp_bytes()
|
||||
.max(res.domain_size() << 3),
|
||||
);
|
||||
|
||||
// Get the number minimum limb to store the message modulus
|
||||
let limbs: usize = k.div_ceil(base2k);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
assert!(f.len() <= self.n());
|
||||
assert!(
|
||||
(max_bit_size(f) + (k % base2k) as u32) < i64::BITS,
|
||||
"overflow: max(|f|) << (k%base2k) > i64::BITS"
|
||||
);
|
||||
assert!(limbs <= res.data[0].size());
|
||||
}
|
||||
|
||||
// Scaling factor
|
||||
let mut scale = 1;
|
||||
if !k.is_multiple_of(base2k) {
|
||||
scale <<= base2k - (k % base2k);
|
||||
}
|
||||
|
||||
// #elements in lookup table
|
||||
let f_len: usize = f.len();
|
||||
|
||||
// If LUT size > TakeScalarZnx
|
||||
let domain_size: usize = res.domain_size();
|
||||
|
||||
let size: usize = res.k.div_ceil(res.base2k) as usize;
|
||||
|
||||
// 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);
|
||||
|
||||
let lut_at: &mut [i64] = lut_full.at_mut(0, limbs - 1);
|
||||
|
||||
let step: usize = domain_size.div_round(f_len);
|
||||
|
||||
f.iter().enumerate().for_each(|(i, fi)| {
|
||||
let start: usize = i * step;
|
||||
let end: usize = start + step;
|
||||
lut_at[start..end].fill(fi * scale);
|
||||
});
|
||||
|
||||
let drift: usize = step >> 1;
|
||||
|
||||
// Rotates half the step to the left
|
||||
|
||||
if res.extension_factor() > 1 {
|
||||
let (tmp, _) = scratch.borrow().take_slice(lut_full.n());
|
||||
|
||||
for i in 0..res.extension_factor() {
|
||||
self.vec_znx_switch_ring(&mut res.data[i], 0, &lut_full, 0);
|
||||
if i < res.extension_factor() {
|
||||
vec_znx_rotate_inplace::<_, ZnxRef>(-1, &mut lut_full, 0, tmp);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.vec_znx_copy(&mut res.data[0], 0, &lut_full, 0);
|
||||
}
|
||||
|
||||
for a in res.data.iter_mut() {
|
||||
self.vec_znx_normalize_inplace(res.base2k.into(), a, 0, scratch.borrow());
|
||||
}
|
||||
|
||||
res.rotate(self, -(drift as i64));
|
||||
|
||||
res.drift = drift
|
||||
}
|
||||
|
||||
fn lookup_table_rotate(&self, k: i64, res: &mut LookupTable) {
|
||||
let extension_factor: usize = res.extension_factor();
|
||||
let two_n: usize = 2 * res.data[0].n();
|
||||
let two_n_ext: usize = two_n * extension_factor;
|
||||
|
||||
let mut scratch: ScratchOwned<_> = ScratchOwned::alloc(self.vec_znx_rotate_inplace_tmp_bytes());
|
||||
|
||||
let k_pos: usize = ((k + two_n_ext as i64) % two_n_ext as i64) as usize;
|
||||
|
||||
let k_hi: usize = k_pos / extension_factor;
|
||||
let k_lo: usize = k_pos % extension_factor;
|
||||
|
||||
(0..extension_factor - k_lo).for_each(|i| {
|
||||
self.vec_znx_rotate_inplace(k_hi as i64, &mut res.data[i], 0, scratch.borrow());
|
||||
});
|
||||
|
||||
(extension_factor - k_lo..extension_factor).for_each(|i| {
|
||||
self.vec_znx_rotate_inplace(k_hi as i64 + 1, &mut res.data[i], 0, scratch.borrow());
|
||||
});
|
||||
|
||||
res.data.rotate_right(k_lo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,11 @@
|
||||
mod cggi_algo;
|
||||
mod cggi_key;
|
||||
mod key;
|
||||
mod key_compressed;
|
||||
mod key_prepared;
|
||||
mod algorithms;
|
||||
mod encryption;
|
||||
mod layouts;
|
||||
mod lut;
|
||||
mod utils;
|
||||
|
||||
pub use cggi_algo::*;
|
||||
pub use key::*;
|
||||
pub use key_compressed::*;
|
||||
pub use key_prepared::*;
|
||||
pub use algorithms::*;
|
||||
pub use encryption::*;
|
||||
pub use layouts::*;
|
||||
pub use lut::*;
|
||||
|
||||
pub mod tests;
|
||||
|
||||
use poulpy_core::layouts::{GLWE, LWE};
|
||||
use poulpy_hal::layouts::{Backend, DataMut, DataRef, Module, Scratch};
|
||||
|
||||
pub trait BlindRotationAlgo {}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CGGI {}
|
||||
impl BlindRotationAlgo for CGGI {}
|
||||
|
||||
pub trait BlincRotationExecute<B: Backend> {
|
||||
fn execute<DR: DataMut, DI: DataRef>(
|
||||
&self,
|
||||
module: &Module<B>,
|
||||
res: &mut GLWE<DR>,
|
||||
lwe: &LWE<DI>,
|
||||
lut: &LookUpTable,
|
||||
scratch: &mut Scratch<B>,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,88 +1,40 @@
|
||||
use poulpy_hal::{
|
||||
api::{
|
||||
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf,
|
||||
SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace,
|
||||
VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAdd, VecZnxDftAddInplace,
|
||||
VecZnxDftApply, VecZnxDftBytesOf, VecZnxDftSubInplace, VecZnxDftZero, VecZnxFillUniform, VecZnxIdftApply,
|
||||
VecZnxIdftApplyConsume, VecZnxIdftApplyTmpBytes, VecZnxMulXpMinusOneInplace, VecZnxNormalize, VecZnxNormalizeInplace,
|
||||
VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxRotateInplaceTmpBytes, VecZnxSub, VecZnxSubInplace,
|
||||
VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, ZnAddNormal,
|
||||
ZnFillUniform, ZnNormalizeInplace,
|
||||
},
|
||||
layouts::{Backend, Module, ScratchOwned, ZnxView},
|
||||
oep::{
|
||||
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeSliceImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl,
|
||||
TakeVecZnxDftSliceImpl, TakeVecZnxImpl, TakeVecZnxSliceImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl,
|
||||
},
|
||||
api::{ScratchOwnedAlloc, ScratchOwnedBorrow},
|
||||
layouts::{Backend, Scratch, ScratchOwned, ZnxView},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::tfhe::blind_rotation::{
|
||||
BlincRotationExecute, BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyEncryptSk, BlindRotationKeyLayout,
|
||||
BlindRotationKeyPrepared, CGGI, LookUpTable, cggi_blind_rotate_tmp_bytes, mod_switch_2n,
|
||||
BlindRotationAlgo, BlindRotationExecute, BlindRotationKey, BlindRotationKeyEncryptSk, BlindRotationKeyFactory,
|
||||
BlindRotationKeyLayout, BlindRotationKeyPrepared, BlindRotationKeyPreparedFactory, LookUpTableLayout, LookupTable,
|
||||
LookupTableFactory, mod_switch_2n,
|
||||
};
|
||||
|
||||
use poulpy_core::layouts::{
|
||||
GLWE, GLWELayout, GLWEPlaintext, GLWESecret, LWE, LWEInfos, LWELayout, LWEPlaintext, LWESecret, LWEToRef,
|
||||
prepared::{GLWESecretPrepared, PrepareAlloc},
|
||||
use poulpy_core::{
|
||||
GLWEDecrypt, LWEEncryptSk, ScratchTakeCore,
|
||||
layouts::{
|
||||
GLWE, GLWELayout, GLWEPlaintext, GLWESecret, GLWESecretPreparedFactory, LWE, LWEInfos, LWELayout, LWEPlaintext,
|
||||
LWESecret, LWEToRef, prepared::GLWESecretPrepared,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn test_blind_rotation<B>(module: &Module<B>, n_lwe: usize, block_size: usize, extension_factor: usize)
|
||||
where
|
||||
Module<B>: VecZnxBigBytesOf
|
||||
+ VecZnxDftBytesOf
|
||||
+ SvpPPolBytesOf
|
||||
+ VmpApplyDftToDftTmpBytes
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VecZnxIdftApplyTmpBytes
|
||||
+ VecZnxIdftApply<B>
|
||||
+ VecZnxDftAdd<B>
|
||||
+ VecZnxDftAddInplace<B>
|
||||
+ VecZnxDftApply<B>
|
||||
+ VecZnxDftZero<B>
|
||||
+ SvpApplyDftToDft<B>
|
||||
+ VecZnxDftSubInplace<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxRotate
|
||||
+ VecZnxAddInplace
|
||||
+ VecZnxSubInplace
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxCopy
|
||||
+ VecZnxMulXpMinusOneInplace<B>
|
||||
+ SvpPrepare<B>
|
||||
+ SvpPPolAlloc<B>
|
||||
+ SvpApplyDftToDftInplace<B>
|
||||
+ VecZnxIdftApplyConsume<B>
|
||||
+ VecZnxBigAddInplace<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxFillUniform
|
||||
+ VecZnxAddNormal
|
||||
+ VecZnxAddScalarInplace
|
||||
+ VecZnxRotateInplace<B>
|
||||
+ VecZnxSwitchRing
|
||||
+ VecZnxSub
|
||||
+ VmpPMatAlloc<B>
|
||||
+ VmpPrepare<B>
|
||||
+ VmpApplyDftToDft<B>
|
||||
+ VmpApplyDftToDftAdd<B>
|
||||
+ ZnFillUniform
|
||||
+ ZnAddNormal
|
||||
+ VecZnxRotateInplaceTmpBytes
|
||||
+ ZnNormalizeInplace<B>,
|
||||
B: Backend
|
||||
+ VecZnxDftAllocBytesImpl<B>
|
||||
+ VecZnxBigAllocBytesImpl<B>
|
||||
+ ScratchOwnedAllocImpl<B>
|
||||
+ ScratchOwnedBorrowImpl<B>
|
||||
+ TakeVecZnxDftImpl<B>
|
||||
+ TakeVecZnxBigImpl<B>
|
||||
+ TakeVecZnxDftSliceImpl<B>
|
||||
+ ScratchAvailableImpl<B>
|
||||
+ TakeVecZnxImpl<B>
|
||||
+ TakeVecZnxSliceImpl<B>
|
||||
+ TakeSliceImpl<B>,
|
||||
pub fn test_blind_rotation<BRA: BlindRotationAlgo, M, BE: Backend>(
|
||||
module: &M,
|
||||
n_lwe: usize,
|
||||
block_size: usize,
|
||||
extension_factor: usize,
|
||||
) where
|
||||
M: BlindRotationKeyEncryptSk<BE, BRA>
|
||||
+ BlindRotationKeyPreparedFactory<BE, BRA>
|
||||
+ BlindRotationExecute<BRA, BE>
|
||||
+ GLWESecretPreparedFactory<BE>
|
||||
+ BlindRotationExecute<BRA, BE>
|
||||
+ LWEEncryptSk<BE>
|
||||
+ LookupTableFactory
|
||||
+ GLWEDecrypt<BE>,
|
||||
BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyFactory<BRA>,
|
||||
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
let n_glwe: usize = module.n();
|
||||
let base2k: usize = 19;
|
||||
@@ -123,18 +75,17 @@ where
|
||||
base2k: base2k.into(),
|
||||
};
|
||||
|
||||
let mut scratch: ScratchOwned<B> = ScratchOwned::<B>::alloc(BlindRotationKey::generate_from_sk_tmp_bytes(
|
||||
module, &brk_infos,
|
||||
));
|
||||
let mut scratch: ScratchOwned<BE> = ScratchOwned::<BE>::alloc(BlindRotationKey::encrypt_sk_tmp_bytes(module, &brk_infos));
|
||||
|
||||
let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&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_glwe_dft: GLWESecretPrepared<Vec<u8>, BE> = GLWESecretPrepared::alloc_from_infos(module, &glwe_infos);
|
||||
sk_glwe_dft.prepare(module, &sk_glwe);
|
||||
|
||||
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_tmp_bytes(
|
||||
let mut scratch_br: ScratchOwned<BE> = ScratchOwned::<BE>::alloc(BlindRotationKeyPrepared::execute_tmp_bytes(
|
||||
module,
|
||||
block_size,
|
||||
extension_factor,
|
||||
@@ -142,7 +93,7 @@ where
|
||||
&brk_infos,
|
||||
));
|
||||
|
||||
let mut brk: BlindRotationKey<Vec<u8>, CGGI> = BlindRotationKey::<Vec<u8>, CGGI>::alloc(&brk_infos);
|
||||
let mut brk: BlindRotationKey<Vec<u8>, BRA> = BlindRotationKey::<Vec<u8>, BRA>::alloc(&brk_infos);
|
||||
|
||||
brk.encrypt_sk(
|
||||
module,
|
||||
@@ -171,12 +122,20 @@ where
|
||||
.enumerate()
|
||||
.for_each(|(i, x)| *x = f(i as i64));
|
||||
|
||||
let mut lut: LookUpTable = LookUpTable::alloc(module, base2k, k_lut, extension_factor);
|
||||
let lut_infos = LookUpTableLayout {
|
||||
n: module.n().into(),
|
||||
extension_factor,
|
||||
k: k_lut.into(),
|
||||
base2k: base2k.into(),
|
||||
};
|
||||
|
||||
let mut lut: LookupTable = LookupTable::alloc(&lut_infos);
|
||||
lut.set(module, &f_vec, log_message_modulus + 1);
|
||||
|
||||
let mut res: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_infos);
|
||||
|
||||
let brk_prepared: BlindRotationKeyPrepared<Vec<u8>, CGGI, B> = brk.prepare_alloc(module, scratch.borrow());
|
||||
let mut brk_prepared: BlindRotationKeyPrepared<Vec<u8>, BRA, BE> = BlindRotationKeyPrepared::alloc(module, &brk);
|
||||
brk_prepared.prepare(module, &brk, scratch_br.borrow());
|
||||
|
||||
brk_prepared.execute(module, &mut res, &lwe, &lut, scratch_br.borrow());
|
||||
|
||||
|
||||
@@ -1,25 +1,12 @@
|
||||
use std::vec;
|
||||
|
||||
use poulpy_hal::{
|
||||
api::{
|
||||
VecZnxCopy, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotateInplace, VecZnxRotateInplaceTmpBytes,
|
||||
VecZnxSwitchRing,
|
||||
},
|
||||
layouts::{Backend, Module},
|
||||
oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeSliceImpl},
|
||||
};
|
||||
use poulpy_hal::api::ModuleN;
|
||||
|
||||
use crate::tfhe::blind_rotation::{DivRound, LookUpTable};
|
||||
use crate::tfhe::blind_rotation::{DivRound, LookUpTableLayout, LookupTable, LookupTableFactory};
|
||||
|
||||
pub fn test_lut_standard<B>(module: &Module<B>)
|
||||
pub fn test_lut_standard<M>(module: &M)
|
||||
where
|
||||
Module<B>: VecZnxRotateInplace<B>
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxSwitchRing
|
||||
+ VecZnxCopy
|
||||
+ VecZnxRotateInplaceTmpBytes,
|
||||
B: Backend + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B> + TakeSliceImpl<B>,
|
||||
M: LookupTableFactory + ModuleN,
|
||||
{
|
||||
let base2k: usize = 20;
|
||||
let k_lut: usize = 40;
|
||||
@@ -33,7 +20,14 @@ where
|
||||
.enumerate()
|
||||
.for_each(|(i, x)| *x = (i as i64) - 8);
|
||||
|
||||
let mut lut: LookUpTable = LookUpTable::alloc(module, base2k, k_lut, extension_factor);
|
||||
let lut_infos: LookUpTableLayout = LookUpTableLayout {
|
||||
n: module.n().into(),
|
||||
extension_factor,
|
||||
k: k_lut.into(),
|
||||
base2k: base2k.into(),
|
||||
};
|
||||
|
||||
let mut lut: LookupTable = LookupTable::alloc(&lut_infos);
|
||||
lut.set(module, &f, log_scale);
|
||||
|
||||
let half_step: i64 = lut.domain_size().div_round(message_modulus << 1) as i64;
|
||||
@@ -51,15 +45,9 @@ where
|
||||
});
|
||||
}
|
||||
|
||||
pub fn test_lut_extended<B>(module: &Module<B>)
|
||||
pub fn test_lut_extended<M>(module: &M)
|
||||
where
|
||||
Module<B>: VecZnxRotateInplace<B>
|
||||
+ VecZnxNormalizeInplace<B>
|
||||
+ VecZnxNormalizeTmpBytes
|
||||
+ VecZnxSwitchRing
|
||||
+ VecZnxCopy
|
||||
+ VecZnxRotateInplaceTmpBytes,
|
||||
B: Backend + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B> + TakeSliceImpl<B>,
|
||||
M: LookupTableFactory + ModuleN,
|
||||
{
|
||||
let base2k: usize = 20;
|
||||
let k_lut: usize = 40;
|
||||
@@ -73,7 +61,14 @@ where
|
||||
.enumerate()
|
||||
.for_each(|(i, x)| *x = (i as i64) - 8);
|
||||
|
||||
let mut lut: LookUpTable = LookUpTable::alloc(module, base2k, k_lut, extension_factor);
|
||||
let lut_infos: LookUpTableLayout = LookUpTableLayout {
|
||||
n: module.n().into(),
|
||||
extension_factor,
|
||||
k: k_lut.into(),
|
||||
base2k: base2k.into(),
|
||||
};
|
||||
|
||||
let mut lut: LookupTable = LookupTable::alloc(&lut_infos);
|
||||
lut.set(module, &f, log_scale);
|
||||
|
||||
let half_step: i64 = lut.domain_size().div_round(message_modulus << 1) as i64;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use poulpy_hal::test_suite::serialization::test_reader_writer_interface;
|
||||
|
||||
use crate::tfhe::blind_rotation::{
|
||||
BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyCompressed, BlindRotationKeyLayout, CGGI,
|
||||
};
|
||||
use crate::tfhe::blind_rotation::{BlindRotationKey, BlindRotationKeyCompressed, BlindRotationKeyLayout, CGGI};
|
||||
|
||||
#[test]
|
||||
fn test_cggi_blind_rotation_key_serialization() {
|
||||
@@ -14,7 +12,6 @@ fn test_cggi_blind_rotation_key_serialization() {
|
||||
dnum: 2_usize.into(),
|
||||
rank: 2_usize.into(),
|
||||
};
|
||||
|
||||
let original: BlindRotationKey<Vec<u8>, CGGI> = BlindRotationKey::alloc(&layout);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
@@ -29,7 +26,6 @@ fn test_cggi_blind_rotation_key_compressed_serialization() {
|
||||
dnum: 2_usize.into(),
|
||||
rank: 2_usize.into(),
|
||||
};
|
||||
|
||||
let original: BlindRotationKeyCompressed<Vec<u8>, CGGI> = BlindRotationKeyCompressed::alloc(&layout);
|
||||
test_reader_writer_interface(original);
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
use poulpy_backend::cpu_spqlios::FFT64Spqlios;
|
||||
use poulpy_hal::{api::ModuleNew, layouts::Module};
|
||||
|
||||
use crate::tfhe::blind_rotation::tests::{
|
||||
generic_blind_rotation::test_blind_rotation,
|
||||
generic_lut::{test_lut_extended, test_lut_standard},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn lut_standard() {
|
||||
let module: Module<FFT64Spqlios> = Module::<FFT64Spqlios>::new(32);
|
||||
test_lut_standard(&module);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lut_extended() {
|
||||
let module: Module<FFT64Spqlios> = Module::<FFT64Spqlios>::new(32);
|
||||
test_lut_extended(&module);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn standard() {
|
||||
let module: Module<FFT64Spqlios> = Module::<FFT64Spqlios>::new(512);
|
||||
test_blind_rotation(&module, 224, 1, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn block_binary() {
|
||||
let module: Module<FFT64Spqlios> = Module::<FFT64Spqlios>::new(512);
|
||||
test_blind_rotation(&module, 224, 7, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn block_binary_extended() {
|
||||
let module: Module<FFT64Spqlios> = Module::<FFT64Spqlios>::new(512);
|
||||
test_blind_rotation(&module, 224, 7, 2);
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
mod fft64;
|
||||
@@ -0,0 +1,40 @@
|
||||
use poulpy_backend::cpu_fft64_ref::FFT64Ref;
|
||||
use poulpy_hal::{api::ModuleNew, layouts::Module};
|
||||
|
||||
use crate::tfhe::blind_rotation::{
|
||||
CGGI,
|
||||
tests::{
|
||||
generic_blind_rotation::test_blind_rotation,
|
||||
generic_lut::{test_lut_extended, test_lut_standard},
|
||||
},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn lut_standard() {
|
||||
let module: Module<FFT64Ref> = Module::<FFT64Ref>::new(32);
|
||||
test_lut_standard(&module);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lut_extended() {
|
||||
let module: Module<FFT64Ref> = Module::<FFT64Ref>::new(32);
|
||||
test_lut_extended(&module);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn standard() {
|
||||
let module: Module<FFT64Ref> = Module::<FFT64Ref>::new(512);
|
||||
test_blind_rotation::<CGGI, _, FFT64Ref>(&module, 224, 1, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn block_binary() {
|
||||
let module: Module<FFT64Ref> = Module::<FFT64Ref>::new(512);
|
||||
test_blind_rotation::<CGGI, _, FFT64Ref>(&module, 224, 7, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn block_binary_extended() {
|
||||
let module: Module<FFT64Ref> = Module::<FFT64Ref>::new(512);
|
||||
test_blind_rotation::<CGGI, _, FFT64Ref>(&module, 224, 7, 2);
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
mod cpu_spqlios;
|
||||
mod fft64;
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
use poulpy_core::layouts::{
|
||||
AutomorphismKey, AutomorphismKeyLayout, GGLWEInfos, GGSWInfos, GLWE, GLWEInfos, GLWESecret, LWEInfos, LWESecret, TensorKey,
|
||||
TensorKeyLayout,
|
||||
prepared::{GLWEAutomorphismKeyPrepared, GLWESecretPrepared, PrepareAlloc, TensorKeyPrepared},
|
||||
prepared::{GLWEAutomorphismKeyPrepared, GLWESecretPrepared, TensorKeyPrepared},
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use poulpy_hal::{
|
||||
api::{
|
||||
ScratchAvailable, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, TakeScalarZnx,
|
||||
TakeSvpPPol, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace,
|
||||
ScratchAvailable, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace,
|
||||
VecZnxAutomorphism, VecZnxBigNormalize, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume,
|
||||
VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace,
|
||||
VecZnxSwitchRing, VmpPMatAlloc, VmpPrepare,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
mod circuit;
|
||||
mod key;
|
||||
pub mod tests;
|
||||
|
||||
//[cfg(tests)]
|
||||
//pub mod tests;
|
||||
|
||||
pub use circuit::*;
|
||||
pub use key::*;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
pub mod circuit_bootstrapping;
|
||||
|
||||
#[cfg(test)]
|
||||
mod implementation;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
pub mod bdd_arithmetic;
|
||||
// pub mod bdd_arithmetic;
|
||||
pub mod blind_rotation;
|
||||
pub mod circuit_bootstrapping;
|
||||
//pub mod circuit_bootstrapping;
|
||||
|
||||
Reference in New Issue
Block a user