core refactoring (#69)
jump to
@@ -1,4 +1,4 @@
-use core::{GGSWCiphertext, GGSWCiphertextExec, GLWECiphertext, GLWESecret, GLWESecretExec, Infos}; +use core::layouts::{prepared::{GGSWCiphertextExec, GLWESecretExec}, GGSWCiphertext, GLWECiphertext, GLWESecret, Infos}; use std::hint::black_box; use backend::{
@@ -1,7 +1,4 @@
-use core::{ - AutomorphismKey, AutomorphismKeyExec, GLWECiphertext, GLWESecret, GLWESecretExec, GLWESwitchingKey, GLWESwitchingKeyExec, - Infos, -}; +use core::layouts::{prepared::{GGLWEAutomorphismKeyExec, GGLWESwitchingKeyExec, GLWESecretExec}, GGLWEAutomorphismKey, GGLWESwitchingKey, GLWECiphertext, GLWESecret, Infos}; use std::{hint::black_box, time::Duration}; use backend::{@@ -43,12 +40,12 @@
let rows: usize = p.k_ct_in.div_ceil(p.basek * digits); let sigma: f64 = 3.2; - let mut ksk: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_grlwe, rows, digits, rank_out); + let mut ksk: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_grlwe, rows, digits, rank_out); let mut ct_in: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_rlwe_in, rank_in); let mut ct_out: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_rlwe_out, rank_out); let mut scratch: ScratchOwned<FFT64> = ScratchOwned::alloc( - GLWESwitchingKey::encrypt_sk_scratch_space(&module, n, basek, ksk.k(), rank_in, rank_out) + GGLWESwitchingKey::encrypt_sk_scratch_space(&module, n, basek, ksk.k(), rank_in, rank_out) | GLWECiphertext::encrypt_sk_scratch_space(&module, n, basek, ct_in.k()) | GLWECiphertext::keyswitch_scratch_space( &module,@@ -93,7 +90,7 @@ sigma,
scratch.borrow(), ); - let ksk_exec: AutomorphismKeyExec<Vec<u8>, _> = AutomorphismKeyExec::from(&module, &ksk, scratch.borrow()); + let ksk_exec: GGLWEAutomorphismKeyExec<Vec<u8>, _> = GGLWEAutomorphismKeyExec::from(&module, &ksk, scratch.borrow()); move || { black_box(ct_out.automorphism(&module, &ct_in, &ksk_exec, scratch.borrow()));@@ -149,11 +146,11 @@
let rows: usize = p.k_ct.div_ceil(p.basek); let sigma: f64 = 3.2; - let mut ksk: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank, rank); + let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank, rank); let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank); let mut scratch: ScratchOwned<FFT64> = ScratchOwned::alloc( - GLWESwitchingKey::encrypt_sk_scratch_space(&module, n, basek, ksk.k(), rank, rank) + GGLWESwitchingKey::encrypt_sk_scratch_space(&module, n, basek, ksk.k(), rank, rank) | GLWECiphertext::encrypt_sk_scratch_space(&module, n, basek, ct.k()) | GLWECiphertext::keyswitch_inplace_scratch_space(&module, n, basek, ct.k(), ksk.k(), digits, rank), );@@ -188,7 +185,7 @@ sigma,
scratch.borrow(), ); - let ksk_exec: GLWESwitchingKeyExec<Vec<u8>, FFT64> = GLWESwitchingKeyExec::from(&module, &ksk, scratch.borrow()); + let ksk_exec: GGLWESwitchingKeyExec<Vec<u8>, FFT64> = GGLWESwitchingKeyExec::from(&module, &ksk, scratch.borrow()); move || { black_box(ct.keyswitch_inplace(&module, &ksk_exec, scratch.borrow()));
@@ -11,10 +11,11 @@ };
use itertools::izip; use crate::{ - GLWECiphertext, GLWECiphertextToMut, GLWEExternalProductFamily, GLWEOps, Infos, LWECiphertext, LWECiphertextToRef, - LookUpTableRotationDirection, TakeGLWECt, + GLWEOps, Infos, LookUpTableRotationDirection, TakeGLWECt, blind_rotation::{key::BlindRotationKeyCGGIExec, lut::LookUpTable}, dist::Distribution, + layouts::{GLWECiphertext, GLWECiphertextToMut, LWECiphertext, LWECiphertextToRef}, + trait_families::GLWEExternalProductFamily, }; pub trait CCGIBlindRotationFamily<B: Backend> = VecZnxBigAllocBytes
@@ -1,16 +1,22 @@
use backend::hal::{ api::{ FillUniform, Reset, ScratchAvailable, SvpPPolAlloc, SvpPrepare, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, - ZnxInfos, ZnxView, ZnxViewMut, + VmpPMatAlloc, VmpPMatPrepare, ZnxInfos, ZnxView, ZnxViewMut, }, layouts::{Backend, Data, DataMut, DataRef, Module, ReaderFrom, ScalarZnx, ScalarZnxToRef, Scratch, SvpPPol, WriterTo}, }; use sampling::source::Source; use crate::{ - Distribution, GGSWCiphertext, GGSWCiphertextExec, GGSWEncryptSkFamily, GGSWLayoutFamily, GLWESecretExec, Infos, LWESecret, + Distribution, Infos, + layouts::{ + GGSWCiphertext, LWESecret, + prepared::{GGSWCiphertextExec, GLWESecretExec}, + }, }; use std::fmt; + +use crate::trait_families::GGSWEncryptSkFamily; #[derive(Clone)] pub struct BlindRotationKeyCGGI<D: Data> {@@ -246,12 +252,12 @@ }
} } -pub trait BlindRotationKeyCGGIExecLayoutFamily<B: Backend> = GGSWLayoutFamily<B> + SvpPPolAlloc<B> + SvpPrepare<B>; +pub trait BlindRotationKeyCGGIExecLayoutFamily<B: Backend> = SvpPPolAlloc<B> + SvpPrepare<B>; impl<B: Backend> BlindRotationKeyCGGIExec<Vec<u8>, B> { pub fn alloc(module: &Module<B>, n_glwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self where - Module<B>: BlindRotationKeyCGGIExecLayoutFamily<B>, + Module<B>: BlindRotationKeyCGGIExecLayoutFamily<B> + VmpPMatAlloc<B> + VmpPMatPrepare<B>, { let mut data: Vec<GGSWCiphertextExec<Vec<u8>, B>> = Vec::with_capacity(n_lwe); (0..n_lwe).for_each(|_| {@@ -269,7 +275,7 @@
pub fn from<DataOther>(module: &Module<B>, other: &BlindRotationKeyCGGI<DataOther>, scratch: &mut Scratch<B>) -> Self where DataOther: DataRef, - Module<B>: BlindRotationKeyCGGIExecLayoutFamily<B>, + Module<B>: BlindRotationKeyCGGIExecLayoutFamily<B> + VmpPMatAlloc<B> + VmpPMatPrepare<B>, { let mut brk: BlindRotationKeyCGGIExec<Vec<u8>, B> = Self::alloc( module,@@ -289,7 +295,7 @@ impl<D: DataMut, B: Backend> BlindRotationKeyCGGIExec<D, B> {
pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &BlindRotationKeyCGGI<DataOther>, scratch: &mut Scratch<B>) where DataOther: DataRef, - Module<B>: BlindRotationKeyCGGIExecLayoutFamily<B>, + Module<B>: BlindRotationKeyCGGIExecLayoutFamily<B> + VmpPMatAlloc<B> + VmpPMatPrepare<B>, { #[cfg(debug_assertions)] {
@@ -4,8 +4,13 @@ layouts::{Backend, Data, DataMut, DataRef, Module, ReaderFrom, ScalarZnx, ScalarZnxToRef, Scratch, WriterTo},
}; use sampling::source::Source; -use crate::{Distribution, GGSWCiphertextCompressed, GGSWEncryptSkFamily, GLWESecretExec, Infos, LWESecret}; +use crate::{ + Distribution, Infos, + layouts::{LWESecret, compressed::GGSWCiphertextCompressed, prepared::GLWESecretExec}, +}; use std::fmt; + +use crate::trait_families::GGSWEncryptSkFamily; #[derive(Clone)] pub struct BlindRotationKeyCGGICompressed<D: Data> {
@@ -1,7 +1,7 @@
use backend::hal::{ api::{ ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxEncodeCoeffsi64, VecZnxFillUniform, - VecZnxRotateInplace, VecZnxSub, VecZnxSwithcDegree, ZnxView, + VecZnxRotateInplace, VecZnxSub, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, ZnxView, }, layouts::{Backend, Module, ScratchOwned}, oep::{@@ -12,13 +12,19 @@ };
use sampling::source::Source; use crate::{ - BlindRotationKeyCGGI, BlindRotationKeyCGGIExec, BlindRotationKeyCGGIExecLayoutFamily, CCGIBlindRotationFamily, - GLWECiphertext, GLWEDecryptFamily, GLWEPlaintext, GLWESecret, GLWESecretExec, GLWESecretFamily, Infos, LWECiphertext, - LWECiphertextToRef, LWEPlaintext, LWESecret, LookUpTable, cggi_blind_rotate, cggi_blind_rotate_scratch_space, mod_switch_2n, + BlindRotationKeyCGGI, BlindRotationKeyCGGIExec, BlindRotationKeyCGGIExecLayoutFamily, CCGIBlindRotationFamily, Infos, + LookUpTable, cggi_blind_rotate, cggi_blind_rotate_scratch_space, + layouts::{ + GLWECiphertext, GLWEPlaintext, GLWESecret, LWECiphertext, LWECiphertextToRef, LWEPlaintext, LWESecret, + prepared::GLWESecretExec, + }, + mod_switch_2n, }; +use crate::trait_families::{GLWEDecryptFamily, GLWESecretExecModuleFamily}; + pub(crate) trait CGGITestModuleFamily<B: Backend> = CCGIBlindRotationFamily<B> - + GLWESecretFamily<B> + + GLWESecretExecModuleFamily<B> + GLWEDecryptFamily<B> + BlindRotationKeyCGGIExecLayoutFamily<B> + VecZnxFillUniform@@ -27,7 +33,9 @@ + VecZnxAddScalarInplace
+ VecZnxEncodeCoeffsi64 + VecZnxRotateInplace + VecZnxSwithcDegree - + VecZnxSub; + + VecZnxSub + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>; pub(crate) trait CGGITestScratchFamily<B: Backend> = VecZnxDftAllocBytesImpl<B> + VecZnxBigAllocBytesImpl<B> + ScratchOwnedAllocImpl<B>
@@ -6,7 +6,7 @@ ScratchAvailable, TakeMatZnx, TakeScalarZnx, TakeSvpPPol, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, TakeVecZnxDftSlice,
TakeVecZnxSlice, VecZnxAddInplace, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxBigAutomorphismInplace, VecZnxBigSubSmallBInplace, VecZnxCopy, VecZnxDftCopy, VecZnxDftToVecZnxBigTmpA, VecZnxNegateInplace, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotateInplace, VecZnxRshInplace, VecZnxSub, - VecZnxSubABInplace, VecZnxSwithcDegree, + VecZnxSubABInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, }, layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}, oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl},@@ -14,11 +14,17 @@ };
use sampling::source::Source; use crate::{ - AutomorphismKey, AutomorphismKeyEncryptSkFamily, AutomorphismKeyExec, BlindRotationKeyCGGI, BlindRotationKeyCGGIExec, - BlindRotationKeyCGGIExecLayoutFamily, CCGIBlindRotationFamily, GGSWCiphertext, GGSWEncryptSkFamily, GLWECiphertext, GLWEOps, - GLWESecret, GLWESecretExec, GLWESecretFamily, GLWETensorKey, GLWETensorKeyEncryptSkFamily, GLWETensorKeyExec, - GLWETraceFamily, Infos, LWECiphertext, LWESecret, LookUpTable, LookUpTableRotationDirection, TakeGGLWE, TakeGLWECt, - cggi_blind_rotate, + BlindRotationKeyCGGI, BlindRotationKeyCGGIExec, BlindRotationKeyCGGIExecLayoutFamily, CCGIBlindRotationFamily, GLWEOps, + Infos, LookUpTable, LookUpTableRotationDirection, TakeGGLWE, TakeGLWECt, cggi_blind_rotate, + layouts::{ + AutomorphismKey, GGSWCiphertext, GLWECiphertext, GLWESecret, GLWETensorKey, LWECiphertext, LWESecret, + prepared::{AutomorphismKeyExec, GLWESecretExec, GLWETensorKeyExec}, + }, +}; + +use crate::trait_families::{ + AutomorphismKeyEncryptSkFamily, GGSWEncryptSkFamily, GLWESecretExecModuleFamily, GLWETensorKeyEncryptSkFamily, + GLWETraceModuleFamily, }; pub struct CircuitBootstrappingKeyCGGI<D: Data> {@@ -45,8 +51,8 @@ sigma: f64,
scratch: &mut Scratch<B>, ) -> Self where - Module<B>: GLWESecretFamily<B> - + GGSWEncryptSkFamily<B> + Module<B>: GGSWEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + VecZnxAddScalarInplace + AutomorphismKeyEncryptSkFamily<B> + VecZnxAutomorphism@@ -111,7 +117,7 @@ other: &CircuitBootstrappingKeyCGGI<DataOther>,
scratch: &mut Scratch<B>, ) -> CircuitBootstrappingKeyCGGIExec<Vec<u8>, B> where - Module<B>: BlindRotationKeyCGGIExecLayoutFamily<B>, + Module<B>: BlindRotationKeyCGGIExecLayoutFamily<B> + VmpPMatAlloc<B> + VmpPMatPrepare<B>, { let brk: BlindRotationKeyCGGIExec<Vec<u8>, B> = BlindRotationKeyCGGIExec::from(module, &other.brk, scratch); let tsk: GLWETensorKeyExec<Vec<u8>, B> = GLWETensorKeyExec::from(module, &other.tsk, scratch);@@ -137,7 +143,7 @@ + VecZnxAddInplace
+ VecZnxNegateInplace + VecZnxCopy + VecZnxSubABInplace - + GLWETraceFamily<B> + + GLWETraceModuleFamily<B> + VecZnxRotateInplace + VecZnxAutomorphismInplace + VecZnxBigSubSmallBInplace<B>;
@@ -5,7 +5,7 @@ hal::{
api::{ ModuleNew, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxEncodeCoeffsi64, VecZnxFillUniform, VecZnxNormalizeInplace, VecZnxRotateInplace, VecZnxStd, VecZnxSwithcDegree, - ZnxView, ZnxViewMut, + VmpPMatAlloc, VmpPMatPrepare, ZnxView, ZnxViewMut, }, layouts::{Backend, Module, ScalarZnx, ScratchOwned}, oep::{@@ -18,14 +18,19 @@ };
use sampling::source::Source; use crate::{ - AutomorphismKeyEncryptSkFamily, BlindRotationKeyCGGIExecLayoutFamily, GGSWAssertNoiseFamily, GGSWCiphertext, - GGSWCiphertextExec, GGSWEncryptSkFamily, GLWECiphertext, GLWEDecryptFamily, GLWEPlaintext, GLWESecret, GLWESecretExec, - GLWESecretFamily, GLWETensorKeyEncryptSkFamily, LWECiphertext, LWESecret, + BlindRotationKeyCGGIExecLayoutFamily, circuit_bootstrapping::circuit_bootstrapping::{ CGGICircuitBootstrapFamily, CircuitBootstrappingKeyCGGI, CircuitBootstrappingKeyCGGIExec, circuit_bootstrap_to_constant_cggi, circuit_bootstrap_to_exponent_cggi, }, - lwe::LWEPlaintext, + layouts::{ + GGSWCiphertext, GLWECiphertext, GLWEPlaintext, GLWESecret, LWECiphertext, LWEPlaintext, LWESecret, + prepared::{GGSWCiphertextExec, GLWESecretExec}, + }, +}; + +use crate::trait_families::{ + AutomorphismKeyEncryptSkFamily, GGSWAssertNoiseFamily, GGSWEncryptSkFamily, GLWEDecryptFamily, GLWETensorKeyEncryptSkFamily, }; #[test]@@ -36,12 +41,10 @@ }
fn to_exponent<B: Backend>(module: &Module<B>) where - Module<B>: GLWESecretFamily<B> - + VecZnxEncodeCoeffsi64 + Module<B>: VecZnxEncodeCoeffsi64 + VecZnxFillUniform + VecZnxAddNormal + VecZnxNormalizeInplace<B> - + GLWESecretFamily<B> + GGSWEncryptSkFamily<B> + VecZnxAddScalarInplace + AutomorphismKeyEncryptSkFamily<B>@@ -52,7 +55,9 @@ + BlindRotationKeyCGGIExecLayoutFamily<B>
+ CGGICircuitBootstrapFamily<B> + GLWEDecryptFamily<B> + GGSWAssertNoiseFamily<B> - + VecZnxStd, + + VecZnxStd + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>, B: ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B> + TakeVecZnxDftImpl<B>@@ -202,12 +207,10 @@ }
fn to_constant<B: Backend>(module: &Module<B>) where - Module<B>: GLWESecretFamily<B> - + VecZnxEncodeCoeffsi64 + Module<B>: VecZnxEncodeCoeffsi64 + VecZnxFillUniform + VecZnxAddNormal + VecZnxNormalizeInplace<B> - + GLWESecretFamily<B> + GGSWEncryptSkFamily<B> + VecZnxAddScalarInplace + AutomorphismKeyEncryptSkFamily<B>@@ -218,7 +221,9 @@ + BlindRotationKeyCGGIExecLayoutFamily<B>
+ CGGICircuitBootstrapFamily<B> + GLWEDecryptFamily<B> + GGSWAssertNoiseFamily<B> - + VecZnxStd, + + VecZnxStd + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>, B: ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B> + TakeVecZnxDftImpl<B>
@@ -0,0 +1,70 @@
+use backend::hal::{ + api::{ScratchAvailable, TakeVecZnx, TakeVecZnxDft, ZnxView, ZnxViewMut, ZnxZero}, + layouts::{Backend, DataMut, DataRef, Module, Scratch}, +}; + +use crate::{ + TakeGLWECt, + layouts::{GLWECiphertext, Infos, LWECiphertext, prepared::GLWEToLWESwitchingKeyExec}, +}; + +use crate::trait_families::GLWEKeyswitchFamily; + +impl LWECiphertext<Vec<u8>> { + pub fn from_glwe_scratch_space<B: Backend>( + module: &Module<B>, + n: usize, + basek: usize, + k_lwe: usize, + k_glwe: usize, + k_ksk: usize, + rank: usize, + ) -> usize + where + Module<B>: GLWEKeyswitchFamily<B>, + { + GLWECiphertext::bytes_of(n, basek, k_lwe, 1) + + GLWECiphertext::keyswitch_scratch_space(module, n, basek, k_lwe, k_glwe, k_ksk, 1, rank, 1) + } +} + +impl<DLwe: DataMut> LWECiphertext<DLwe> { + pub fn sample_extract<DGlwe: DataRef>(&mut self, a: &GLWECiphertext<DGlwe>) { + #[cfg(debug_assertions)] + { + assert!(self.n() <= a.n()); + } + + let min_size: usize = self.size().min(a.size()); + let n: usize = self.n(); + + self.data.zero(); + (0..min_size).for_each(|i| { + let data_lwe: &mut [i64] = self.data.at_mut(0, i); + data_lwe[0] = a.data.at(0, i)[0]; + data_lwe[1..].copy_from_slice(&a.data.at(1, i)[..n]); + }); + } + + pub fn from_glwe<DGlwe, DKs, B: Backend>( + &mut self, + module: &Module<B>, + a: &GLWECiphertext<DGlwe>, + ks: &GLWEToLWESwitchingKeyExec<DKs, B>, + scratch: &mut Scratch<B>, + ) where + DGlwe: DataRef, + DKs: DataRef, + Module<B>: GLWEKeyswitchFamily<B>, + Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + { + #[cfg(debug_assertions)] + { + assert_eq!(self.basek(), a.basek()); + assert_eq!(a.n(), ks.n()); + } + let (mut tmp_glwe, scratch1) = scratch.take_glwe_ct(a.n(), a.basek(), self.k(), 1); + tmp_glwe.keyswitch(module, a, &ks.0, scratch1); + self.sample_extract(&tmp_glwe); + } +}
@@ -0,0 +1,63 @@
+use backend::hal::{ + api::{ScratchAvailable, TakeVecZnx, TakeVecZnxDft, ZnxView, ZnxViewMut, ZnxZero}, + layouts::{Backend, DataMut, DataRef, Module, Scratch}, +}; + +use crate::{ + TakeGLWECt, + layouts::{GLWECiphertext, Infos, LWECiphertext, prepared::LWEToGLWESwitchingKeyExec}, +}; + +use crate::trait_families::GLWEKeyswitchFamily; + +impl GLWECiphertext<Vec<u8>> { + pub fn from_lwe_scratch_space<B: Backend>( + module: &Module<B>, + n: usize, + basek: usize, + k_lwe: usize, + k_glwe: usize, + k_ksk: usize, + rank: usize, + ) -> usize + where + Module<B>: GLWEKeyswitchFamily<B>, + { + GLWECiphertext::keyswitch_scratch_space(module, n, basek, k_glwe, k_lwe, k_ksk, 1, 1, rank) + + GLWECiphertext::bytes_of(n, basek, k_lwe, 1) + } +} + +impl<D: DataMut> GLWECiphertext<D> { + pub fn from_lwe<DLwe, DKsk, B: Backend>( + &mut self, + module: &Module<B>, + lwe: &LWECiphertext<DLwe>, + ksk: &LWEToGLWESwitchingKeyExec<DKsk, B>, + scratch: &mut Scratch<B>, + ) where + DLwe: DataRef, + DKsk: DataRef, + Module<B>: GLWEKeyswitchFamily<B>, + Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + { + #[cfg(debug_assertions)] + { + assert!(lwe.n() <= self.n()); + assert_eq!(self.basek(), self.basek()); + } + + let (mut glwe, scratch1) = scratch.take_glwe_ct(ksk.n(), lwe.basek(), lwe.k(), 1); + glwe.data.zero(); + + let n_lwe: usize = lwe.n(); + + (0..lwe.size()).for_each(|i| { + let data_lwe: &[i64] = lwe.data.at(0, i); + glwe.data.at_mut(0, i)[0] = data_lwe[0]; + glwe.data.at_mut(1, i)[..n_lwe].copy_from_slice(&data_lwe[1..]); + }); + + self.keyswitch(module, &glwe, &ksk.0, scratch1); + } +}
@@ -1,7 +1,4 @@
-use backend::hal::{ - api::{VecZnxCopy, VecZnxFillUniform, ZnxInfos}, - layouts::{Backend, Module}, -}; +use backend::hal::api::ZnxInfos; pub trait Infos { type Inner: ZnxInfos;@@ -55,9 +52,3 @@ pub trait SetMetaData {
fn set_basek(&mut self, basek: usize); fn set_k(&mut self, k: usize); } - -pub trait Decompress<B: Backend, C> { - fn decompress(&mut self, module: &Module<B>, other: &C) - where - Module<B>: VecZnxFillUniform + VecZnxCopy; -}
@@ -0,0 +1,88 @@
+use backend::hal::{ + api::{ + ScratchAvailable, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, VecZnxAutomorphism, + VecZnxSwithcDegree, + }, + layouts::{Backend, DataMut, DataRef, Module, Scratch}, +}; +use sampling::source::Source; + +use crate::{ + TakeGLWESecret, TakeGLWESecretExec, + layouts::{ + GLWESecret, Infos, + compressed::{GGLWEAutomorphismKeyCompressed, GGLWESwitchingKeyCompressed}, + }, +}; + +use crate::trait_families::{GGLWEAutomorphismKeyEncryptSkFamily, GLWESecretExecModuleFamily}; + +impl GGLWEAutomorphismKeyCompressed<Vec<u8>> { + pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize + where + Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + { + GGLWESwitchingKeyCompressed::encrypt_sk_scratch_space(module, n, basek, k, rank, rank) + GLWESecret::bytes_of(n, rank) + } +} + +impl<DataSelf: DataMut> GGLWEAutomorphismKeyCompressed<DataSelf> { + pub fn encrypt_sk<DataSk: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + p: i64, + sk: &GLWESecret<DataSk>, + seed_xa: [u8; 32], + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> + + VecZnxSwithcDegree + + VecZnxAutomorphism + + VecZnxAddScalarInplace + + GLWESecretExecModuleFamily<B>, + Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + TakeVecZnx, + { + #[cfg(debug_assertions)] + { + assert_eq!(self.n(), sk.n()); + assert_eq!(self.rank_out(), self.rank_in()); + assert_eq!(sk.rank(), self.rank()); + assert!( + scratch.available() + >= GGLWEAutomorphismKeyCompressed::encrypt_sk_scratch_space( + module, + sk.n(), + self.basek(), + self.k(), + self.rank() + ), + "scratch.available(): {} < AutomorphismKey::encrypt_sk_scratch_space(module, self.rank()={}, self.size()={}): {}", + scratch.available(), + self.rank(), + self.size(), + GGLWEAutomorphismKeyCompressed::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k(), self.rank()) + ) + } + + let (mut sk_out, scratch_1) = scratch.take_glwe_secret(sk.n(), sk.rank()); + + { + (0..self.rank()).for_each(|i| { + module.vec_znx_automorphism( + module.galois_element_inv(p), + &mut sk_out.data.as_vec_znx_mut(), + i, + &sk.data.as_vec_znx(), + i, + ); + }); + } + + self.key + .encrypt_sk(module, &sk, &sk_out, seed_xa, source_xe, sigma, scratch_1); + + self.p = p; + } +}
@@ -0,0 +1,121 @@
+use backend::hal::{ + api::{ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, VecZnxNormalizeInplace, ZnxZero}, + layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch}, +}; +use sampling::source::Source; + +use crate::{ + TakeGLWEPt, + encryption::glwe_encrypt_sk_internal, + layouts::{GGLWECiphertext, Infos, compressed::GGLWECiphertextCompressed, prepared::GLWESecretExec}, +}; + +use crate::trait_families::{GGLWEEncryptSkFamily, GGLWESwitchingKeyEncryptSkFamily}; + +impl GGLWECiphertextCompressed<Vec<u8>> { + pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize) -> usize + where + Module<B>: GGLWESwitchingKeyEncryptSkFamily<B>, + { + GGLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) + } +} + +impl<D: DataMut> GGLWECiphertextCompressed<D> { + pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + pt: &ScalarZnx<DataPt>, + sk: &GLWESecretExec<DataSk, B>, + seed: [u8; 32], + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + Module<B>: GGLWEEncryptSkFamily<B> + VecZnxAddScalarInplace, + Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + { + #[cfg(debug_assertions)] + { + use backend::hal::api::ZnxInfos; + + assert_eq!( + self.rank_in(), + pt.cols(), + "self.rank_in(): {} != pt.cols(): {}", + self.rank_in(), + pt.cols() + ); + assert_eq!( + self.rank_out(), + sk.rank(), + "self.rank_out(): {} != sk.rank(): {}", + self.rank_out(), + sk.rank() + ); + assert_eq!(self.n(), sk.n()); + assert_eq!(pt.n(), sk.n()); + assert!( + scratch.available() + >= GGLWECiphertextCompressed::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k()), + "scratch.available: {} < GGLWECiphertext::encrypt_sk_scratch_space(module, self.rank()={}, self.size()={}): {}", + scratch.available(), + self.rank(), + self.size(), + GGLWECiphertextCompressed::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k()) + ); + assert!( + self.rows() * self.digits() * self.basek() <= self.k(), + "self.rows() : {} * self.digits() : {} * self.basek() : {} = {} >= self.k() = {}", + self.rows(), + self.digits(), + self.basek(), + self.rows() * self.digits() * self.basek(), + self.k() + ); + } + + let rows: usize = self.rows(); + let digits: usize = self.digits(); + let basek: usize = self.basek(); + let k: usize = self.k(); + let rank_in: usize = self.rank_in(); + let cols: usize = self.rank_out() + 1; + + let mut source_xa = Source::new(seed); + + let (mut tmp_pt, scrach_1) = scratch.take_glwe_pt(sk.n(), basek, k); + (0..rank_in).for_each(|col_i| { + (0..rows).for_each(|row_i| { + // Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt + tmp_pt.data.zero(); // zeroes for next iteration + module.vec_znx_add_scalar_inplace( + &mut tmp_pt.data, + 0, + (digits - 1) + row_i * digits, + pt, + col_i, + ); + module.vec_znx_normalize_inplace(basek, &mut tmp_pt.data, 0, scrach_1); + + let (seed, mut source_xa_tmp) = source_xa.branch(); + self.seed[col_i * rows + row_i] = seed; + + glwe_encrypt_sk_internal( + module, + self.basek(), + self.k(), + &mut self.at_mut(row_i, col_i).data, + cols, + true, + Some((&tmp_pt, 0)), + sk, + &mut source_xa_tmp, + source_xe, + sigma, + scrach_1, + ); + }); + }); + } +}
@@ -0,0 +1,109 @@
+use backend::hal::{ + api::{ScratchAvailable, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, VecZnxSwithcDegree}, + layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch}, +}; +use sampling::source::Source; + +use crate::{ + TakeGLWESecretExec, + layouts::{ + GGLWECiphertext, GLWESecret, GGLWESwitchingKey, Infos, compressed::GGLWESwitchingKeyCompressed, prepared::GLWESecretExec, + }, +}; + +use crate::trait_families::{GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; + +impl GGLWESwitchingKeyCompressed<Vec<u8>> { + pub fn encrypt_sk_scratch_space<B: Backend>( + module: &Module<B>, + n: usize, + basek: usize, + k: usize, + rank_in: usize, + rank_out: usize, + ) -> usize + where + Module<B>: GGLWESwitchingKeyEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + { + (GGLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) | ScalarZnx::alloc_bytes(n, 1)) + + ScalarZnx::alloc_bytes(n, rank_in) + + GLWESecretExec::bytes_of(module, n, rank_out) + } +} + +impl<DataSelf: DataMut> GGLWESwitchingKeyCompressed<DataSelf> { + pub fn encrypt_sk<DataSkIn: DataRef, DataSkOut: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + sk_in: &GLWESecret<DataSkIn>, + sk_out: &GLWESecret<DataSkOut>, + seed_xa: [u8; 32], + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + Module<B>: + GGLWESwitchingKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWESecretExecModuleFamily<B>, + Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + ScratchAvailable + TakeVecZnx, + { + #[cfg(debug_assertions)] + { + assert!(sk_in.n() <= module.n()); + assert!(sk_out.n() <= module.n()); + assert!( + scratch.available() + >= GGLWESwitchingKey::encrypt_sk_scratch_space( + module, + sk_out.n(), + self.basek(), + self.k(), + self.rank_in(), + self.rank_out() + ), + "scratch.available()={} < GLWESwitchingKey::encrypt_sk_scratch_space={}", + scratch.available(), + GGLWESwitchingKey::encrypt_sk_scratch_space( + module, + sk_out.n(), + self.basek(), + self.k(), + self.rank_in(), + self.rank_out() + ) + ) + } + + let n: usize = sk_in.n().max(sk_out.n()); + + let (mut sk_in_tmp, scratch1) = scratch.take_scalar_znx(n, sk_in.rank()); + (0..sk_in.rank()).for_each(|i| { + module.vec_znx_switch_degree( + &mut sk_in_tmp.as_vec_znx_mut(), + i, + &sk_in.data.as_vec_znx(), + i, + ); + }); + + let (mut sk_out_tmp, scratch2) = scratch1.take_glwe_secret_exec(n, sk_out.rank()); + { + let (mut tmp, _) = scratch2.take_scalar_znx(n, 1); + (0..sk_out.rank()).for_each(|i| { + module.vec_znx_switch_degree(&mut tmp.as_vec_znx_mut(), 0, &sk_out.data.as_vec_znx(), i); + module.svp_prepare(&mut sk_out_tmp.data, i, &tmp, 0); + }); + } + + self.key.encrypt_sk( + module, + &sk_in_tmp, + &sk_out_tmp, + seed_xa, + source_xe, + sigma, + scratch2, + ); + self.sk_in_n = sk_in.n(); + self.sk_out_n = sk_out.n(); + } +}
@@ -0,0 +1,85 @@
+use backend::hal::{ + api::{ + ScratchAvailable, SvpApply, TakeScalarZnx, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, VecZnxAddScalarInplace, + VecZnxDftToVecZnxBigTmpA, VecZnxSwithcDegree, + }, + layouts::{Backend, DataMut, DataRef, Module, Scratch}, +}; +use sampling::source::Source; + +use crate::{ + TakeGLWESecret, TakeGLWESecretExec, + layouts::{GGLWETensorKey, GLWESecret, Infos, compressed::GGLWETensorKeyCompressed}, + trait_families::GLWEDecryptFamily, +}; + +use crate::trait_families::{GGLWETensorKeyEncryptSkFamily, GLWESecretExecModuleFamily}; + +impl GGLWETensorKeyCompressed<Vec<u8>> { + pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize + where + Module<B>: GGLWETensorKeyEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + { + GGLWETensorKey::encrypt_sk_scratch_space(module, n, basek, k, rank) + } +} + +impl<DataSelf: DataMut> GGLWETensorKeyCompressed<DataSelf> { + pub fn encrypt_sk<DataSk: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + sk: &GLWESecret<DataSk>, + seed_xa: [u8; 32], + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + Module<B>: GGLWETensorKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWESecretExecModuleFamily<B>, + Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeGLWESecretExec<B> + TakeScalarZnx + TakeVecZnx, + { + #[cfg(debug_assertions)] + { + assert_eq!(self.rank(), sk.rank()); + assert_eq!(self.n(), sk.n()); + } + + let n: usize = sk.n(); + let rank: usize = self.rank(); + + let (mut sk_dft_prep, scratch1) = scratch.take_glwe_secret_exec(n, rank); + sk_dft_prep.prepare(module, &sk); + + let (mut sk_dft, scratch2) = scratch1.take_vec_znx_dft(n, rank, 1); + + (0..rank).for_each(|i| { + module.vec_znx_dft_from_vec_znx(1, 0, &mut sk_dft, i, &sk.data.as_vec_znx(), i); + }); + + let (mut sk_ij_big, scratch3) = scratch2.take_vec_znx_big(n, 1, 1); + let (mut sk_ij, scratch4) = scratch3.take_glwe_secret(n, 1); + let (mut sk_ij_dft, scratch5) = scratch4.take_vec_znx_dft(n, 1, 1); + + let mut source_xa: Source = Source::new(seed_xa); + + (0..rank).for_each(|i| { + (i..rank).for_each(|j| { + module.svp_apply(&mut sk_ij_dft, 0, &sk_dft_prep.data, j, &sk_dft, i); + + module.vec_znx_dft_to_vec_znx_big_tmp_a(&mut sk_ij_big, 0, &mut sk_ij_dft, 0); + module.vec_znx_big_normalize( + self.basek(), + &mut sk_ij.data.as_vec_znx_mut(), + 0, + &sk_ij_big, + 0, + scratch5, + ); + + let (seed_xa_tmp, _) = source_xa.branch(); + + self.at_mut(i, j) + .encrypt_sk(module, &sk_ij, sk, seed_xa_tmp, source_xe, sigma, scratch5); + }); + }) + } +}
@@ -0,0 +1,90 @@
+use backend::hal::{ + api::{ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, VecZnxNormalizeInplace, ZnxZero}, + layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch}, +}; +use sampling::source::Source; + +use crate::{ + TakeGLWEPt, + encryption::glwe_encrypt_sk_internal, + layouts::{GGSWCiphertext, Infos, compressed::GGSWCiphertextCompressed, prepared::GLWESecretExec}, +}; + +use crate::trait_families::GGSWEncryptSkFamily; + +impl GGSWCiphertextCompressed<Vec<u8>> { + pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize + where + Module<B>: GGSWEncryptSkFamily<B>, + { + GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k, rank) + } +} + +impl<DataSelf: DataMut> GGSWCiphertextCompressed<DataSelf> { + pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + pt: &ScalarZnx<DataPt>, + sk: &GLWESecretExec<DataSk, B>, + seed_xa: [u8; 32], + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + Module<B>: GGSWEncryptSkFamily<B> + VecZnxAddScalarInplace, + Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + { + #[cfg(debug_assertions)] + { + use backend::hal::api::ZnxInfos; + + assert_eq!(self.rank(), sk.rank()); + assert_eq!(self.n(), sk.n()); + assert_eq!(pt.n(), sk.n()); + } + + let basek: usize = self.basek(); + let k: usize = self.k(); + let rank: usize = self.rank(); + let cols: usize = rank + 1; + let digits: usize = self.digits(); + + let (mut tmp_pt, scratch_1) = scratch.take_glwe_pt(self.n(), basek, k); + + let mut source = Source::new(seed_xa); + + self.seed = vec![[0u8; 32]; self.rows() * cols]; + + (0..self.rows()).for_each(|row_i| { + tmp_pt.data.zero(); + + // Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt + module.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (digits - 1) + row_i * digits, pt, 0); + module.vec_znx_normalize_inplace(basek, &mut tmp_pt.data, 0, scratch_1); + + (0..rank + 1).for_each(|col_j| { + // rlwe encrypt of vec_znx_pt into vec_znx_ct + + let (seed, mut source_xa_tmp) = source.branch(); + + self.seed[row_i * cols + col_j] = seed; + + glwe_encrypt_sk_internal( + module, + self.basek(), + self.k(), + &mut self.at_mut(row_i, col_j).data, + cols, + true, + Some((&tmp_pt, col_j)), + sk, + &mut source_xa_tmp, + source_xe, + sigma, + scratch_1, + ); + }); + }); + } +}
@@ -0,0 +1,79 @@
+use backend::hal::{ + api::{ScratchAvailable, TakeVecZnx, TakeVecZnxDft}, + layouts::{Backend, DataMut, DataRef, Module, Scratch}, +}; +use sampling::source::Source; + +use crate::{ + encryption::glwe_ct::glwe_encrypt_sk_internal, + layouts::{GLWECiphertext, GLWEPlaintext, Infos, compressed::GLWECiphertextCompressed, prepared::GLWESecretExec}, +}; + +use crate::trait_families::GLWEEncryptSkFamily; + +impl GLWECiphertextCompressed<Vec<u8>> { + pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize) -> usize + where + Module<B>: GLWEEncryptSkFamily<B>, + { + GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) + } +} + +impl<D: DataMut> GLWECiphertextCompressed<D> { + pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + pt: &GLWEPlaintext<DataPt>, + sk: &GLWESecretExec<DataSk, B>, + seed_xa: [u8; 32], + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + Module<B>: GLWEEncryptSkFamily<B>, + Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + { + self.encrypt_sk_internal( + module, + Some((pt, 0)), + sk, + seed_xa, + source_xe, + sigma, + scratch, + ); + } + + pub(crate) fn encrypt_sk_internal<DataPt: DataRef, DataSk: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + pt: Option<(&GLWEPlaintext<DataPt>, usize)>, + sk: &GLWESecretExec<DataSk, B>, + seed_xa: [u8; 32], + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + Module<B>: GLWEEncryptSkFamily<B>, + Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + { + let mut source_xa = Source::new(seed_xa); + let cols: usize = self.rank() + 1; + glwe_encrypt_sk_internal( + module, + self.basek(), + self.k(), + &mut self.data, + cols, + true, + pt, + sk, + &mut source_xa, + source_xe, + sigma, + scratch, + ); + self.seed = seed_xa; + } +}
@@ -0,0 +1,6 @@
+mod gglwe_atk; +mod gglwe_ct; +mod gglwe_ksk; +mod gglwe_tsk; +mod ggsw_ct; +mod glwe_ct;
@@ -0,0 +1,83 @@
+use backend::hal::{ + api::{ + ScratchAvailable, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, VecZnxAutomorphism, + VecZnxSwithcDegree, + }, + layouts::{Backend, DataMut, DataRef, Module, Scratch}, +}; +use sampling::source::Source; + +use crate::{ + TakeGLWESecret, TakeGLWESecretExec, + layouts::{GGLWEAutomorphismKey, GLWESecret, GGLWESwitchingKey, Infos}, +}; + +use crate::trait_families::{GGLWEAutomorphismKeyEncryptSkFamily, GLWESecretExecModuleFamily}; + +impl GGLWEAutomorphismKey<Vec<u8>> { + pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize + where + Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + { + GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank, rank) + GLWESecret::bytes_of(n, rank) + } + + pub fn encrypt_pk_scratch_space<B: Backend>(module: &Module<B>, _n: usize, _basek: usize, _k: usize, _rank: usize) -> usize { + GGLWESwitchingKey::encrypt_pk_scratch_space(module, _n, _basek, _k, _rank, _rank) + } +} + +impl<DataSelf: DataMut> GGLWEAutomorphismKey<DataSelf> { + pub fn encrypt_sk<DataSk: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + p: i64, + sk: &GLWESecret<DataSk>, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> + + VecZnxAutomorphism + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + GLWESecretExecModuleFamily<B>, + Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + TakeVecZnx, + { + #[cfg(debug_assertions)] + { + assert_eq!(self.n(), sk.n()); + assert_eq!(self.rank_out(), self.rank_in()); + assert_eq!(sk.rank(), self.rank()); + assert!( + scratch.available() + >= GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k(), self.rank()), + "scratch.available(): {} < AutomorphismKey::encrypt_sk_scratch_space(module, self.rank()={}, self.size()={}): {}", + scratch.available(), + self.rank(), + self.size(), + GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k(), self.rank()) + ) + } + + let (mut sk_out, scratch_1) = scratch.take_glwe_secret(sk.n(), sk.rank()); + + { + (0..self.rank()).for_each(|i| { + module.vec_znx_automorphism( + module.galois_element_inv(p), + &mut sk_out.data.as_vec_znx_mut(), + i, + &sk.data.as_vec_znx(), + i, + ); + }); + } + + self.key + .encrypt_sk(module, &sk, &sk_out, source_xa, source_xe, sigma, scratch_1); + + self.p = p; + } +}
@@ -0,0 +1,121 @@
+use backend::hal::{ + api::{ + ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, + ZnxZero, + }, + layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch}, +}; +use sampling::source::Source; + +use crate::{ + TakeGLWEPt, + layouts::{GGLWECiphertext, GLWECiphertext, GLWEPlaintext, Infos, prepared::GLWESecretExec}, +}; + +use crate::trait_families::GGLWEEncryptSkFamily; + +impl GGLWECiphertext<Vec<u8>> { + pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize) -> usize + where + Module<B>: GGLWEEncryptSkFamily<B>, + { + GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) + + (GLWEPlaintext::byte_of(n, basek, k) | module.vec_znx_normalize_tmp_bytes(n)) + } + + pub fn encrypt_pk_scratch_space<B: Backend>(_module: &Module<B>, _n: usize, _basek: usize, _k: usize, _rank: usize) -> usize { + unimplemented!() + } +} + +impl<DataSelf: DataMut> GGLWECiphertext<DataSelf> { + pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + pt: &ScalarZnx<DataPt>, + sk: &GLWESecretExec<DataSk, B>, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + Module<B>: GGLWEEncryptSkFamily<B> + VecZnxAddScalarInplace, + Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + { + #[cfg(debug_assertions)] + { + use backend::hal::api::ZnxInfos; + + assert_eq!( + self.rank_in(), + pt.cols(), + "self.rank_in(): {} != pt.cols(): {}", + self.rank_in(), + pt.cols() + ); + assert_eq!( + self.rank_out(), + sk.rank(), + "self.rank_out(): {} != sk.rank(): {}", + self.rank_out(), + sk.rank() + ); + assert_eq!(self.n(), sk.n()); + assert_eq!(pt.n(), sk.n()); + assert!( + scratch.available() >= GGLWECiphertext::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k()), + "scratch.available: {} < GGLWECiphertext::encrypt_sk_scratch_space(module, self.rank()={}, self.size()={}): {}", + scratch.available(), + self.rank(), + self.size(), + GGLWECiphertext::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k()) + ); + assert!( + self.rows() * self.digits() * self.basek() <= self.k(), + "self.rows() : {} * self.digits() : {} * self.basek() : {} = {} >= self.k() = {}", + self.rows(), + self.digits(), + self.basek(), + self.rows() * self.digits() * self.basek(), + self.k() + ); + } + + let rows: usize = self.rows(); + let digits: usize = self.digits(); + let basek: usize = self.basek(); + let k: usize = self.k(); + let rank_in: usize = self.rank_in(); + + let (mut tmp_pt, scrach_1) = scratch.take_glwe_pt(sk.n(), basek, k); + // For each input column (i.e. rank) produces a GGLWE ciphertext of rank_out+1 columns + // + // Example for ksk rank 2 to rank 3: + // + // (-(a0*s0 + a1*s1 + a2*s2) + s0', a0, a1, a2) + // (-(b0*s0 + b1*s1 + b2*s2) + s0', b0, b1, b2) + // + // Example ksk rank 2 to rank 1 + // + // (-(a*s) + s0, a) + // (-(b*s) + s1, b) + (0..rank_in).for_each(|col_i| { + (0..rows).for_each(|row_i| { + // Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt + tmp_pt.data.zero(); // zeroes for next iteration + module.vec_znx_add_scalar_inplace( + &mut tmp_pt.data, + 0, + (digits - 1) + row_i * digits, + pt, + col_i, + ); + module.vec_znx_normalize_inplace(basek, &mut tmp_pt.data, 0, scrach_1); + + // rlwe encrypt of vec_znx_pt into vec_znx_ct + self.at_mut(row_i, col_i) + .encrypt_sk(module, &tmp_pt, sk, source_xa, source_xe, sigma, scrach_1); + }); + }); + } +}
@@ -0,0 +1,118 @@
+use backend::hal::{ + api::{ScratchAvailable, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, VecZnxSwithcDegree}, + layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch}, +}; +use sampling::source::Source; + +use crate::{ + TakeGLWESecretExec, + layouts::{GGLWECiphertext, GLWESecret, GGLWESwitchingKey, Infos, prepared::GLWESecretExec}, +}; + +use crate::trait_families::{GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; + +impl GGLWESwitchingKey<Vec<u8>> { + pub fn encrypt_sk_scratch_space<B: Backend>( + module: &Module<B>, + n: usize, + basek: usize, + k: usize, + rank_in: usize, + rank_out: usize, + ) -> usize + where + Module<B>: GGLWESwitchingKeyEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + { + (GGLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) | ScalarZnx::alloc_bytes(n, 1)) + + ScalarZnx::alloc_bytes(n, rank_in) + + GLWESecretExec::bytes_of(module, n, rank_out) + } + + pub fn encrypt_pk_scratch_space<B: Backend>( + module: &Module<B>, + _n: usize, + _basek: usize, + _k: usize, + _rank_in: usize, + _rank_out: usize, + ) -> usize { + GGLWECiphertext::encrypt_pk_scratch_space(module, _n, _basek, _k, _rank_out) + } +} + +impl<DataSelf: DataMut> GGLWESwitchingKey<DataSelf> { + pub fn encrypt_sk<DataSkIn: DataRef, DataSkOut: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + sk_in: &GLWESecret<DataSkIn>, + sk_out: &GLWESecret<DataSkOut>, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + Module<B>: + GGLWESwitchingKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWESecretExecModuleFamily<B>, + Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + ScratchAvailable + TakeVecZnx, + { + #[cfg(debug_assertions)] + { + assert!(sk_in.n() <= module.n()); + assert!(sk_out.n() <= module.n()); + assert!( + scratch.available() + >= GGLWESwitchingKey::encrypt_sk_scratch_space( + module, + sk_out.n(), + self.basek(), + self.k(), + self.rank_in(), + self.rank_out() + ), + "scratch.available()={} < GLWESwitchingKey::encrypt_sk_scratch_space={}", + scratch.available(), + GGLWESwitchingKey::encrypt_sk_scratch_space( + module, + sk_out.n(), + self.basek(), + self.k(), + self.rank_in(), + self.rank_out() + ) + ) + } + + let n: usize = sk_in.n().max(sk_out.n()); + + let (mut sk_in_tmp, scratch1) = scratch.take_scalar_znx(n, sk_in.rank()); + (0..sk_in.rank()).for_each(|i| { + module.vec_znx_switch_degree( + &mut sk_in_tmp.as_vec_znx_mut(), + i, + &sk_in.data.as_vec_znx(), + i, + ); + }); + + let (mut sk_out_tmp, scratch2) = scratch1.take_glwe_secret_exec(n, sk_out.rank()); + { + let (mut tmp, _) = scratch2.take_scalar_znx(n, 1); + (0..sk_out.rank()).for_each(|i| { + module.vec_znx_switch_degree(&mut tmp.as_vec_znx_mut(), 0, &sk_out.data.as_vec_znx(), i); + module.svp_prepare(&mut sk_out_tmp.data, i, &tmp, 0); + }); + } + + self.key.encrypt_sk( + module, + &sk_in_tmp, + &sk_out_tmp, + source_xa, + source_xe, + sigma, + scratch2, + ); + self.sk_in_n = sk_in.n(); + self.sk_out_n = sk_out.n(); + } +}
@@ -0,0 +1,87 @@
+use backend::hal::{ + api::{ + ScratchAvailable, SvpApply, TakeScalarZnx, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, VecZnxAddScalarInplace, + VecZnxBigAllocBytes, VecZnxDftToVecZnxBigTmpA, VecZnxSwithcDegree, + }, + layouts::{Backend, DataMut, DataRef, Module, Scratch}, +}; +use sampling::source::Source; + +use crate::{ + TakeGLWESecret, TakeGLWESecretExec, + layouts::{GGLWETensorKey, GLWESecret, GGLWESwitchingKey, Infos, prepared::GLWESecretExec}, + trait_families::GLWEDecryptFamily, +}; + +use crate::trait_families::{GGLWETensorKeyEncryptSkFamily, GLWESecretExecModuleFamily}; + +impl GGLWETensorKey<Vec<u8>> { + pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize + where + Module<B>: GGLWETensorKeyEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + { + GLWESecretExec::bytes_of(module, n, rank) + + module.vec_znx_dft_alloc_bytes(n, rank, 1) + + module.vec_znx_big_alloc_bytes(n, 1, 1) + + module.vec_znx_dft_alloc_bytes(n, 1, 1) + + GLWESecret::bytes_of(n, 1) + + GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank, rank) + } +} + +impl<DataSelf: DataMut> GGLWETensorKey<DataSelf> { + pub fn encrypt_sk<DataSk: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + sk: &GLWESecret<DataSk>, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + Module<B>: GGLWETensorKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWESecretExecModuleFamily<B>, + Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeGLWESecretExec<B> + TakeScalarZnx + TakeVecZnx, + { + #[cfg(debug_assertions)] + { + assert_eq!(self.rank(), sk.rank()); + assert_eq!(self.n(), sk.n()); + } + + let n: usize = sk.n(); + + let rank: usize = self.rank(); + + let (mut sk_dft_prep, scratch1) = scratch.take_glwe_secret_exec(n, rank); + sk_dft_prep.prepare(module, &sk); + + let (mut sk_dft, scratch2) = scratch1.take_vec_znx_dft(n, rank, 1); + + (0..rank).for_each(|i| { + module.vec_znx_dft_from_vec_znx(1, 0, &mut sk_dft, i, &sk.data.as_vec_znx(), i); + }); + + let (mut sk_ij_big, scratch3) = scratch2.take_vec_znx_big(n, 1, 1); + let (mut sk_ij, scratch4) = scratch3.take_glwe_secret(n, 1); + let (mut sk_ij_dft, scratch5) = scratch4.take_vec_znx_dft(n, 1, 1); + + (0..rank).for_each(|i| { + (i..rank).for_each(|j| { + module.svp_apply(&mut sk_ij_dft, 0, &sk_dft_prep.data, j, &sk_dft, i); + + module.vec_znx_dft_to_vec_znx_big_tmp_a(&mut sk_ij_big, 0, &mut sk_ij_dft, 0); + module.vec_znx_big_normalize( + self.basek(), + &mut sk_ij.data.as_vec_znx_mut(), + 0, + &sk_ij_big, + 0, + scratch5, + ); + + self.at_mut(i, j) + .encrypt_sk(module, &sk_ij, sk, source_xa, source_xe, sigma, scratch5); + }); + }) + } +}
@@ -0,0 +1,81 @@
+use backend::hal::{ + api::{ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, VecZnxNormalizeInplace, ZnxZero}, + layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch, VecZnx}, +}; +use sampling::source::Source; + +use crate::{ + TakeGLWEPt, + layouts::{GGSWCiphertext, GLWECiphertext, Infos, prepared::GLWESecretExec}, +}; + +use crate::trait_families::GLWEEncryptSkFamily; + +pub trait GGSWEncryptSkFamily<B: Backend> = GLWEEncryptSkFamily<B>; + +impl GGSWCiphertext<Vec<u8>> { + pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize + where + Module<B>: GGSWEncryptSkFamily<B>, + { + let size = k.div_ceil(basek); + GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) + + VecZnx::alloc_bytes(n, rank + 1, size) + + VecZnx::alloc_bytes(n, 1, size) + + module.vec_znx_dft_alloc_bytes(n, rank + 1, size) + } +} + +impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> { + pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + pt: &ScalarZnx<DataPt>, + sk: &GLWESecretExec<DataSk, B>, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + Module<B>: GGSWEncryptSkFamily<B> + VecZnxAddScalarInplace, + Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + { + #[cfg(debug_assertions)] + { + use backend::hal::api::ZnxInfos; + + assert_eq!(self.rank(), sk.rank()); + assert_eq!(self.n(), sk.n()); + assert_eq!(pt.n(), sk.n()); + } + + let basek: usize = self.basek(); + let k: usize = self.k(); + let rank: usize = self.rank(); + let digits: usize = self.digits(); + + let (mut tmp_pt, scratch1) = scratch.take_glwe_pt(self.n(), basek, k); + + (0..self.rows()).for_each(|row_i| { + tmp_pt.data.zero(); + + // Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt + module.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (digits - 1) + row_i * digits, pt, 0); + module.vec_znx_normalize_inplace(basek, &mut tmp_pt.data, 0, scratch1); + + (0..rank + 1).for_each(|col_j| { + // rlwe encrypt of vec_znx_pt into vec_znx_ct + + self.at_mut(row_i, col_j).encrypt_sk_internal( + module, + Some((&tmp_pt, col_j)), + sk, + source_xa, + source_xe, + sigma, + scratch1, + ); + }); + }); + } +}
@@ -0,0 +1,53 @@
+use backend::hal::{ + api::{ScratchOwnedAlloc, ScratchOwnedBorrow}, + layouts::{Backend, DataMut, DataRef, Module, ScratchOwned}, + oep::{ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeVecZnxDftImpl, TakeVecZnxImpl}, +}; +use sampling::source::Source; + +use crate::{ + dist::Distribution, + layouts::{GLWECiphertext, GLWEPublicKey, Infos, prepared::GLWESecretExec}, +}; + +use crate::trait_families::GLWEEncryptSkFamily; + +impl<D: DataMut> GLWEPublicKey<D> { + pub fn generate_from_sk<S: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + sk: &GLWESecretExec<S, B>, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + ) where + Module<B>: GLWEEncryptSkFamily<B>, + B: ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + TakeVecZnxDftImpl<B> + + ScratchAvailableImpl<B> + + TakeVecZnxImpl<B>, + { + #[cfg(debug_assertions)] + { + assert_eq!(self.n(), sk.n()); + + match sk.dist { + Distribution::NONE => panic!("invalid sk: SecretDistribution::NONE"), + _ => {} + } + } + + // Its ok to allocate scratch space here since pk is usually generated only once. + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWECiphertext::encrypt_sk_scratch_space( + module, + self.n(), + self.basek(), + self.k(), + )); + + let mut tmp: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(self.n(), self.basek(), self.k(), self.rank()); + tmp.encrypt_zero_sk(module, sk, source_xa, source_xe, sigma, scratch.borrow()); + self.dist = sk.dist; + } +}
@@ -0,0 +1,67 @@
+use backend::hal::{ + api::{ + ScratchAvailable, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, + VecZnxSwithcDegree, ZnxView, ZnxViewMut, ZnxZero, + }, + layouts::{Backend, DataMut, DataRef, Module, Scratch}, +}; +use sampling::source::Source; + +use crate::{ + TakeGLWESecret, TakeGLWESecretExec, + layouts::{GLWESecret, GGLWESwitchingKey, GLWEToLWESwitchingKey, LWESecret, prepared::GLWESecretExec}, +}; + +use crate::trait_families::{GGLWEEncryptSkFamily, GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; + +impl GLWEToLWESwitchingKey<Vec<u8>> { + pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank_in: usize) -> usize + where + Module<B>: GGLWEEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + { + GLWESecretExec::bytes_of(module, n, rank_in) + + (GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank_in, 1) | GLWESecret::bytes_of(n, rank_in)) + } +} + +impl<D: DataMut> GLWEToLWESwitchingKey<D> { + pub fn encrypt_sk<DLwe, DGlwe, B: Backend>( + &mut self, + module: &Module<B>, + sk_lwe: &LWESecret<DLwe>, + sk_glwe: &GLWESecret<DGlwe>, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + DLwe: DataRef, + DGlwe: DataRef, + Module<B>: GGLWESwitchingKeyEncryptSkFamily<B> + + VecZnxAutomorphismInplace + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + GLWESecretExecModuleFamily<B>, + Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + TakeVecZnx, + { + #[cfg(debug_assertions)] + { + assert!(sk_lwe.n() <= module.n()); + } + + let (mut sk_lwe_as_glwe, scratch1) = scratch.take_glwe_secret(sk_glwe.n(), 1); + sk_lwe_as_glwe.data.zero(); + sk_lwe_as_glwe.data.at_mut(0, 0)[..sk_lwe.n()].copy_from_slice(sk_lwe.data.at(0, 0)); + module.vec_znx_automorphism_inplace(-1, &mut sk_lwe_as_glwe.data.as_vec_znx_mut(), 0); + + self.0.encrypt_sk( + module, + sk_glwe, + &sk_lwe_as_glwe, + source_xa, + source_xe, + sigma, + scratch1, + ); + } +}
@@ -0,0 +1,82 @@
+use backend::hal::{ + api::{ + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddNormal, VecZnxFillUniform, VecZnxNormalizeInplace, ZnxView, ZnxViewMut, + }, + layouts::{Backend, DataMut, DataRef, Module, ScratchOwned, VecZnx}, + oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl}, +}; +use sampling::source::Source; + +use crate::{ + SIX_SIGMA, + layouts::{Infos, LWECiphertext, LWEPlaintext, LWESecret}, +}; + +impl<DataSelf: DataMut> LWECiphertext<DataSelf> { + pub fn encrypt_sk<DataPt, DataSk, B: Backend>( + &mut self, + module: &Module<B>, + pt: &LWEPlaintext<DataPt>, + sk: &LWESecret<DataSk>, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + ) where + DataPt: DataRef, + DataSk: DataRef, + Module<B>: VecZnxFillUniform + VecZnxAddNormal + VecZnxNormalizeInplace<B>, + B: ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, + { + #[cfg(debug_assertions)] + { + assert_eq!(self.n(), sk.n()) + } + + let basek: usize = self.basek(); + let k: usize = self.k(); + + module.vec_znx_fill_uniform(basek, &mut self.data, 0, k, source_xa); + + let mut tmp_znx: VecZnx<Vec<u8>> = VecZnx::alloc(1, 1, self.size()); + + let min_size = self.size().min(pt.size()); + + (0..min_size).for_each(|i| { + tmp_znx.at_mut(0, i)[0] = pt.data.at(0, i)[0] + - self.data.at(0, i)[1..] + .iter() + .zip(sk.data.at(0, 0)) + .map(|(x, y)| x * y) + .sum::<i64>(); + }); + + (min_size..self.size()).for_each(|i| { + tmp_znx.at_mut(0, i)[0] -= self.data.at(0, i)[1..] + .iter() + .zip(sk.data.at(0, 0)) + .map(|(x, y)| x * y) + .sum::<i64>(); + }); + + module.vec_znx_add_normal( + basek, + &mut self.data, + 0, + k, + source_xe, + sigma, + sigma * SIX_SIGMA, + ); + + module.vec_znx_normalize_inplace( + basek, + &mut tmp_znx, + 0, + ScratchOwned::alloc(size_of::<i64>()).borrow(), + ); + + (0..self.size()).for_each(|i| { + self.data.at_mut(0, i)[0] = tmp_znx.at(0, i)[0]; + }); + } +}
@@ -0,0 +1,76 @@
+use backend::hal::{ + api::{ + ScratchAvailable, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, + VecZnxSwithcDegree, ZnxView, ZnxViewMut, + }, + layouts::{Backend, DataMut, DataRef, Module, Scratch}, +}; +use sampling::source::Source; + +use crate::{ + TakeGLWESecret, TakeGLWESecretExec, + layouts::{GLWESecret, GGLWESwitchingKey, Infos, LWESecret, LWESwitchingKey, prepared::GLWESecretExec}, +}; + +use crate::trait_families::{GGLWEEncryptSkFamily, GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; + +impl LWESwitchingKey<Vec<u8>> { + pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize) -> usize + where + Module<B>: GGLWEEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + { + GLWESecret::bytes_of(n, 1) + + GLWESecretExec::bytes_of(module, n, 1) + + GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, 1, 1) + } +} + +impl<D: DataMut> LWESwitchingKey<D> { + pub fn encrypt_sk<DIn, DOut, B: Backend>( + &mut self, + module: &Module<B>, + sk_lwe_in: &LWESecret<DIn>, + sk_lwe_out: &LWESecret<DOut>, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + DIn: DataRef, + DOut: DataRef, + Module<B>: GGLWESwitchingKeyEncryptSkFamily<B> + + VecZnxAutomorphismInplace + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + GLWESecretExecModuleFamily<B>, + Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + TakeVecZnx, + { + #[cfg(debug_assertions)] + { + assert!(sk_lwe_in.n() <= self.n()); + assert!(sk_lwe_out.n() <= self.n()); + assert!(self.n() <= module.n()); + } + + let (mut sk_in_glwe, scratch1) = scratch.take_glwe_secret(self.n(), 1); + let (mut sk_out_glwe, scratch2) = scratch1.take_glwe_secret(self.n(), 1); + + sk_out_glwe.data.at_mut(0, 0)[..sk_lwe_out.n()].copy_from_slice(sk_lwe_out.data.at(0, 0)); + sk_out_glwe.data.at_mut(0, 0)[sk_lwe_out.n()..].fill(0); + module.vec_znx_automorphism_inplace(-1, &mut sk_out_glwe.data.as_vec_znx_mut(), 0); + + sk_in_glwe.data.at_mut(0, 0)[..sk_lwe_in.n()].copy_from_slice(sk_lwe_in.data.at(0, 0)); + sk_in_glwe.data.at_mut(0, 0)[sk_lwe_in.n()..].fill(0); + module.vec_znx_automorphism_inplace(-1, &mut sk_in_glwe.data.as_vec_znx_mut(), 0); + + self.0.encrypt_sk( + module, + &sk_in_glwe, + &sk_out_glwe, + source_xa, + source_xe, + sigma, + scratch2, + ); + } +}
@@ -0,0 +1,66 @@
+use backend::hal::{ + api::{ + ScratchAvailable, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, + VecZnxSwithcDegree, ZnxView, ZnxViewMut, + }, + layouts::{Backend, DataMut, DataRef, Module, Scratch}, +}; +use sampling::source::Source; + +use crate::{ + TakeGLWESecret, TakeGLWESecretExec, + layouts::{GLWESecret, GGLWESwitchingKey, LWESecret, LWEToGLWESwitchingKey}, +}; + +use crate::trait_families::{GGLWEEncryptSkFamily, GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; + +impl LWEToGLWESwitchingKey<Vec<u8>> { + pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank_out: usize) -> usize + where + Module<B>: GGLWEEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + { + GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, 1, rank_out) + GLWESecret::bytes_of(n, 1) + } +} + +impl<D: DataMut> LWEToGLWESwitchingKey<D> { + pub fn encrypt_sk<DLwe, DGlwe, B: Backend>( + &mut self, + module: &Module<B>, + sk_lwe: &LWESecret<DLwe>, + sk_glwe: &GLWESecret<DGlwe>, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + DLwe: DataRef, + DGlwe: DataRef, + Module<B>: GGLWESwitchingKeyEncryptSkFamily<B> + + VecZnxAutomorphismInplace + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + GLWESecretExecModuleFamily<B>, + Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + TakeVecZnx, + { + #[cfg(debug_assertions)] + { + assert!(sk_lwe.n() <= module.n()); + } + + let (mut sk_lwe_as_glwe, scratch1) = scratch.take_glwe_secret(sk_glwe.n(), 1); + sk_lwe_as_glwe.data.at_mut(0, 0)[..sk_lwe.n()].copy_from_slice(sk_lwe.data.at(0, 0)); + sk_lwe_as_glwe.data.at_mut(0, 0)[sk_lwe.n()..].fill(0); + module.vec_znx_automorphism_inplace(-1, &mut sk_lwe_as_glwe.data.as_vec_znx_mut(), 0); + + self.0.encrypt_sk( + module, + &sk_lwe_as_glwe, + &sk_glwe, + source_xa, + source_xe, + sigma, + scratch1, + ); + } +}
@@ -0,0 +1,14 @@
+mod compressed; +mod gglwe_atk; +mod gglwe_ct; +mod gglwe_ksk; +mod gglwe_tsk; +mod ggsw_ct; +mod glwe_ct; +mod glwe_pk; +mod glwe_to_lwe_ksk; +mod lwe_ct; +mod lwe_ksk; +mod lwe_to_glwe_ksk; + +pub(crate) use glwe_ct::glwe_encrypt_sk_internal;
@@ -0,0 +1,69 @@
+use backend::hal::{ + api::{ScratchAvailable, TakeVecZnxDft}, + layouts::{Backend, DataMut, DataRef, Module, Scratch}, +}; + +use crate::{ + layouts::{GGLWEAutomorphismKey, GGLWESwitchingKey, prepared::GGSWCiphertextExec}, + trait_families::GLWEExternalProductFamily, +}; + +impl GGLWEAutomorphismKey<Vec<u8>> { + pub fn external_product_scratch_space<B: Backend>( + module: &Module<B>, + n: usize, + basek: usize, + k_out: usize, + k_in: usize, + ggsw_k: usize, + digits: usize, + rank: usize, + ) -> usize + where + Module<B>: GLWEExternalProductFamily<B>, + { + GGLWESwitchingKey::external_product_scratch_space(module, n, basek, k_out, k_in, ggsw_k, digits, rank) + } + + pub fn external_product_inplace_scratch_space<B: Backend>( + module: &Module<B>, + n: usize, + basek: usize, + k_out: usize, + ggsw_k: usize, + digits: usize, + rank: usize, + ) -> usize + where + Module<B>: GLWEExternalProductFamily<B>, + { + GGLWESwitchingKey::external_product_inplace_scratch_space(module, n, basek, k_out, ggsw_k, digits, rank) + } +} + +impl<DataSelf: DataMut> GGLWEAutomorphismKey<DataSelf> { + pub fn external_product<DataLhs: DataRef, DataRhs: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + lhs: &GGLWEAutomorphismKey<DataLhs>, + rhs: &GGSWCiphertextExec<DataRhs, B>, + scratch: &mut Scratch<B>, + ) where + Module<B>: GLWEExternalProductFamily<B>, + Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable, + { + self.key.external_product(module, &lhs.key, rhs, scratch); + } + + pub fn external_product_inplace<DataRhs: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + rhs: &GGSWCiphertextExec<DataRhs, B>, + scratch: &mut Scratch<B>, + ) where + Module<B>: GLWEExternalProductFamily<B>, + Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable, + { + self.key.external_product_inplace(module, rhs, scratch); + } +}
@@ -0,0 +1,4 @@
+mod gglwe_atk; +mod gglwe_ksk; +mod ggsw_ct; +mod glwe_ct;
@@ -3,9 +3,12 @@ api::{ScratchAvailable, TakeVecZnxDft, VecZnxAutomorphism, VecZnxAutomorphismInplace, ZnxZero},
layouts::{Backend, DataMut, DataRef, Module, Scratch}, }; -use crate::{AutomorphismKey, AutomorphismKeyExec, GLWECiphertext, GLWEKeyswitchFamily, Infos}; +use crate::{ + layouts::{GGLWEAutomorphismKey, GLWECiphertext, Infos, prepared::GGLWEAutomorphismKeyExec}, + trait_families::GLWEKeyswitchFamily, +}; -impl AutomorphismKey<Vec<u8>> { +impl GGLWEAutomorphismKey<Vec<u8>> { pub fn automorphism_scratch_space<B: Backend>( module: &Module<B>, n: usize,@@ -34,16 +37,16 @@ ) -> usize
where Module<B>: GLWEKeyswitchFamily<B>, { - AutomorphismKey::automorphism_scratch_space(module, n, basek, k_out, k_out, k_ksk, digits, rank) + GGLWEAutomorphismKey::automorphism_scratch_space(module, n, basek, k_out, k_out, k_ksk, digits, rank) } } -impl<DataSelf: DataMut> AutomorphismKey<DataSelf> { +impl<DataSelf: DataMut> GGLWEAutomorphismKey<DataSelf> { pub fn automorphism<'a, DataLhs: DataRef, DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - lhs: &AutomorphismKey<DataLhs>, - rhs: &AutomorphismKeyExec<DataRhs, B>, + lhs: &GGLWEAutomorphismKey<DataLhs>, + rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxAutomorphism + VecZnxAutomorphismInplace,@@ -117,14 +120,14 @@
pub fn automorphism_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &AutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxAutomorphism + VecZnxAutomorphismInplace, Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable, { unsafe { - let self_ptr: *mut AutomorphismKey<DataSelf> = self as *mut AutomorphismKey<DataSelf>; + let self_ptr: *mut GGLWEAutomorphismKey<DataSelf> = self as *mut GGLWEAutomorphismKey<DataSelf>; self.automorphism(&module, &*self_ptr, rhs, scratch); } }
@@ -1,702 +0,0 @@
-use backend::hal::{ - api::{ - ScratchAvailable, SvpApply, TakeScalarZnx, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, VecZnxAddScalarInplace, - VecZnxAutomorphism, VecZnxBigAllocBytes, VecZnxDftToVecZnxBigTmpA, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, - VecZnxSwithcDegree, ZnxZero, - }, - layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch}, -}; -use sampling::source::Source; - -use crate::{ - AutomorphismKey, AutomorphismKeyCompressed, GGLWECiphertext, GGLWECiphertextCompressed, GLWECiphertext, GLWEDecryptFamily, - GLWEEncryptSkFamily, GLWEPlaintext, GLWESecret, GLWESecretExec, GLWESecretFamily, GLWESwitchingKey, - GLWESwitchingKeyCompressed, GLWETensorKey, GLWETensorKeyCompressed, Infos, TakeGLWEPt, TakeGLWESecret, TakeGLWESecretExec, - encrypt_sk_internal, -}; - -pub trait GGLWEEncryptSkFamily<B: Backend> = GLWEEncryptSkFamily<B> + GLWESecretFamily<B>; - -impl GGLWECiphertext<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize) -> usize - where - Module<B>: GGLWEEncryptSkFamily<B>, - { - GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) - + (GLWEPlaintext::byte_of(n, basek, k) | module.vec_znx_normalize_tmp_bytes(n)) - } - - pub fn encrypt_pk_scratch_space<B: Backend>(_module: &Module<B>, _n: usize, _basek: usize, _k: usize, _rank: usize) -> usize { - unimplemented!() - } -} - -impl<DataSelf: DataMut> GGLWECiphertext<DataSelf> { - pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - pt: &ScalarZnx<DataPt>, - sk: &GLWESecretExec<DataSk, B>, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, - ) where - Module<B>: GGLWEEncryptSkFamily<B> + VecZnxAddScalarInplace, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - use backend::hal::api::ZnxInfos; - - assert_eq!( - self.rank_in(), - pt.cols(), - "self.rank_in(): {} != pt.cols(): {}", - self.rank_in(), - pt.cols() - ); - assert_eq!( - self.rank_out(), - sk.rank(), - "self.rank_out(): {} != sk.rank(): {}", - self.rank_out(), - sk.rank() - ); - assert_eq!(self.n(), sk.n()); - assert_eq!(pt.n(), sk.n()); - assert!( - scratch.available() >= GGLWECiphertext::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k()), - "scratch.available: {} < GGLWECiphertext::encrypt_sk_scratch_space(module, self.rank()={}, self.size()={}): {}", - scratch.available(), - self.rank(), - self.size(), - GGLWECiphertext::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k()) - ); - assert!( - self.rows() * self.digits() * self.basek() <= self.k(), - "self.rows() : {} * self.digits() : {} * self.basek() : {} = {} >= self.k() = {}", - self.rows(), - self.digits(), - self.basek(), - self.rows() * self.digits() * self.basek(), - self.k() - ); - } - - let rows: usize = self.rows(); - let digits: usize = self.digits(); - let basek: usize = self.basek(); - let k: usize = self.k(); - let rank_in: usize = self.rank_in(); - - let (mut tmp_pt, scrach_1) = scratch.take_glwe_pt(sk.n(), basek, k); - // For each input column (i.e. rank) produces a GGLWE ciphertext of rank_out+1 columns - // - // Example for ksk rank 2 to rank 3: - // - // (-(a0*s0 + a1*s1 + a2*s2) + s0', a0, a1, a2) - // (-(b0*s0 + b1*s1 + b2*s2) + s0', b0, b1, b2) - // - // Example ksk rank 2 to rank 1 - // - // (-(a*s) + s0, a) - // (-(b*s) + s1, b) - (0..rank_in).for_each(|col_i| { - (0..rows).for_each(|row_i| { - // Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt - tmp_pt.data.zero(); // zeroes for next iteration - module.vec_znx_add_scalar_inplace( - &mut tmp_pt.data, - 0, - (digits - 1) + row_i * digits, - pt, - col_i, - ); - module.vec_znx_normalize_inplace(basek, &mut tmp_pt.data, 0, scrach_1); - - // rlwe encrypt of vec_znx_pt into vec_znx_ct - self.at_mut(row_i, col_i) - .encrypt_sk(module, &tmp_pt, sk, source_xa, source_xe, sigma, scrach_1); - }); - }); - } -} - -impl GGLWECiphertextCompressed<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize) -> usize - where - Module<B>: GLWESwitchingKeyEncryptSkFamily<B>, - { - GGLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) - } -} - -impl<D: DataMut> GGLWECiphertextCompressed<D> { - pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - pt: &ScalarZnx<DataPt>, - sk: &GLWESecretExec<DataSk, B>, - seed: [u8; 32], - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, - ) where - Module<B>: GGLWEEncryptSkFamily<B> + VecZnxAddScalarInplace, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - use backend::hal::api::ZnxInfos; - - assert_eq!( - self.rank_in(), - pt.cols(), - "self.rank_in(): {} != pt.cols(): {}", - self.rank_in(), - pt.cols() - ); - assert_eq!( - self.rank_out(), - sk.rank(), - "self.rank_out(): {} != sk.rank(): {}", - self.rank_out(), - sk.rank() - ); - assert_eq!(self.n(), sk.n()); - assert_eq!(pt.n(), sk.n()); - assert!( - scratch.available() - >= GGLWECiphertextCompressed::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k()), - "scratch.available: {} < GGLWECiphertext::encrypt_sk_scratch_space(module, self.rank()={}, self.size()={}): {}", - scratch.available(), - self.rank(), - self.size(), - GGLWECiphertextCompressed::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k()) - ); - assert!( - self.rows() * self.digits() * self.basek() <= self.k(), - "self.rows() : {} * self.digits() : {} * self.basek() : {} = {} >= self.k() = {}", - self.rows(), - self.digits(), - self.basek(), - self.rows() * self.digits() * self.basek(), - self.k() - ); - } - - let rows: usize = self.rows(); - let digits: usize = self.digits(); - let basek: usize = self.basek(); - let k: usize = self.k(); - let rank_in: usize = self.rank_in(); - let cols: usize = self.rank_out() + 1; - - let mut source_xa = Source::new(seed); - - let (mut tmp_pt, scrach_1) = scratch.take_glwe_pt(sk.n(), basek, k); - (0..rank_in).for_each(|col_i| { - (0..rows).for_each(|row_i| { - // Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt - tmp_pt.data.zero(); // zeroes for next iteration - module.vec_znx_add_scalar_inplace( - &mut tmp_pt.data, - 0, - (digits - 1) + row_i * digits, - pt, - col_i, - ); - module.vec_znx_normalize_inplace(basek, &mut tmp_pt.data, 0, scrach_1); - - let (seed, mut source_xa_tmp) = source_xa.branch(); - self.seed[col_i * rows + row_i] = seed; - - encrypt_sk_internal( - module, - self.basek(), - self.k(), - &mut self.at_mut(row_i, col_i).data, - cols, - true, - Some((&tmp_pt, 0)), - sk, - &mut source_xa_tmp, - source_xe, - sigma, - scrach_1, - ); - }); - }); - } -} - -pub trait GLWESwitchingKeyEncryptSkFamily<B: Backend> = GGLWEEncryptSkFamily<B>; - -impl GLWESwitchingKey<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend>( - module: &Module<B>, - n: usize, - basek: usize, - k: usize, - rank_in: usize, - rank_out: usize, - ) -> usize - where - Module<B>: GLWESwitchingKeyEncryptSkFamily<B>, - { - (GGLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) | ScalarZnx::alloc_bytes(n, 1)) - + ScalarZnx::alloc_bytes(n, rank_in) - + GLWESecretExec::bytes_of(module, n, rank_out) - } - - pub fn encrypt_pk_scratch_space<B: Backend>( - module: &Module<B>, - _n: usize, - _basek: usize, - _k: usize, - _rank_in: usize, - _rank_out: usize, - ) -> usize { - GGLWECiphertext::encrypt_pk_scratch_space(module, _n, _basek, _k, _rank_out) - } -} - -impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> { - pub fn encrypt_sk<DataSkIn: DataRef, DataSkOut: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - sk_in: &GLWESecret<DataSkIn>, - sk_out: &GLWESecret<DataSkOut>, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, - ) where - Module<B>: GLWESwitchingKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace, - Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + ScratchAvailable + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - assert!(sk_in.n() <= module.n()); - assert!(sk_out.n() <= module.n()); - assert!( - scratch.available() - >= GLWESwitchingKey::encrypt_sk_scratch_space( - module, - sk_out.n(), - self.basek(), - self.k(), - self.rank_in(), - self.rank_out() - ), - "scratch.available()={} < GLWESwitchingKey::encrypt_sk_scratch_space={}", - scratch.available(), - GLWESwitchingKey::encrypt_sk_scratch_space( - module, - sk_out.n(), - self.basek(), - self.k(), - self.rank_in(), - self.rank_out() - ) - ) - } - - let n: usize = sk_in.n().max(sk_out.n()); - - let (mut sk_in_tmp, scratch1) = scratch.take_scalar_znx(n, sk_in.rank()); - (0..sk_in.rank()).for_each(|i| { - module.vec_znx_switch_degree( - &mut sk_in_tmp.as_vec_znx_mut(), - i, - &sk_in.data.as_vec_znx(), - i, - ); - }); - - let (mut sk_out_tmp, scratch2) = scratch1.take_glwe_secret_exec(n, sk_out.rank()); - { - let (mut tmp, _) = scratch2.take_scalar_znx(n, 1); - (0..sk_out.rank()).for_each(|i| { - module.vec_znx_switch_degree(&mut tmp.as_vec_znx_mut(), 0, &sk_out.data.as_vec_znx(), i); - module.svp_prepare(&mut sk_out_tmp.data, i, &tmp, 0); - }); - } - - self.key.encrypt_sk( - module, - &sk_in_tmp, - &sk_out_tmp, - source_xa, - source_xe, - sigma, - scratch2, - ); - self.sk_in_n = sk_in.n(); - self.sk_out_n = sk_out.n(); - } -} - -impl GLWESwitchingKeyCompressed<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend>( - module: &Module<B>, - n: usize, - basek: usize, - k: usize, - rank_in: usize, - rank_out: usize, - ) -> usize - where - Module<B>: GLWESwitchingKeyEncryptSkFamily<B>, - { - (GGLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) | ScalarZnx::alloc_bytes(n, 1)) - + ScalarZnx::alloc_bytes(n, rank_in) - + GLWESecretExec::bytes_of(module, n, rank_out) - } -} - -impl<DataSelf: DataMut> GLWESwitchingKeyCompressed<DataSelf> { - pub fn encrypt_sk<DataSkIn: DataRef, DataSkOut: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - sk_in: &GLWESecret<DataSkIn>, - sk_out: &GLWESecret<DataSkOut>, - seed_xa: [u8; 32], - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, - ) where - Module<B>: GLWESwitchingKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace, - Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + ScratchAvailable + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - assert!(sk_in.n() <= module.n()); - assert!(sk_out.n() <= module.n()); - assert!( - scratch.available() - >= GLWESwitchingKey::encrypt_sk_scratch_space( - module, - sk_out.n(), - self.basek(), - self.k(), - self.rank_in(), - self.rank_out() - ), - "scratch.available()={} < GLWESwitchingKey::encrypt_sk_scratch_space={}", - scratch.available(), - GLWESwitchingKey::encrypt_sk_scratch_space( - module, - sk_out.n(), - self.basek(), - self.k(), - self.rank_in(), - self.rank_out() - ) - ) - } - - let n: usize = sk_in.n().max(sk_out.n()); - - let (mut sk_in_tmp, scratch1) = scratch.take_scalar_znx(n, sk_in.rank()); - (0..sk_in.rank()).for_each(|i| { - module.vec_znx_switch_degree( - &mut sk_in_tmp.as_vec_znx_mut(), - i, - &sk_in.data.as_vec_znx(), - i, - ); - }); - - let (mut sk_out_tmp, scratch2) = scratch1.take_glwe_secret_exec(n, sk_out.rank()); - { - let (mut tmp, _) = scratch2.take_scalar_znx(n, 1); - (0..sk_out.rank()).for_each(|i| { - module.vec_znx_switch_degree(&mut tmp.as_vec_znx_mut(), 0, &sk_out.data.as_vec_znx(), i); - module.svp_prepare(&mut sk_out_tmp.data, i, &tmp, 0); - }); - } - - self.key.encrypt_sk( - module, - &sk_in_tmp, - &sk_out_tmp, - seed_xa, - source_xe, - sigma, - scratch2, - ); - self.sk_in_n = sk_in.n(); - self.sk_out_n = sk_out.n(); - } -} - -pub trait AutomorphismKeyEncryptSkFamily<B: Backend> = GGLWEEncryptSkFamily<B>; - -impl AutomorphismKey<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize - where - Module<B>: AutomorphismKeyEncryptSkFamily<B>, - { - GLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank, rank) + GLWESecret::bytes_of(n, rank) - } - - pub fn encrypt_pk_scratch_space<B: Backend>(module: &Module<B>, _n: usize, _basek: usize, _k: usize, _rank: usize) -> usize { - GLWESwitchingKey::encrypt_pk_scratch_space(module, _n, _basek, _k, _rank, _rank) - } -} - -impl<DataSelf: DataMut> AutomorphismKey<DataSelf> { - pub fn encrypt_sk<DataSk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - p: i64, - sk: &GLWESecret<DataSk>, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, - ) where - Module<B>: AutomorphismKeyEncryptSkFamily<B> + VecZnxAutomorphism + VecZnxSwithcDegree + VecZnxAddScalarInplace, - Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - assert_eq!(self.n(), sk.n()); - assert_eq!(self.rank_out(), self.rank_in()); - assert_eq!(sk.rank(), self.rank()); - assert!( - scratch.available() - >= AutomorphismKey::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k(), self.rank()), - "scratch.available(): {} < AutomorphismKey::encrypt_sk_scratch_space(module, self.rank()={}, self.size()={}): {}", - scratch.available(), - self.rank(), - self.size(), - AutomorphismKey::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k(), self.rank()) - ) - } - - let (mut sk_out, scratch_1) = scratch.take_glwe_secret(sk.n(), sk.rank()); - - { - (0..self.rank()).for_each(|i| { - module.vec_znx_automorphism( - module.galois_element_inv(p), - &mut sk_out.data.as_vec_znx_mut(), - i, - &sk.data.as_vec_znx(), - i, - ); - }); - } - - self.key - .encrypt_sk(module, &sk, &sk_out, source_xa, source_xe, sigma, scratch_1); - - self.p = p; - } -} - -impl AutomorphismKeyCompressed<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize - where - Module<B>: AutomorphismKeyEncryptSkFamily<B>, - { - GLWESwitchingKeyCompressed::encrypt_sk_scratch_space(module, n, basek, k, rank, rank) + GLWESecret::bytes_of(n, rank) - } -} - -impl<DataSelf: DataMut> AutomorphismKeyCompressed<DataSelf> { - pub fn encrypt_sk<DataSk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - p: i64, - sk: &GLWESecret<DataSk>, - seed_xa: [u8; 32], - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, - ) where - Module<B>: AutomorphismKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAutomorphism + VecZnxAddScalarInplace, - Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - assert_eq!(self.n(), sk.n()); - assert_eq!(self.rank_out(), self.rank_in()); - assert_eq!(sk.rank(), self.rank()); - assert!( - scratch.available() - >= AutomorphismKeyCompressed::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k(), self.rank()), - "scratch.available(): {} < AutomorphismKey::encrypt_sk_scratch_space(module, self.rank()={}, self.size()={}): {}", - scratch.available(), - self.rank(), - self.size(), - AutomorphismKeyCompressed::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k(), self.rank()) - ) - } - - let (mut sk_out, scratch_1) = scratch.take_glwe_secret(sk.n(), sk.rank()); - - { - (0..self.rank()).for_each(|i| { - module.vec_znx_automorphism( - module.galois_element_inv(p), - &mut sk_out.data.as_vec_znx_mut(), - i, - &sk.data.as_vec_znx(), - i, - ); - }); - } - - self.key - .encrypt_sk(module, &sk, &sk_out, seed_xa, source_xe, sigma, scratch_1); - - self.p = p; - } -} - -pub trait GLWETensorKeyEncryptSkFamily<B: Backend> = - GGLWEEncryptSkFamily<B> + VecZnxBigAllocBytes + VecZnxDftToVecZnxBigTmpA<B> + SvpApply<B>; - -impl GLWETensorKey<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize - where - Module<B>: GLWETensorKeyEncryptSkFamily<B>, - { - GLWESecretExec::bytes_of(module, n, rank) - + module.vec_znx_dft_alloc_bytes(n, rank, 1) - + module.vec_znx_big_alloc_bytes(n, 1, 1) - + module.vec_znx_dft_alloc_bytes(n, 1, 1) - + GLWESecret::bytes_of(n, 1) - + GLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank, rank) - } -} - -impl<DataSelf: DataMut> GLWETensorKey<DataSelf> { - pub fn encrypt_sk<DataSk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - sk: &GLWESecret<DataSk>, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, - ) where - Module<B>: GLWETensorKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace, - Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeGLWESecretExec<B> + TakeScalarZnx + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - assert_eq!(self.rank(), sk.rank()); - assert_eq!(self.n(), sk.n()); - } - - let n: usize = sk.n(); - - let rank: usize = self.rank(); - - let (mut sk_dft_prep, scratch1) = scratch.take_glwe_secret_exec(n, rank); - sk_dft_prep.prepare(module, &sk); - - let (mut sk_dft, scratch2) = scratch1.take_vec_znx_dft(n, rank, 1); - - (0..rank).for_each(|i| { - module.vec_znx_dft_from_vec_znx(1, 0, &mut sk_dft, i, &sk.data.as_vec_znx(), i); - }); - - let (mut sk_ij_big, scratch3) = scratch2.take_vec_znx_big(n, 1, 1); - let (mut sk_ij, scratch4) = scratch3.take_glwe_secret(n, 1); - let (mut sk_ij_dft, scratch5) = scratch4.take_vec_znx_dft(n, 1, 1); - - (0..rank).for_each(|i| { - (i..rank).for_each(|j| { - module.svp_apply(&mut sk_ij_dft, 0, &sk_dft_prep.data, j, &sk_dft, i); - - module.vec_znx_dft_to_vec_znx_big_tmp_a(&mut sk_ij_big, 0, &mut sk_ij_dft, 0); - module.vec_znx_big_normalize( - self.basek(), - &mut sk_ij.data.as_vec_znx_mut(), - 0, - &sk_ij_big, - 0, - scratch5, - ); - - self.at_mut(i, j) - .encrypt_sk(module, &sk_ij, sk, source_xa, source_xe, sigma, scratch5); - }); - }) - } -} - -impl GLWETensorKeyCompressed<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize - where - Module<B>: GLWETensorKeyEncryptSkFamily<B>, - { - GLWETensorKey::encrypt_sk_scratch_space(module, n, basek, k, rank) - } -} - -impl<DataSelf: DataMut> GLWETensorKeyCompressed<DataSelf> { - pub fn encrypt_sk<DataSk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - sk: &GLWESecret<DataSk>, - seed_xa: [u8; 32], - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, - ) where - Module<B>: GLWETensorKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace, - Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeGLWESecretExec<B> + TakeScalarZnx + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - assert_eq!(self.rank(), sk.rank()); - assert_eq!(self.n(), sk.n()); - } - - let n: usize = sk.n(); - let rank: usize = self.rank(); - - let (mut sk_dft_prep, scratch1) = scratch.take_glwe_secret_exec(n, rank); - sk_dft_prep.prepare(module, &sk); - - let (mut sk_dft, scratch2) = scratch1.take_vec_znx_dft(n, rank, 1); - - (0..rank).for_each(|i| { - module.vec_znx_dft_from_vec_znx(1, 0, &mut sk_dft, i, &sk.data.as_vec_znx(), i); - }); - - let (mut sk_ij_big, scratch3) = scratch2.take_vec_znx_big(n, 1, 1); - let (mut sk_ij, scratch4) = scratch3.take_glwe_secret(n, 1); - let (mut sk_ij_dft, scratch5) = scratch4.take_vec_znx_dft(n, 1, 1); - - let mut source_xa: Source = Source::new(seed_xa); - - (0..rank).for_each(|i| { - (i..rank).for_each(|j| { - module.svp_apply(&mut sk_ij_dft, 0, &sk_dft_prep.data, j, &sk_dft, i); - - module.vec_znx_dft_to_vec_znx_big_tmp_a(&mut sk_ij_big, 0, &mut sk_ij_dft, 0); - module.vec_znx_big_normalize( - self.basek(), - &mut sk_ij.data.as_vec_znx_mut(), - 0, - &sk_ij_big, - 0, - scratch5, - ); - - let (seed_xa_tmp, _) = source_xa.branch(); - - self.at_mut(i, j) - .encrypt_sk(module, &sk_ij, sk, seed_xa_tmp, source_xe, sigma, scratch5); - }); - }) - } -}
@@ -3,9 +3,12 @@ api::{ScratchAvailable, TakeVecZnxDft, ZnxZero},
layouts::{Backend, DataMut, DataRef, Module, Scratch}, }; -use crate::{AutomorphismKey, GGSWCiphertextExec, GLWECiphertext, GLWEExternalProductFamily, GLWESwitchingKey, Infos}; +use crate::{ + layouts::{GLWECiphertext, GGLWESwitchingKey, Infos, prepared::GGSWCiphertextExec}, + trait_families::GLWEExternalProductFamily, +}; -impl GLWESwitchingKey<Vec<u8>> { +impl GGLWESwitchingKey<Vec<u8>> { pub fn external_product_scratch_space<B: Backend>( module: &Module<B>, n: usize,@@ -38,11 +41,11 @@ GLWECiphertext::external_product_inplace_scratch_space(module, n, basek, k_out, k_ggsw, digits, rank)
} } -impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> { +impl<DataSelf: DataMut> GGLWESwitchingKey<DataSelf> { pub fn external_product<DataLhs: DataRef, DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - lhs: &GLWESwitchingKey<DataLhs>, + lhs: &GGLWESwitchingKey<DataLhs>, rhs: &GGSWCiphertextExec<DataRhs, B>, scratch: &mut Scratch<B>, ) where@@ -116,63 +119,3 @@ });
}); } } - -impl AutomorphismKey<Vec<u8>> { - pub fn external_product_scratch_space<B: Backend>( - module: &Module<B>, - n: usize, - basek: usize, - k_out: usize, - k_in: usize, - ggsw_k: usize, - digits: usize, - rank: usize, - ) -> usize - where - Module<B>: GLWEExternalProductFamily<B>, - { - GLWESwitchingKey::external_product_scratch_space(module, n, basek, k_out, k_in, ggsw_k, digits, rank) - } - - pub fn external_product_inplace_scratch_space<B: Backend>( - module: &Module<B>, - n: usize, - basek: usize, - k_out: usize, - ggsw_k: usize, - digits: usize, - rank: usize, - ) -> usize - where - Module<B>: GLWEExternalProductFamily<B>, - { - GLWESwitchingKey::external_product_inplace_scratch_space(module, n, basek, k_out, ggsw_k, digits, rank) - } -} - -impl<DataSelf: DataMut> AutomorphismKey<DataSelf> { - pub fn external_product<DataLhs: DataRef, DataRhs: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - lhs: &AutomorphismKey<DataLhs>, - rhs: &GGSWCiphertextExec<DataRhs, B>, - scratch: &mut Scratch<B>, - ) where - Module<B>: GLWEExternalProductFamily<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable, - { - self.key.external_product(module, &lhs.key, rhs, scratch); - } - - pub fn external_product_inplace<DataRhs: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - rhs: &GGSWCiphertextExec<DataRhs, B>, - scratch: &mut Scratch<B>, - ) where - Module<B>: GLWEExternalProductFamily<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable, - { - self.key.external_product_inplace(module, rhs, scratch); - } -}
@@ -4,10 +4,14 @@ layouts::{Backend, DataMut, DataRef, Module, Scratch},
}; use crate::{ - AutomorphismKey, AutomorphismKeyExec, GLWECiphertext, GLWEKeyswitchFamily, GLWESwitchingKey, GLWESwitchingKeyExec, Infos, + layouts::{ + GGLWEAutomorphismKey, GLWECiphertext, GGLWESwitchingKey, Infos, + prepared::{GGLWEAutomorphismKeyExec, GGLWESwitchingKeyExec}, + }, + trait_families::GLWEKeyswitchFamily, }; -impl AutomorphismKey<Vec<u8>> { +impl GGLWEAutomorphismKey<Vec<u8>> { pub fn keyswitch_scratch_space<B: Backend>( module: &Module<B>, n: usize,@@ -21,7 +25,7 @@ ) -> usize
where Module<B>: GLWEKeyswitchFamily<B>, { - GLWESwitchingKey::keyswitch_scratch_space(module, n, basek, k_out, k_in, k_ksk, digits, rank, rank) + GGLWESwitchingKey::keyswitch_scratch_space(module, n, basek, k_out, k_in, k_ksk, digits, rank, rank) } pub fn keyswitch_inplace_scratch_space<B: Backend>(@@ -36,16 +40,16 @@ ) -> usize
where Module<B>: GLWEKeyswitchFamily<B>, { - GLWESwitchingKey::keyswitch_inplace_scratch_space(module, n, basek, k_out, k_ksk, digits, rank) + GGLWESwitchingKey::keyswitch_inplace_scratch_space(module, n, basek, k_out, k_ksk, digits, rank) } } -impl<DataSelf: DataMut> AutomorphismKey<DataSelf> { +impl<DataSelf: DataMut> GGLWEAutomorphismKey<DataSelf> { pub fn keyswitch<DataLhs: DataRef, DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - lhs: &AutomorphismKey<DataLhs>, - rhs: &GLWESwitchingKeyExec<DataRhs, B>, + lhs: &GGLWEAutomorphismKey<DataLhs>, + rhs: &GGLWESwitchingKeyExec<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B>,@@ -57,7 +61,7 @@
pub fn keyswitch_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &AutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B>,@@ -67,7 +71,7 @@ self.key.keyswitch_inplace(module, &rhs.key, scratch);
} } -impl GLWESwitchingKey<Vec<u8>> { +impl GGLWESwitchingKey<Vec<u8>> { pub fn keyswitch_scratch_space<B: Backend>( module: &Module<B>, n: usize,@@ -103,12 +107,12 @@ GLWECiphertext::keyswitch_inplace_scratch_space(module, n, basek, k_out, k_ksk, digits, rank)
} } -impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> { +impl<DataSelf: DataMut> GGLWESwitchingKey<DataSelf> { pub fn keyswitch<DataLhs: DataRef, DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - lhs: &GLWESwitchingKey<DataLhs>, - rhs: &GLWESwitchingKeyExec<DataRhs, B>, + lhs: &GGLWESwitchingKey<DataLhs>, + rhs: &GGLWESwitchingKeyExec<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B>,@@ -156,7 +160,7 @@
pub fn keyswitch_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &GLWESwitchingKeyExec<DataRhs, B>, + rhs: &GGLWESwitchingKeyExec<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B>,
@@ -1,541 +0,0 @@
-use backend::hal::{ - api::{FillUniform, Reset, VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare}, - layouts::{Backend, Data, DataMut, DataRef, MatZnx, ReaderFrom, WriterTo}, -}; - -use crate::{GLWECiphertext, Infos}; -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; - -pub trait GGLWEExecLayoutFamily<B: Backend> = VmpPMatAlloc<B> + VmpPMatAllocBytes + VmpPMatPrepare<B>; -use std::fmt; - -#[derive(PartialEq, Eq, Clone)] -pub struct GGLWECiphertext<D: Data> { - pub(crate) data: MatZnx<D>, - pub(crate) basek: usize, - pub(crate) k: usize, - pub(crate) digits: usize, -} - -impl<D: DataRef> fmt::Debug for GGLWECiphertext<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl<D: DataMut> FillUniform for GGLWECiphertext<D> { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.data.fill_uniform(source); - } -} - -impl<D: DataMut> Reset for GGLWECiphertext<D> { - fn reset(&mut self) { - self.data.reset(); - self.basek = 0; - self.k = 0; - self.digits = 0; - } -} - -impl<D: DataRef> fmt::Display for GGLWECiphertext<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "(GGLWECiphertext: basek={} k={} digits={}) {}", - self.basek, self.k, self.digits, self.data - ) - } -} - -impl<D: DataRef> GGLWECiphertext<D> { - pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> { - GLWECiphertext { - data: self.data.at(row, col), - basek: self.basek, - k: self.k, - } - } -} - -impl<D: DataMut> GGLWECiphertext<D> { - pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> { - GLWECiphertext { - data: self.data.at_mut(row, col), - basek: self.basek, - k: self.k, - } - } -} - -impl GGLWECiphertext<Vec<u8>> { - pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self { - let size: usize = k.div_ceil(basek); - debug_assert!( - size > digits, - "invalid gglwe: ceil(k/basek): {} <= digits: {}", - size, - digits - ); - - assert!( - rows * digits <= size, - "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}", - rows, - digits, - size - ); - - Self { - data: MatZnx::alloc(n, rows, rank_in, rank_out + 1, size), - basek: basek, - k, - digits, - } - } - - pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> usize { - let size: usize = k.div_ceil(basek); - debug_assert!( - size > digits, - "invalid gglwe: ceil(k/basek): {} <= digits: {}", - size, - digits - ); - - assert!( - rows * digits <= size, - "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}", - rows, - digits, - size - ); - - MatZnx::alloc_bytes(n, rows, rank_in, rank_out + 1, rows) - } -} - -impl<D: Data> Infos for GGLWECiphertext<D> { - type Inner = MatZnx<D>; - - fn inner(&self) -> &Self::Inner { - &self.data - } - - fn basek(&self) -> usize { - self.basek - } - - fn k(&self) -> usize { - self.k - } -} - -impl<D: Data> GGLWECiphertext<D> { - pub fn rank(&self) -> usize { - self.data.cols_out() - 1 - } - - pub fn digits(&self) -> usize { - self.digits - } - - pub fn rank_in(&self) -> usize { - self.data.cols_in() - } - - pub fn rank_out(&self) -> usize { - self.data.cols_out() - 1 - } -} - -impl<D: DataMut> ReaderFrom for GGLWECiphertext<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - self.k = reader.read_u64::<LittleEndian>()? as usize; - self.basek = reader.read_u64::<LittleEndian>()? as usize; - self.digits = reader.read_u64::<LittleEndian>()? as usize; - self.data.read_from(reader) - } -} - -impl<D: DataRef> WriterTo for GGLWECiphertext<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::<LittleEndian>(self.k as u64)?; - writer.write_u64::<LittleEndian>(self.basek as u64)?; - writer.write_u64::<LittleEndian>(self.digits as u64)?; - self.data.write_to(writer) - } -} - -#[derive(PartialEq, Eq, Clone)] -pub struct GLWESwitchingKey<D: Data> { - pub(crate) key: GGLWECiphertext<D>, - pub(crate) sk_in_n: usize, // Degree of sk_in - pub(crate) sk_out_n: usize, // Degree of sk_out -} - -impl<D: DataRef> fmt::Debug for GLWESwitchingKey<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl<D: DataRef> fmt::Display for GLWESwitchingKey<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "(GLWESwitchingKey: sk_in_n={} sk_out_n={}) {}", - self.sk_in_n, self.sk_out_n, self.key.data - ) - } -} - -impl<D: DataMut> FillUniform for GLWESwitchingKey<D> { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.key.fill_uniform(source); - } -} - -impl<D: DataMut> Reset for GLWESwitchingKey<D> -where - MatZnx<D>: Reset, -{ - fn reset(&mut self) { - self.key.reset(); - self.sk_in_n = 0; - self.sk_out_n = 0; - } -} - -impl GLWESwitchingKey<Vec<u8>> { - pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self { - GLWESwitchingKey { - key: GGLWECiphertext::alloc(n, basek, k, rows, digits, rank_in, rank_out), - sk_in_n: 0, - sk_out_n: 0, - } - } - - pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> usize { - GGLWECiphertext::<Vec<u8>>::bytes_of(n, basek, k, rows, digits, rank_in, rank_out) - } -} - -impl<D: Data> Infos for GLWESwitchingKey<D> { - type Inner = MatZnx<D>; - - fn inner(&self) -> &Self::Inner { - self.key.inner() - } - - fn basek(&self) -> usize { - self.key.basek() - } - - fn k(&self) -> usize { - self.key.k() - } -} - -impl<D: Data> GLWESwitchingKey<D> { - pub fn rank(&self) -> usize { - self.key.data.cols_out() - 1 - } - - pub fn rank_in(&self) -> usize { - self.key.data.cols_in() - } - - pub fn rank_out(&self) -> usize { - self.key.data.cols_out() - 1 - } - - pub fn digits(&self) -> usize { - self.key.digits() - } - - pub fn sk_degree_in(&self) -> usize { - self.sk_in_n - } - - pub fn sk_degree_out(&self) -> usize { - self.sk_out_n - } -} - -impl<D: DataRef> GLWESwitchingKey<D> { - pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> { - self.key.at(row, col) - } -} - -impl<D: DataMut> GLWESwitchingKey<D> { - pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> { - self.key.at_mut(row, col) - } -} - -impl<D: DataMut> ReaderFrom for GLWESwitchingKey<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - self.sk_in_n = reader.read_u64::<LittleEndian>()? as usize; - self.sk_out_n = reader.read_u64::<LittleEndian>()? as usize; - self.key.read_from(reader) - } -} - -impl<D: DataRef> WriterTo for GLWESwitchingKey<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::<LittleEndian>(self.sk_in_n as u64)?; - writer.write_u64::<LittleEndian>(self.sk_out_n as u64)?; - self.key.write_to(writer) - } -} - -#[derive(PartialEq, Eq, Clone)] -pub struct AutomorphismKey<D: Data> { - pub(crate) key: GLWESwitchingKey<D>, - pub(crate) p: i64, -} - -impl<D: DataRef> fmt::Debug for AutomorphismKey<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl<D: DataMut> FillUniform for AutomorphismKey<D> { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.key.fill_uniform(source); - } -} - -impl<D: DataMut> Reset for AutomorphismKey<D> -where - MatZnx<D>: Reset, -{ - fn reset(&mut self) { - self.key.reset(); - self.p = 0; - } -} - -impl<D: DataRef> fmt::Display for AutomorphismKey<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "(AutomorphismKey: p={}) {}", self.p, self.key) - } -} - -impl AutomorphismKey<Vec<u8>> { - pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self { - AutomorphismKey { - key: GLWESwitchingKey::alloc(n, basek, k, rows, digits, rank, rank), - p: 0, - } - } - - pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize { - GLWESwitchingKey::bytes_of(n, basek, k, rows, digits, rank, rank) - } -} - -impl<D: Data> Infos for AutomorphismKey<D> { - type Inner = MatZnx<D>; - - fn inner(&self) -> &Self::Inner { - &self.key.inner() - } - - fn basek(&self) -> usize { - self.key.basek() - } - - fn k(&self) -> usize { - self.key.k() - } -} - -impl<D: Data> AutomorphismKey<D> { - pub fn p(&self) -> i64 { - self.p - } - - pub fn digits(&self) -> usize { - self.key.digits() - } - - pub fn rank(&self) -> usize { - self.key.rank() - } - - pub fn rank_in(&self) -> usize { - self.key.rank_in() - } - - pub fn rank_out(&self) -> usize { - self.key.rank_out() - } -} - -impl<D: DataRef> AutomorphismKey<D> { - pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> { - self.key.at(row, col) - } -} - -impl<D: DataMut> AutomorphismKey<D> { - pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> { - self.key.at_mut(row, col) - } -} - -impl<D: DataMut> ReaderFrom for AutomorphismKey<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - self.p = reader.read_u64::<LittleEndian>()? as i64; - self.key.read_from(reader) - } -} - -impl<D: DataRef> WriterTo for AutomorphismKey<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::<LittleEndian>(self.p as u64)?; - self.key.write_to(writer) - } -} - -#[derive(PartialEq, Eq, Clone)] -pub struct GLWETensorKey<D: Data> { - pub(crate) keys: Vec<GLWESwitchingKey<D>>, -} - -impl<D: DataRef> fmt::Debug for GLWETensorKey<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl<D: DataMut> FillUniform for GLWETensorKey<D> { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.keys - .iter_mut() - .for_each(|key: &mut GLWESwitchingKey<D>| key.fill_uniform(source)) - } -} - -impl<D: DataMut> Reset for GLWETensorKey<D> -where - MatZnx<D>: Reset, -{ - fn reset(&mut self) { - self.keys - .iter_mut() - .for_each(|key: &mut GLWESwitchingKey<D>| key.reset()) - } -} - -impl<D: DataRef> fmt::Display for GLWETensorKey<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - writeln!(f, "(GLWETensorKey)",)?; - for (i, key) in self.keys.iter().enumerate() { - write!(f, "{}: {}", i, key)?; - } - Ok(()) - } -} - -impl GLWETensorKey<Vec<u8>> { - pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self { - let mut keys: Vec<GLWESwitchingKey<Vec<u8>>> = Vec::new(); - let pairs: usize = (((rank + 1) * rank) >> 1).max(1); - (0..pairs).for_each(|_| { - keys.push(GLWESwitchingKey::alloc(n, basek, k, rows, digits, 1, rank)); - }); - Self { keys: keys } - } - - pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize { - let pairs: usize = (((rank + 1) * rank) >> 1).max(1); - pairs * GLWESwitchingKey::<Vec<u8>>::bytes_of(n, basek, k, rows, digits, 1, rank) - } -} - -impl<D: Data> Infos for GLWETensorKey<D> { - type Inner = MatZnx<D>; - - fn inner(&self) -> &Self::Inner { - &self.keys[0].inner() - } - - fn basek(&self) -> usize { - self.keys[0].basek() - } - - fn k(&self) -> usize { - self.keys[0].k() - } -} - -impl<D: Data> GLWETensorKey<D> { - pub fn rank(&self) -> usize { - self.keys[0].rank() - } - - pub fn rank_in(&self) -> usize { - self.keys[0].rank_in() - } - - pub fn rank_out(&self) -> usize { - self.keys[0].rank_out() - } - - pub fn digits(&self) -> usize { - self.keys[0].digits() - } -} - -impl<D: DataMut> GLWETensorKey<D> { - // Returns a mutable reference to GLWESwitchingKey_{s}(s[i] * s[j]) - pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GLWESwitchingKey<D> { - if i > j { - std::mem::swap(&mut i, &mut j); - }; - let rank: usize = self.rank(); - &mut self.keys[i * rank + j - (i * (i + 1) / 2)] - } -} - -impl<D: DataRef> GLWETensorKey<D> { - // Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j]) - pub fn at(&self, mut i: usize, mut j: usize) -> &GLWESwitchingKey<D> { - if i > j { - std::mem::swap(&mut i, &mut j); - }; - let rank: usize = self.rank(); - &self.keys[i * rank + j - (i * (i + 1) / 2)] - } -} - -impl<D: DataMut> ReaderFrom for GLWETensorKey<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - let len: usize = reader.read_u64::<LittleEndian>()? as usize; - if self.keys.len() != len { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, - format!("self.keys.len()={} != read len={}", self.keys.len(), len), - )); - } - for key in &mut self.keys { - key.read_from(reader)?; - } - Ok(()) - } -} - -impl<D: DataRef> WriterTo for GLWETensorKey<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::<LittleEndian>(self.keys.len() as u64)?; - for key in &self.keys { - key.write_to(writer)?; - } - Ok(()) - } -}
@@ -1,626 +0,0 @@
-use backend::hal::{ - api::{FillUniform, Reset, VecZnxCopy, VecZnxFillUniform}, - layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, WriterTo}, -}; - -use crate::{AutomorphismKey, Decompress, GGLWECiphertext, GLWECiphertextCompressed, GLWESwitchingKey, GLWETensorKey, Infos}; -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; -use std::fmt; - -#[derive(PartialEq, Eq, Clone)] -pub struct GGLWECiphertextCompressed<D: Data> { - pub(crate) data: MatZnx<D>, - pub(crate) basek: usize, - pub(crate) k: usize, - pub(crate) rank_out: usize, - pub(crate) digits: usize, - pub(crate) seed: Vec<[u8; 32]>, -} - -impl<D: DataRef> fmt::Debug for GGLWECiphertextCompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl<D: DataMut> FillUniform for GGLWECiphertextCompressed<D> { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.data.fill_uniform(source); - } -} - -impl<D: DataMut> Reset for GGLWECiphertextCompressed<D> -where - MatZnx<D>: Reset, -{ - fn reset(&mut self) { - self.data.reset(); - self.basek = 0; - self.k = 0; - self.digits = 0; - self.rank_out = 0; - self.seed = Vec::new(); - } -} - -impl<D: DataRef> fmt::Display for GGLWECiphertextCompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "(GGLWECiphertextCompressed: basek={} k={} digits={}) {}", - self.basek, self.k, self.digits, self.data - ) - } -} - -impl GGLWECiphertextCompressed<Vec<u8>> { - pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self { - let size: usize = k.div_ceil(basek); - debug_assert!( - size > digits, - "invalid gglwe: ceil(k/basek): {} <= digits: {}", - size, - digits - ); - - assert!( - rows * digits <= size, - "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}", - rows, - digits, - size - ); - - Self { - data: MatZnx::alloc(n, rows, rank_in, 1, size), - basek: basek, - k, - rank_out, - digits, - seed: vec![[0u8; 32]; rows * rank_in], - } - } - - pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize) -> usize { - let size: usize = k.div_ceil(basek); - debug_assert!( - size > digits, - "invalid gglwe: ceil(k/basek): {} <= digits: {}", - size, - digits - ); - - assert!( - rows * digits <= size, - "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}", - rows, - digits, - size - ); - - MatZnx::alloc_bytes(n, rows, rank_in, 1, rows) - } -} - -impl<D: Data> Infos for GGLWECiphertextCompressed<D> { - type Inner = MatZnx<D>; - - fn inner(&self) -> &Self::Inner { - &self.data - } - - fn basek(&self) -> usize { - self.basek - } - - fn k(&self) -> usize { - self.k - } -} - -impl<D: Data> GGLWECiphertextCompressed<D> { - pub fn rank(&self) -> usize { - self.rank_out - } - - pub fn digits(&self) -> usize { - self.digits - } - - pub fn rank_in(&self) -> usize { - self.data.cols_in() - } - - pub fn rank_out(&self) -> usize { - self.rank_out - } -} - -impl<D: DataRef> GGLWECiphertextCompressed<D> { - pub(crate) fn at(&self, row: usize, col: usize) -> GLWECiphertextCompressed<&[u8]> { - GLWECiphertextCompressed { - data: self.data.at(row, col), - basek: self.basek, - k: self.k, - rank: self.rank_out, - seed: self.seed[self.rank_in() * row + col], - } - } -} - -impl<D: DataMut> GGLWECiphertextCompressed<D> { - pub(crate) fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertextCompressed<&mut [u8]> { - let rank_in: usize = self.rank_in(); - GLWECiphertextCompressed { - data: self.data.at_mut(row, col), - basek: self.basek, - k: self.k, - rank: self.rank_out, - seed: self.seed[rank_in * row + col], // Warning: value is copied and not borrow mut - } - } -} - -impl<D: DataMut> ReaderFrom for GGLWECiphertextCompressed<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - self.k = reader.read_u64::<LittleEndian>()? as usize; - self.basek = reader.read_u64::<LittleEndian>()? as usize; - self.digits = reader.read_u64::<LittleEndian>()? as usize; - self.rank_out = reader.read_u64::<LittleEndian>()? as usize; - let seed_len = reader.read_u64::<LittleEndian>()? as usize; - self.seed = vec![[0u8; 32]; seed_len]; - for s in &mut self.seed { - reader.read_exact(s)?; - } - self.data.read_from(reader) - } -} - -impl<D: DataRef> WriterTo for GGLWECiphertextCompressed<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::<LittleEndian>(self.k as u64)?; - writer.write_u64::<LittleEndian>(self.basek as u64)?; - writer.write_u64::<LittleEndian>(self.digits as u64)?; - writer.write_u64::<LittleEndian>(self.rank_out as u64)?; - writer.write_u64::<LittleEndian>(self.seed.len() as u64)?; - for s in &self.seed { - writer.write_all(s)?; - } - self.data.write_to(writer) - } -} - -impl<D: DataMut, B: Backend, DR: DataRef> Decompress<B, GGLWECiphertextCompressed<DR>> for GGLWECiphertext<D> { - fn decompress(&mut self, module: &Module<B>, other: &GGLWECiphertextCompressed<DR>) - where - Module<B>: VecZnxFillUniform + VecZnxCopy, - { - #[cfg(debug_assertions)] - { - use backend::hal::api::ZnxInfos; - - assert_eq!( - self.n(), - other.data.n(), - "invalid receiver: self.n()={} != other.n()={}", - self.n(), - other.data.n() - ); - assert_eq!( - self.size(), - other.size(), - "invalid receiver: self.size()={} != other.size()={}", - self.size(), - other.size() - ); - assert_eq!( - self.rank_in(), - other.rank_in(), - "invalid receiver: self.rank_in()={} != other.rank_in()={}", - self.rank_in(), - other.rank_in() - ); - assert_eq!( - self.rank_out(), - other.rank_out(), - "invalid receiver: self.rank_out()={} != other.rank_out()={}", - self.rank_out(), - other.rank_out() - ); - - assert_eq!( - self.rows(), - other.rows(), - "invalid receiver: self.rows()={} != other.rows()={}", - self.rows(), - other.rows() - ); - } - - let rank_in: usize = self.rank_in(); - let rows: usize = self.rows(); - - (0..rank_in).for_each(|col_i| { - (0..rows).for_each(|row_i| { - self.at_mut(row_i, col_i) - .decompress(module, &other.at(row_i, col_i)); - }); - }); - } -} - -#[derive(PartialEq, Eq, Clone)] -pub struct GLWESwitchingKeyCompressed<D: Data> { - pub(crate) key: GGLWECiphertextCompressed<D>, - pub(crate) sk_in_n: usize, // Degree of sk_in - pub(crate) sk_out_n: usize, // Degree of sk_out -} - -impl<D: DataRef> fmt::Debug for GLWESwitchingKeyCompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl<D: DataMut> FillUniform for GLWESwitchingKeyCompressed<D> { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.key.fill_uniform(source); - } -} - -impl<D: DataMut> Reset for GLWESwitchingKeyCompressed<D> -where - MatZnx<D>: Reset, -{ - fn reset(&mut self) { - self.key.reset(); - self.sk_in_n = 0; - self.sk_out_n = 0; - } -} - -impl<D: DataRef> fmt::Display for GLWESwitchingKeyCompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "(GLWESwitchingKeyCompressed: sk_in_n={} sk_out_n={}) {}", - self.sk_in_n, self.sk_out_n, self.key.data - ) - } -} - -impl<D: Data> Infos for GLWESwitchingKeyCompressed<D> { - type Inner = MatZnx<D>; - - fn inner(&self) -> &Self::Inner { - &self.key.inner() - } - - fn basek(&self) -> usize { - self.key.basek() - } - - fn k(&self) -> usize { - self.key.k() - } -} - -impl<D: Data> GLWESwitchingKeyCompressed<D> { - pub fn rank(&self) -> usize { - self.key.rank() - } - - pub fn digits(&self) -> usize { - self.key.digits() - } - - pub fn rank_in(&self) -> usize { - self.key.rank_in() - } - - pub fn rank_out(&self) -> usize { - self.key.rank_out() - } -} - -impl GLWESwitchingKeyCompressed<Vec<u8>> { - pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self { - GLWESwitchingKeyCompressed { - key: GGLWECiphertextCompressed::alloc(n, basek, k, rows, digits, rank_in, rank_out), - sk_in_n: 0, - sk_out_n: 0, - } - } - - pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize) -> usize { - GGLWECiphertextCompressed::bytes_of(n, basek, k, rows, digits, rank_in) - } -} - -impl<D: DataMut> ReaderFrom for GLWESwitchingKeyCompressed<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - self.sk_in_n = reader.read_u64::<LittleEndian>()? as usize; - self.sk_out_n = reader.read_u64::<LittleEndian>()? as usize; - self.key.read_from(reader) - } -} - -impl<D: DataRef> WriterTo for GLWESwitchingKeyCompressed<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::<LittleEndian>(self.sk_in_n as u64)?; - writer.write_u64::<LittleEndian>(self.sk_out_n as u64)?; - self.key.write_to(writer) - } -} - -impl<D: DataMut> GLWESwitchingKey<D> { - pub fn decompress<DataOther: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - other: &GLWESwitchingKeyCompressed<DataOther>, - ) where - Module<B>: VecZnxFillUniform + VecZnxCopy, - { - self.key.decompress(module, &other.key); - self.sk_in_n = other.sk_in_n; - self.sk_out_n = other.sk_out_n; - } -} - -#[derive(PartialEq, Eq, Clone)] -pub struct AutomorphismKeyCompressed<D: Data> { - pub(crate) key: GLWESwitchingKeyCompressed<D>, - pub(crate) p: i64, -} - -impl<D: DataRef> fmt::Debug for AutomorphismKeyCompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl<D: DataMut> FillUniform for AutomorphismKeyCompressed<D> { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.key.fill_uniform(source); - } -} - -impl<D: DataMut> Reset for AutomorphismKeyCompressed<D> -where - MatZnx<D>: Reset, -{ - fn reset(&mut self) { - self.key.reset(); - self.p = 0; - } -} - -impl<D: DataRef> fmt::Display for AutomorphismKeyCompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "(AutomorphismKeyCompressed: p={}) {}", self.p, self.key) - } -} - -impl AutomorphismKeyCompressed<Vec<u8>> { - pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self { - AutomorphismKeyCompressed { - key: GLWESwitchingKeyCompressed::alloc(n, basek, k, rows, digits, rank, rank), - p: 0, - } - } - - pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize { - GLWESwitchingKeyCompressed::<Vec<u8>>::bytes_of(n, basek, k, rows, digits, rank) - } -} - -impl<D: Data> Infos for AutomorphismKeyCompressed<D> { - type Inner = MatZnx<D>; - - fn inner(&self) -> &Self::Inner { - &self.key.inner() - } - - fn basek(&self) -> usize { - self.key.basek() - } - - fn k(&self) -> usize { - self.key.k() - } -} - -impl<D: Data> AutomorphismKeyCompressed<D> { - pub fn rank(&self) -> usize { - self.key.rank() - } - - pub fn digits(&self) -> usize { - self.key.digits() - } - - pub fn rank_in(&self) -> usize { - self.key.rank_in() - } - - pub fn rank_out(&self) -> usize { - self.key.rank_out() - } -} - -impl<D: DataMut> ReaderFrom for AutomorphismKeyCompressed<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - self.p = reader.read_u64::<LittleEndian>()? as i64; - self.key.read_from(reader) - } -} - -impl<D: DataRef> WriterTo for AutomorphismKeyCompressed<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::<LittleEndian>(self.p as u64)?; - self.key.write_to(writer) - } -} - -impl<D: DataMut> AutomorphismKey<D> { - pub fn decompress<DataOther: DataRef, B: Backend>(&mut self, module: &Module<B>, other: &AutomorphismKeyCompressed<DataOther>) - where - Module<B>: VecZnxFillUniform + VecZnxCopy, - { - self.key.decompress(module, &other.key); - self.p = other.p; - } -} - -#[derive(PartialEq, Eq, Clone)] -pub struct GLWETensorKeyCompressed<D: Data> { - pub(crate) keys: Vec<GLWESwitchingKeyCompressed<D>>, -} - -impl<D: DataRef> fmt::Debug for GLWETensorKeyCompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl<D: DataMut> FillUniform for GLWETensorKeyCompressed<D> { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.keys - .iter_mut() - .for_each(|key: &mut GLWESwitchingKeyCompressed<D>| key.fill_uniform(source)) - } -} - -impl<D: DataMut> Reset for GLWETensorKeyCompressed<D> -where - MatZnx<D>: Reset, -{ - fn reset(&mut self) { - self.keys - .iter_mut() - .for_each(|key: &mut GLWESwitchingKeyCompressed<D>| key.reset()) - } -} - -impl<D: DataRef> fmt::Display for GLWETensorKeyCompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - writeln!(f, "(GLWETensorKeyCompressed)",)?; - for (i, key) in self.keys.iter().enumerate() { - write!(f, "{}: {}", i, key)?; - } - Ok(()) - } -} - -impl GLWETensorKeyCompressed<Vec<u8>> { - pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self { - let mut keys: Vec<GLWESwitchingKeyCompressed<Vec<u8>>> = Vec::new(); - let pairs: usize = (((rank + 1) * rank) >> 1).max(1); - (0..pairs).for_each(|_| { - keys.push(GLWESwitchingKeyCompressed::alloc( - n, basek, k, rows, digits, 1, rank, - )); - }); - Self { keys: keys } - } - - pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize { - let pairs: usize = (((rank + 1) * rank) >> 1).max(1); - pairs * GLWESwitchingKeyCompressed::bytes_of(n, basek, k, rows, digits, 1) - } -} - -impl<D: Data> Infos for GLWETensorKeyCompressed<D> { - type Inner = MatZnx<D>; - - fn inner(&self) -> &Self::Inner { - &self.keys[0].inner() - } - - fn basek(&self) -> usize { - self.keys[0].basek() - } - - fn k(&self) -> usize { - self.keys[0].k() - } -} - -impl<D: Data> GLWETensorKeyCompressed<D> { - pub fn rank(&self) -> usize { - self.keys[0].rank() - } - - pub fn digits(&self) -> usize { - self.keys[0].digits() - } - - pub fn rank_in(&self) -> usize { - self.keys[0].rank_in() - } - - pub fn rank_out(&self) -> usize { - self.keys[0].rank_out() - } -} - -impl<D: DataMut> ReaderFrom for GLWETensorKeyCompressed<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - let len: usize = reader.read_u64::<LittleEndian>()? as usize; - if self.keys.len() != len { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, - format!("self.keys.len()={} != read len={}", self.keys.len(), len), - )); - } - for key in &mut self.keys { - key.read_from(reader)?; - } - Ok(()) - } -} - -impl<D: DataRef> WriterTo for GLWETensorKeyCompressed<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::<LittleEndian>(self.keys.len() as u64)?; - for key in &self.keys { - key.write_to(writer)?; - } - Ok(()) - } -} - -impl<D: DataMut> GLWETensorKeyCompressed<D> { - pub(crate) fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GLWESwitchingKeyCompressed<D> { - if i > j { - std::mem::swap(&mut i, &mut j); - }; - let rank: usize = self.rank(); - &mut self.keys[i * rank + j - (i * (i + 1) / 2)] - } -} - -impl<D: DataMut> GLWETensorKey<D> { - pub fn decompress<DataOther: DataRef, B: Backend>(&mut self, module: &Module<B>, other: &GLWETensorKeyCompressed<DataOther>) - where - Module<B>: VecZnxFillUniform + VecZnxCopy, - { - #[cfg(debug_assertions)] - { - assert_eq!( - self.keys.len(), - other.keys.len(), - "invalid receiver: self.keys.len()={} != other.keys.len()={}", - self.keys.len(), - other.keys.len() - ); - } - - self.keys - .iter_mut() - .zip(other.keys.iter()) - .for_each(|(a, b)| { - a.decompress(module, b); - }); - } -}
@@ -1,465 +0,0 @@
-use backend::hal::{ - api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare}, - layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}, -}; - -use crate::{AutomorphismKey, GGLWECiphertext, GGLWEExecLayoutFamily, GLWESwitchingKey, GLWETensorKey, Infos}; - -#[derive(PartialEq, Eq)] -pub struct GGLWECiphertextExec<D: Data, B: Backend> { - pub(crate) data: VmpPMat<D, B>, - pub(crate) basek: usize, - pub(crate) k: usize, - pub(crate) digits: usize, -} - -impl<B: Backend> GGLWECiphertextExec<Vec<u8>, B> { - pub fn alloc( - module: &Module<B>, - n: usize, - basek: usize, - k: usize, - rows: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - ) -> Self - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - let size: usize = k.div_ceil(basek); - debug_assert!( - size > digits, - "invalid gglwe: ceil(k/basek): {} <= digits: {}", - size, - digits - ); - - assert!( - rows * digits <= size, - "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}", - rows, - digits, - size - ); - - Self { - data: module.vmp_pmat_alloc(n, rows, rank_in, rank_out + 1, size), - basek: basek, - k, - digits, - } - } - - pub fn bytes_of( - module: &Module<B>, - n: usize, - basek: usize, - k: usize, - rows: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - ) -> usize - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - let size: usize = k.div_ceil(basek); - debug_assert!( - size > digits, - "invalid gglwe: ceil(k/basek): {} <= digits: {}", - size, - digits - ); - - assert!( - rows * digits <= size, - "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}", - rows, - digits, - size - ); - - module.vmp_pmat_alloc_bytes(n, rows, rank_in, rank_out + 1, rows) - } -} - -impl<D: Data, B: Backend> Infos for GGLWECiphertextExec<D, B> { - type Inner = VmpPMat<D, B>; - - fn inner(&self) -> &Self::Inner { - &self.data - } - - fn basek(&self) -> usize { - self.basek - } - - fn k(&self) -> usize { - self.k - } -} - -impl<D: Data, B: Backend> GGLWECiphertextExec<D, B> { - pub fn rank(&self) -> usize { - self.data.cols_out() - 1 - } - - pub fn digits(&self) -> usize { - self.digits - } - - pub fn rank_in(&self) -> usize { - self.data.cols_in() - } - - pub fn rank_out(&self) -> usize { - self.data.cols_out() - 1 - } -} - -impl<D: DataMut, B: Backend> GGLWECiphertextExec<D, B> { - pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGLWECiphertext<DataOther>, scratch: &mut Scratch<B>) - where - DataOther: DataRef, - Module<B>: GGLWEExecLayoutFamily<B>, - { - module.vmp_prepare(&mut self.data, &other.data, scratch); - self.basek = other.basek; - self.k = other.k; - self.digits = other.digits; - } -} - -#[derive(PartialEq, Eq)] -pub struct GLWESwitchingKeyExec<D: Data, B: Backend> { - pub(crate) key: GGLWECiphertextExec<D, B>, - pub(crate) sk_in_n: usize, // Degree of sk_in - pub(crate) sk_out_n: usize, // Degree of sk_out -} - -impl<B: Backend> GLWESwitchingKeyExec<Vec<u8>, B> { - pub fn alloc( - module: &Module<B>, - n: usize, - basek: usize, - k: usize, - rows: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - ) -> Self - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - GLWESwitchingKeyExec::<Vec<u8>, B> { - key: GGLWECiphertextExec::alloc(module, n, basek, k, rows, digits, rank_in, rank_out), - sk_in_n: 0, - sk_out_n: 0, - } - } - - pub fn bytes_of( - module: &Module<B>, - n: usize, - basek: usize, - k: usize, - rows: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - ) -> usize - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - GGLWECiphertextExec::bytes_of(module, n, basek, k, rows, digits, rank_in, rank_out) - } - - pub fn from<DataOther: DataRef>(module: &Module<B>, other: &GLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) -> Self - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - let mut ksk_exec: GLWESwitchingKeyExec<Vec<u8>, B> = Self::alloc( - module, - other.n(), - other.basek(), - other.k(), - other.rows(), - other.digits(), - other.rank_in(), - other.rank_out(), - ); - ksk_exec.prepare(module, other, scratch); - ksk_exec - } -} - -impl<D: Data, B: Backend> Infos for GLWESwitchingKeyExec<D, B> { - type Inner = VmpPMat<D, B>; - - fn inner(&self) -> &Self::Inner { - self.key.inner() - } - - fn basek(&self) -> usize { - self.key.basek() - } - - fn k(&self) -> usize { - self.key.k() - } -} - -impl<D: Data, B: Backend> GLWESwitchingKeyExec<D, B> { - pub fn rank(&self) -> usize { - self.key.data.cols_out() - 1 - } - - pub fn rank_in(&self) -> usize { - self.key.data.cols_in() - } - - pub fn rank_out(&self) -> usize { - self.key.data.cols_out() - 1 - } - - pub fn digits(&self) -> usize { - self.key.digits() - } - - pub fn sk_degree_in(&self) -> usize { - self.sk_in_n - } - - pub fn sk_degree_out(&self) -> usize { - self.sk_out_n - } -} - -impl<D: DataMut, B: Backend> GLWESwitchingKeyExec<D, B> { - pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) - where - DataOther: DataRef, - Module<B>: GGLWEExecLayoutFamily<B>, - { - self.key.prepare(module, &other.key, scratch); - self.sk_in_n = other.sk_in_n; - self.sk_out_n = other.sk_out_n; - } -} - -#[derive(PartialEq, Eq)] -pub struct AutomorphismKeyExec<D: Data, B: Backend> { - pub(crate) key: GLWESwitchingKeyExec<D, B>, - pub(crate) p: i64, -} - -impl<B: Backend> AutomorphismKeyExec<Vec<u8>, B> { - pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - AutomorphismKeyExec::<Vec<u8>, B> { - key: GLWESwitchingKeyExec::alloc(module, n, basek, k, rows, digits, rank, rank), - p: 0, - } - } - - pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - GLWESwitchingKeyExec::bytes_of(module, n, basek, k, rows, digits, rank, rank) - } - - pub fn from<DataOther: DataRef>(module: &Module<B>, other: &AutomorphismKey<DataOther>, scratch: &mut Scratch<B>) -> Self - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - let mut atk_exec: AutomorphismKeyExec<Vec<u8>, B> = Self::alloc( - module, - other.n(), - other.basek(), - other.k(), - other.rows(), - other.digits(), - other.rank(), - ); - atk_exec.prepare(module, other, scratch); - atk_exec - } -} - -impl<D: DataMut, B: Backend> AutomorphismKeyExec<D, B> { - pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &AutomorphismKey<DataOther>, scratch: &mut Scratch<B>) - where - DataOther: DataRef, - Module<B>: GGLWEExecLayoutFamily<B>, - { - self.key.prepare(module, &other.key, scratch); - self.p = other.p; - } -} - -impl<D: Data, B: Backend> Infos for AutomorphismKeyExec<D, B> { - type Inner = VmpPMat<D, B>; - - fn inner(&self) -> &Self::Inner { - &self.key.inner() - } - - fn basek(&self) -> usize { - self.key.basek() - } - - fn k(&self) -> usize { - self.key.k() - } -} - -impl<D: Data, B: Backend> AutomorphismKeyExec<D, B> { - pub fn p(&self) -> i64 { - self.p - } - - pub fn digits(&self) -> usize { - self.key.digits() - } - - pub fn rank(&self) -> usize { - self.key.rank() - } - - pub fn rank_in(&self) -> usize { - self.key.rank_in() - } - - pub fn rank_out(&self) -> usize { - self.key.rank_out() - } -} - -#[derive(PartialEq, Eq)] -pub struct GLWETensorKeyExec<D: Data, B: Backend> { - pub(crate) keys: Vec<GLWESwitchingKeyExec<D, B>>, -} - -impl<B: Backend> GLWETensorKeyExec<Vec<u8>, B> { - pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - let mut keys: Vec<GLWESwitchingKeyExec<Vec<u8>, B>> = Vec::new(); - let pairs: usize = (((rank + 1) * rank) >> 1).max(1); - (0..pairs).for_each(|_| { - keys.push(GLWESwitchingKeyExec::alloc( - module, n, basek, k, rows, digits, 1, rank, - )); - }); - Self { keys } - } - - pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - let pairs: usize = (((rank + 1) * rank) >> 1).max(1); - pairs * GLWESwitchingKeyExec::bytes_of(module, n, basek, k, rows, digits, 1, rank) - } - - pub fn from<D: DataRef>( - module: &Module<B>, - other: &GLWETensorKey<D>, - scratch: &mut Scratch<B>, - ) -> GLWETensorKeyExec<Vec<u8>, B> - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - let mut tsk_exec: GLWETensorKeyExec<Vec<u8>, B> = Self::alloc( - module, - other.n(), - other.basek(), - other.k(), - other.rows(), - other.digits(), - other.rank(), - ); - tsk_exec.prepare(module, other, scratch); - tsk_exec - } -} - -impl<D: Data, B: Backend> Infos for GLWETensorKeyExec<D, B> { - type Inner = VmpPMat<D, B>; - - fn inner(&self) -> &Self::Inner { - &self.keys[0].inner() - } - - fn basek(&self) -> usize { - self.keys[0].basek() - } - - fn k(&self) -> usize { - self.keys[0].k() - } -} - -impl<D: Data, B: Backend> GLWETensorKeyExec<D, B> { - pub fn rank(&self) -> usize { - self.keys[0].rank() - } - - pub fn rank_in(&self) -> usize { - self.keys[0].rank_in() - } - - pub fn rank_out(&self) -> usize { - self.keys[0].rank_out() - } - - pub fn digits(&self) -> usize { - self.keys[0].digits() - } -} - -impl<D: DataMut, B: Backend> GLWETensorKeyExec<D, B> { - // Returns a mutable reference to GLWESwitchingKey_{s}(s[i] * s[j]) - pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GLWESwitchingKeyExec<D, B> { - if i > j { - std::mem::swap(&mut i, &mut j); - }; - let rank: usize = self.rank(); - &mut self.keys[i * rank + j - (i * (i + 1) / 2)] - } -} - -impl<D: DataRef, B: Backend> GLWETensorKeyExec<D, B> { - // Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j]) - pub fn at(&self, mut i: usize, mut j: usize) -> &GLWESwitchingKeyExec<D, B> { - if i > j { - std::mem::swap(&mut i, &mut j); - }; - let rank: usize = self.rank(); - &self.keys[i * rank + j - (i * (i + 1) / 2)] - } -} - -impl<D: DataMut, B: Backend> GLWETensorKeyExec<D, B> { - pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GLWETensorKey<DataOther>, scratch: &mut Scratch<B>) - where - DataOther: DataRef, - Module<B>: GGLWEExecLayoutFamily<B>, - { - #[cfg(debug_assertions)] - { - assert_eq!(self.keys.len(), other.keys.len()); - } - self.keys - .iter_mut() - .zip(other.keys.iter()) - .for_each(|(a, b)| { - a.prepare(module, b, scratch); - }); - } -}
@@ -1,16 +0,0 @@
-mod automorphism; -mod encryption; -mod external_product; -mod keyswitch; -mod layout; -mod layouts_compressed; -mod layouts_exec; -mod noise; - -pub use encryption::*; -pub use layout::*; -pub use layouts_compressed::*; -pub use layouts_exec::*; - -#[cfg(test)] -mod tests;
@@ -4,7 +4,10 @@ layouts::{Backend, DataRef, Module, ScalarZnx, ScratchOwned},
oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl}, }; -use crate::{GGLWECiphertext, GLWECiphertext, GLWEDecryptFamily, GLWEPlaintext, GLWESecretExec, Infos}; +use crate::{ + layouts::{GGLWECiphertext, GLWECiphertext, GLWEPlaintext, Infos, prepared::GLWESecretExec}, + trait_families::GLWEDecryptFamily, +}; impl<D: DataRef> GGLWECiphertext<D> { pub fn assert_noise<B: Backend, DataSk, DataWant>(
@@ -3,20 +3,19 @@ hal::{api::ModuleNew, layouts::Module},
implementation::cpu_spqlios::FFT64, }; -use crate::gglwe::tests::{ - generics_automorphism_key::{ - test_automorphisk_key_encrypt_sk, test_automorphisk_key_encrypt_sk_compressed, test_gglwe_automorphism, - test_gglwe_automorphism_inplace, - }, - generics_gglwe::{ - test_gglwe_encrypt_sk, test_gglwe_encrypt_sk_compressed, test_gglwe_external_product, - test_gglwe_external_product_inplace, test_gglwe_keyswitch, test_gglwe_keyswitch_inplace, +use crate::tests::generics::{ + automorphism::{test_gglwe_automorphism_key_automorphism, test_gglwe_automorphism_key_automorphism_inplace}, + encryption::{ + test_gglwe_automorphisk_key_compressed_encrypt_sk, test_gglwe_automorphisk_key_encrypt_sk, + test_gglwe_switching_key_compressed_encrypt_sk, test_gglwe_switching_key_encrypt_sk, + test_glwe_tensor_key_compressed_encrypt_sk, test_glwe_tensor_key_encrypt_sk, }, - generics_tensor_key::{test_tensor_key_encrypt_sk, test_tensor_key_encrypt_sk_compressed}, + external_product::{test_gglwe_switching_key_external_product, test_gglwe_switching_key_external_product_inplace}, + keyswitch::{test_gglwe_switching_key_keyswitch, test_gglwe_switching_key_keyswitch_inplace}, }; #[test] -fn gglwe_encrypt_sk() { +fn gglwe_switching_key_encrypt_sk() { let log_n: usize = 8; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); let basek: usize = 12;@@ -26,17 +25,17 @@ (1..4).for_each(|rank_in| {
(1..4).for_each(|rank_out| { (1..digits + 1).for_each(|di| { println!( - "test gglwe_encrypt_sk digits: {} ranks: ({} {})", + "test_gglwe_switching_key_encrypt_sk digits: {} ranks: ({} {})", di, rank_in, rank_out ); - test_gglwe_encrypt_sk(&module, basek, k_ksk, di, rank_in, rank_out, 3.2); + test_gglwe_switching_key_encrypt_sk(&module, basek, k_ksk, di, rank_in, rank_out, 3.2); }); }); }); } #[test] -fn gglwe_encrypt_sk_compressed() { +fn gglwe_switching_key_compressed_encrypt_sk() { let log_n: usize = 8; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); let basek: usize = 12;@@ -46,17 +45,17 @@ (1..4).for_each(|rank_in| {
(1..4).for_each(|rank_out| { (1..digits + 1).for_each(|di| { println!( - "test gglwe_encrypt_sk_compressed digits: {} ranks: ({} {})", + "test_gglwe_switching_key_compressed_encrypt_sk digits: {} ranks: ({} {})", di, rank_in, rank_out ); - test_gglwe_encrypt_sk_compressed(&module, basek, k_ksk, di, rank_in, rank_out, 3.2); + test_gglwe_switching_key_compressed_encrypt_sk(&module, basek, k_ksk, di, rank_in, rank_out, 3.2); }); }); }); } #[test] -fn gglwe_keyswitch() { +fn gglwe_switching_key_keyswitch() { let log_n: usize = 8; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); let basek: usize = 12;@@ -68,11 +67,11 @@ (1..4).for_each(|rank_out_s1s2| {
(1..digits + 1).for_each(|di| { let k_ksk: usize = k_in + basek * di; println!( - "test gglwe_keyswitch digits: {} ranks: ({},{},{})", + "test_gglwe_switching_key_keyswitch digits: {} ranks: ({},{},{})", di, rank_in_s0s1, rank_out_s0s1, rank_out_s1s2 ); let k_out: usize = k_ksk; // Better capture noise. - test_gglwe_keyswitch( + test_gglwe_switching_key_keyswitch( &module, basek, k_out,@@ -91,7 +90,7 @@ });
} #[test] -fn gglwe_keyswitch_inplace() { +fn gglwe_switching_key_keyswitch_inplace() { let log_n: usize = 8; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); let basek: usize = 12;@@ -102,10 +101,10 @@ (1..4).for_each(|rank_out_s0s1| {
(1..digits + 1).for_each(|di| { let k_ksk: usize = k_ct + basek * di; println!( - "test gglwe_keyswitch_inplace digits: {} ranks: ({},{})", + "test_gglwe_switching_key_keyswitch_inplace digits: {} ranks: ({},{})", di, rank_in_s0s1, rank_out_s0s1 ); - test_gglwe_keyswitch_inplace( + test_gglwe_switching_key_keyswitch_inplace( &module, basek, k_ct,@@ -121,7 +120,7 @@ });
} #[test] -fn gglwe_external_product() { +fn gglwe_switching_key_external_product() { let log_n: usize = 8; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); let basek: usize = 12;@@ -132,11 +131,11 @@ (1..4).for_each(|rank_out| {
(1..digits + 1).for_each(|di| { let k_ggsw: usize = k_in + basek * di; println!( - "test gglwe_external_product digits: {} ranks: ({} {})", + "test_gglwe_switching_key_external_product digits: {} ranks: ({} {})", di, rank_in, rank_out ); let k_out: usize = k_in; // Better capture noise. - test_gglwe_external_product( + test_gglwe_switching_key_external_product( &module, basek, k_out, k_in, k_ggsw, di, rank_in, rank_out, 3.2, ); });@@ -145,7 +144,7 @@ });
} #[test] -fn gglwe_external_product_inplace() { +fn gglwe_switching_key_external_product_inplace() { let log_n: usize = 5; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); let basek: usize = 12;@@ -156,17 +155,17 @@ (1..4).for_each(|rank_out| {
(1..digits).for_each(|di| { let k_ggsw: usize = k_ct + basek * di; println!( - "test gglwe_external_product_inplace digits: {} ranks: ({} {})", + "test_gglwe_switching_key_external_product_inplace digits: {} ranks: ({} {})", di, rank_in, rank_out ); - test_gglwe_external_product_inplace(&module, basek, k_ct, k_ggsw, di, rank_in, rank_out, 3.2); + test_gglwe_switching_key_external_product_inplace(&module, basek, k_ct, k_ggsw, di, rank_in, rank_out, 3.2); }); }); }); } #[test] -fn automorphism_key_encrypt_sk() { +fn gglwe_automorphisk_key_encrypt_sk() { let log_n: usize = 8; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); let basek: usize = 12;@@ -176,16 +175,16 @@ let sigma: f64 = 3.2;
(1..4).for_each(|rank| { (2..digits + 1).for_each(|di| { println!( - "test automorphism key encrypt sk digits: {} rank: {}", + "test_gglwe_automorphisk_key_encrypt_sk digits: {} rank: {}", di, rank ); - test_automorphisk_key_encrypt_sk(&module, basek, k, di, rank, sigma); + test_gglwe_automorphisk_key_encrypt_sk(&module, basek, k, di, rank, sigma); }); }); } #[test] -fn automorphism_key_encrypt_sk_compressed() { +fn gglwe_automorphisk_key_compressed_encrypt_sk() { let log_n: usize = 8; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); let basek: usize = 12;@@ -195,16 +194,16 @@ let sigma: f64 = 3.2;
(1..4).for_each(|rank| { (2..digits + 1).for_each(|di| { println!( - "test automorphism key encrypt sk compressed digits: {} rank: {}", + "test_gglwe_automorphisk_key_compressed_encrypt_sk digits: {} rank: {}", di, rank ); - test_automorphisk_key_encrypt_sk_compressed(&module, basek, k, di, rank, sigma); + test_gglwe_automorphisk_key_compressed_encrypt_sk(&module, basek, k, di, rank, sigma); }); }); } #[test] -fn gglwe_automorphism() { +fn gglwe_automorphism_key_automorphism() { let log_n: usize = 8; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); let basek: usize = 12;@@ -214,15 +213,18 @@ let digits: usize = k_in.div_ceil(basek);
let sigma: f64 = 3.2; (1..4).for_each(|rank| { (2..digits + 1).for_each(|di| { - println!("test automorphism digits: {} rank: {}", di, rank); + println!( + "test_gglwe_automorphism_key_automorphism: {} rank: {}", + di, rank + ); let k_apply: usize = (digits + di) * basek; - test_gglwe_automorphism(&module, -1, 5, basek, di, k_in, k_out, k_apply, sigma, rank); + test_gglwe_automorphism_key_automorphism(&module, -1, 5, basek, di, k_in, k_out, k_apply, sigma, rank); }); }); } #[test] -fn gglwe_automorphism_inplace() { +fn gglwe_automorphism_key_automorphism_inplace() { let log_n: usize = 8; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); let basek: usize = 12;@@ -231,29 +233,32 @@ let digits: usize = k_in.div_ceil(basek);
let sigma: f64 = 3.2; (1..4).for_each(|rank| { (2..digits + 1).for_each(|di| { - println!("test automorphism_inplace digits: {} rank: {}", di, rank); + println!( + "test_gglwe_automorphism_key_automorphism_inplace: {} rank: {}", + di, rank + ); let k_apply: usize = (digits + di) * basek; - test_gglwe_automorphism_inplace(&module, -1, 5, basek, di, k_in, k_apply, sigma, rank); + test_gglwe_automorphism_key_automorphism_inplace(&module, -1, 5, basek, di, k_in, k_apply, sigma, rank); }); }); } #[test] -fn tensor_key_encrypt_sk() { +fn glwe_tensor_key_encrypt_sk() { let log_n: usize = 8; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); (1..4).for_each(|rank| { - println!("test encrypt_sk rank: {}", rank); - test_tensor_key_encrypt_sk(&module, 16, 54, 3.2, rank); + println!("test_glwe_tensor_key_encrypt_sk rank: {}", rank); + test_glwe_tensor_key_encrypt_sk(&module, 16, 54, 3.2, rank); }); } #[test] -fn tensor_key_encrypt_sk_compressed() { +fn glwe_tensor_key_compressed_encrypt_sk() { let log_n: usize = 8; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); (1..4).for_each(|rank| { - println!("test encrypt_sk_compressed rank: {}", rank); - test_tensor_key_encrypt_sk_compressed(&module, 16, 54, 3.2, rank); + println!("test_glwe_tensor_key_compressed_encrypt_sk rank: {}", rank); + test_glwe_tensor_key_compressed_encrypt_sk(&module, 16, 54, 3.2, rank); }); }
@@ -1,54 +0,0 @@
-use backend::hal::tests::serialization::test_reader_writer_interface; - -use crate::{ - AutomorphismKey, AutomorphismKeyCompressed, GGLWECiphertext, GGLWECiphertextCompressed, GLWESwitchingKey, - GLWESwitchingKeyCompressed, GLWETensorKey, GLWETensorKeyCompressed, -}; - -#[test] -fn test_gglwe_serialization() { - let original: GGLWECiphertext<Vec<u8>> = GGLWECiphertext::alloc(1024, 12, 54, 3, 1, 2, 2); - test_reader_writer_interface(original); -} - -#[test] -fn test_gglwe_compressed_serialization() { - let original: GGLWECiphertextCompressed<Vec<u8>> = GGLWECiphertextCompressed::alloc(1024, 12, 54, 3, 1, 2, 2); - test_reader_writer_interface(original); -} - -#[test] -fn test_glwe_switching_key_serialization() { - let original: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(1024, 12, 54, 3, 1, 2, 2); - test_reader_writer_interface(original); -} - -#[test] -fn test_glwe_switching_key_compressed_serialization() { - let original: GLWESwitchingKeyCompressed<Vec<u8>> = GLWESwitchingKeyCompressed::alloc(1024, 12, 54, 3, 1, 2, 2); - test_reader_writer_interface(original); -} - -#[test] -fn test_automorphism_key_serialization() { - let original: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(1024, 12, 54, 3, 1, 2); - test_reader_writer_interface(original); -} - -#[test] -fn test_automorphism_key_compressed_serialization() { - let original: AutomorphismKeyCompressed<Vec<u8>> = AutomorphismKeyCompressed::alloc(1024, 12, 54, 3, 1, 2); - test_reader_writer_interface(original); -} - -#[test] -fn test_tensor_key_serialization() { - let original: GLWETensorKey<Vec<u8>> = GLWETensorKey::alloc(1024, 12, 54, 3, 1, 2); - test_reader_writer_interface(original); -} - -#[test] -fn test_tensor_key_compressed_serialization() { - let original: GLWETensorKeyCompressed<Vec<u8>> = GLWETensorKeyCompressed::alloc(1024, 12, 54, 3, 1, 2); - test_reader_writer_interface(original); -}
@@ -1,396 +0,0 @@
-use backend::hal::{ - api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxCopy, - VecZnxStd, VecZnxSubScalarInplace, VecZnxSwithcDegree, - }, - layouts::{Backend, Module, ScratchOwned}, - oep::{ - ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, - TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, - }, -}; -use sampling::source::Source; - -use crate::{ - AutomorphismKey, AutomorphismKeyCompressed, AutomorphismKeyEncryptSkFamily, AutomorphismKeyExec, GGLWEExecLayoutFamily, - GLWEDecryptFamily, GLWEKeyswitchFamily, GLWEPlaintext, GLWESecret, GLWESecretExec, Infos, - noise::log2_std_noise_gglwe_product, -}; - -pub(crate) trait AutomorphismTestModuleFamily<B: Backend> = AutomorphismKeyEncryptSkFamily<B> - + GLWEKeyswitchFamily<B> - + VecZnxAutomorphism - + GGLWEExecLayoutFamily<B> - + VecZnxSwithcDegree - + VecZnxAddScalarInplace - + VecZnxAutomorphism - + VecZnxAutomorphismInplace - + GLWEDecryptFamily<B> - + VecZnxSubScalarInplace - + VecZnxStd - + VecZnxCopy; -pub(crate) trait AutomorphismTestScratchFamily<B: Backend> = ScratchOwnedAllocImpl<B> - + ScratchOwnedBorrowImpl<B> - + ScratchAvailableImpl<B> - + TakeScalarZnxImpl<B> - + TakeVecZnxDftImpl<B> - + TakeVecZnxImpl<B> - + TakeSvpPPolImpl<B> - + TakeVecZnxBigImpl<B>; - -pub(crate) fn test_automorphisk_key_encrypt_sk<B: Backend>( - module: &Module<B>, - basek: usize, - k_ksk: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module<B>: AutomorphismTestModuleFamily<B>, - B: AutomorphismTestScratchFamily<B>, -{ - let n: usize = module.n(); - let rows: usize = (k_ksk - digits * basek) / (digits * basek); - - let mut atk: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(AutomorphismKey::encrypt_sk_scratch_space( - module, n, basek, k_ksk, rank, - )); - - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk.fill_ternary_prob(0.5, &mut source_xs); - - let p = -5; - - atk.encrypt_sk( - module, - p, - &sk, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut sk_out: GLWESecret<Vec<u8>> = sk.clone(); - (0..atk.rank()).for_each(|i| { - module.vec_znx_automorphism( - module.galois_element_inv(p), - &mut sk_out.data.as_vec_znx_mut(), - i, - &sk.data.as_vec_znx(), - i, - ); - }); - let sk_out_exec = GLWESecretExec::from(module, &sk_out); - - atk.key - .key - .assert_noise(module, &sk_out_exec, &sk.data, sigma); -} - -pub(crate) fn test_automorphisk_key_encrypt_sk_compressed<B: Backend>( - module: &Module<B>, - basek: usize, - k_ksk: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module<B>: AutomorphismTestModuleFamily<B>, - B: AutomorphismTestScratchFamily<B>, -{ - let n: usize = module.n(); - let rows: usize = (k_ksk - digits * basek) / (digits * basek); - - let mut atk_compressed: AutomorphismKeyCompressed<Vec<u8>> = - AutomorphismKeyCompressed::alloc(n, basek, k_ksk, rows, digits, rank); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(AutomorphismKey::encrypt_sk_scratch_space( - module, n, basek, k_ksk, rank, - )); - - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk.fill_ternary_prob(0.5, &mut source_xs); - - let p = -5; - - let seed_xa: [u8; 32] = [1u8; 32]; - - atk_compressed.encrypt_sk( - module, - p, - &sk, - seed_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut sk_out: GLWESecret<Vec<u8>> = sk.clone(); - (0..atk_compressed.rank()).for_each(|i| { - module.vec_znx_automorphism( - module.galois_element_inv(p), - &mut sk_out.data.as_vec_znx_mut(), - i, - &sk.data.as_vec_znx(), - i, - ); - }); - let sk_out_exec = GLWESecretExec::from(module, &sk_out); - - let mut atk: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); - atk.decompress(module, &atk_compressed); - - atk.key - .key - .assert_noise(module, &sk_out_exec, &sk.data, sigma); -} - -pub(crate) fn test_gglwe_automorphism<B: Backend>( - module: &Module<B>, - p0: i64, - p1: i64, - basek: usize, - digits: usize, - k_in: usize, - k_out: usize, - k_apply: usize, - sigma: f64, - rank: usize, -) where - Module<B>: AutomorphismTestModuleFamily<B>, - B: AutomorphismTestScratchFamily<B>, -{ - let n: usize = module.n(); - let digits_in: usize = 1; - - let rows_in: usize = k_in / (basek * digits); - let rows_apply: usize = k_in.div_ceil(basek * digits); - - let mut auto_key_in: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_in, rows_in, digits_in, rank); - let mut auto_key_out: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_out, rows_in, digits_in, rank); - let mut auto_key_apply: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_apply, rows_apply, digits, rank); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - AutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_apply, rank) - | AutomorphismKey::automorphism_scratch_space(module, n, basek, k_out, k_in, k_apply, digits, rank), - ); - - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk.fill_ternary_prob(0.5, &mut source_xs); - - // gglwe_{s1}(s0) = s0 -> s1 - auto_key_in.encrypt_sk( - module, - p0, - &sk, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - // gglwe_{s2}(s1) -> s1 -> s2 - auto_key_apply.encrypt_sk( - module, - p1, - &sk, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut auto_key_apply_exec: AutomorphismKeyExec<Vec<u8>, B> = - AutomorphismKeyExec::alloc(module, n, basek, k_apply, rows_apply, digits, rank); - - auto_key_apply_exec.prepare(module, &auto_key_apply, scratch.borrow()); - - // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0) - auto_key_out.automorphism(module, &auto_key_in, &auto_key_apply_exec, scratch.borrow()); - - let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_out); - - let mut sk_auto: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk_auto.fill_zero(); // Necessary to avoid panic of unfilled sk - (0..rank).for_each(|i| { - module.vec_znx_automorphism( - module.galois_element_inv(p0 * p1), - &mut sk_auto.data.as_vec_znx_mut(), - i, - &sk.data.as_vec_znx(), - i, - ); - }); - - let sk_auto_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_auto); - - (0..auto_key_out.rank_in()).for_each(|col_i| { - (0..auto_key_out.rows()).for_each(|row_i| { - auto_key_out - .at(row_i, col_i) - .decrypt(module, &mut pt, &sk_auto_dft, scratch.borrow()); - - module.vec_znx_sub_scalar_inplace( - &mut pt.data, - 0, - (digits_in - 1) + row_i * digits_in, - &sk.data, - col_i, - ); - - let noise_have: f64 = module.vec_znx_std(basek, &pt.data, 0).log2(); - let noise_want: f64 = log2_std_noise_gglwe_product( - n as f64, - basek * digits, - 0.5, - 0.5, - 0f64, - sigma * sigma, - 0f64, - rank as f64, - k_out, - k_apply, - ); - - assert!( - noise_have < noise_want + 0.5, - "{} {}", - noise_have, - noise_want - ); - }); - }); -} - -pub(crate) fn test_gglwe_automorphism_inplace<B: Backend>( - module: &Module<B>, - p0: i64, - p1: i64, - basek: usize, - digits: usize, - k_in: usize, - k_apply: usize, - sigma: f64, - rank: usize, -) where - Module<B>: AutomorphismTestModuleFamily<B>, - B: AutomorphismTestScratchFamily<B>, -{ - let n: usize = module.n(); - let digits_in: usize = 1; - - let rows_in: usize = k_in / (basek * digits); - let rows_apply: usize = k_in.div_ceil(basek * digits); - - let mut auto_key: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_in, rows_in, digits_in, rank); - let mut auto_key_apply: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_apply, rows_apply, digits, rank); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - AutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_apply, rank) - | AutomorphismKey::automorphism_inplace_scratch_space(module, n, basek, k_in, k_apply, digits, rank), - ); - - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk.fill_ternary_prob(0.5, &mut source_xs); - - // gglwe_{s1}(s0) = s0 -> s1 - auto_key.encrypt_sk( - module, - p0, - &sk, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - // gglwe_{s2}(s1) -> s1 -> s2 - auto_key_apply.encrypt_sk( - module, - p1, - &sk, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut auto_key_apply_exec: AutomorphismKeyExec<Vec<u8>, B> = - AutomorphismKeyExec::alloc(module, n, basek, k_apply, rows_apply, digits, rank); - - auto_key_apply_exec.prepare(module, &auto_key_apply, scratch.borrow()); - - // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0) - auto_key.automorphism_inplace(module, &auto_key_apply_exec, scratch.borrow()); - - let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_in); - - let mut sk_auto: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk_auto.fill_zero(); // Necessary to avoid panic of unfilled sk - - (0..rank).for_each(|i| { - module.vec_znx_automorphism( - module.galois_element_inv(p0 * p1), - &mut sk_auto.data.as_vec_znx_mut(), - i, - &sk.data.as_vec_znx(), - i, - ); - }); - - let sk_auto_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_auto); - - (0..auto_key.rank_in()).for_each(|col_i| { - (0..auto_key.rows()).for_each(|row_i| { - auto_key - .at(row_i, col_i) - .decrypt(module, &mut pt, &sk_auto_dft, scratch.borrow()); - module.vec_znx_sub_scalar_inplace( - &mut pt.data, - 0, - (digits_in - 1) + row_i * digits_in, - &sk.data, - col_i, - ); - - let noise_have: f64 = module.vec_znx_std(basek, &pt.data, 0).log2(); - let noise_want: f64 = log2_std_noise_gglwe_product( - n as f64, - basek * digits, - 0.5, - 0.5, - 0f64, - sigma * sigma, - 0f64, - rank as f64, - k_in, - k_apply, - ); - - assert!( - noise_have < noise_want + 0.5, - "{} {}", - noise_have, - noise_want - ); - }); - }); -}
@@ -1,578 +0,0 @@
-use backend::hal::{ - api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxRotateInplace, VecZnxStd, - VecZnxSubScalarInplace, VecZnxSwithcDegree, ZnxViewMut, - }, - layouts::{Backend, Module, ScalarZnx, ScalarZnxToMut, ScratchOwned}, - oep::{ - ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, - TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl, - }, -}; -use sampling::source::Source; - -use crate::{ - GGLWEEncryptSkFamily, GGLWEExecLayoutFamily, GGSWCiphertext, GGSWCiphertextExec, GGSWLayoutFamily, GLWEDecryptFamily, - GLWEExternalProductFamily, GLWEKeyswitchFamily, GLWESecret, GLWESecretExec, GLWESwitchingKey, GLWESwitchingKeyCompressed, - GLWESwitchingKeyEncryptSkFamily, GLWESwitchingKeyExec, - noise::{log2_std_noise_gglwe_product, noise_ggsw_product}, -}; - -pub(crate) trait TestModuleFamily<B: Backend> = GGLWEEncryptSkFamily<B> - + GLWEDecryptFamily<B> - + VecZnxSwithcDegree - + VecZnxAddScalarInplace - + VecZnxStd - + VecZnxSubScalarInplace - + VecZnxCopy; - -pub(crate) trait TestScratchFamily<B: Backend> = TakeVecZnxDftImpl<B> - + TakeVecZnxBigImpl<B> - + TakeSvpPPolImpl<B> - + ScratchOwnedAllocImpl<B> - + ScratchOwnedBorrowImpl<B> - + ScratchAvailableImpl<B> - + TakeScalarZnxImpl<B> - + TakeVecZnxImpl<B> - + VecZnxDftAllocBytesImpl<B> - + VecZnxBigAllocBytesImpl<B> - + TakeSvpPPolImpl<B>; - -pub(crate) fn test_gglwe_encrypt_sk<B: Backend>( - module: &Module<B>, - basek: usize, - k_ksk: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - sigma: f64, -) where - Module<B>: TestModuleFamily<B>, - B: TestScratchFamily<B>, -{ - let n: usize = module.n(); - let rows: usize = (k_ksk - digits * basek) / (digits * basek); - - let mut ksk: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_in, rank_out); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWESwitchingKey::encrypt_sk_scratch_space( - module, n, basek, k_ksk, rank_in, rank_out, - )); - - let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in); - sk_in.fill_ternary_prob(0.5, &mut source_xs); - - let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out); - sk_out.fill_ternary_prob(0.5, &mut source_xs); - let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); - - ksk.encrypt_sk( - module, - &sk_in, - &sk_out, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - ksk.key - .assert_noise(module, &sk_out_exec, &sk_in.data, sigma); -} - -pub(crate) fn test_gglwe_encrypt_sk_compressed<B: Backend>( - module: &Module<B>, - basek: usize, - k_ksk: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - sigma: f64, -) where - Module<B>: TestModuleFamily<B>, - B: TestScratchFamily<B>, -{ - let n: usize = module.n(); - let rows: usize = (k_ksk - digits * basek) / (digits * basek); - - let mut ksk_compressed: GLWESwitchingKeyCompressed<Vec<u8>> = - GLWESwitchingKeyCompressed::alloc(n, basek, k_ksk, rows, digits, rank_in, rank_out); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWESwitchingKeyCompressed::encrypt_sk_scratch_space( - module, n, basek, k_ksk, rank_in, rank_out, - )); - - let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in); - sk_in.fill_ternary_prob(0.5, &mut source_xs); - - let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out); - sk_out.fill_ternary_prob(0.5, &mut source_xs); - let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); - - let seed_xa = [1u8; 32]; - - ksk_compressed.encrypt_sk( - module, - &sk_in, - &sk_out, - seed_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut ksk: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_in, rank_out); - ksk.decompress(module, &ksk_compressed); - - ksk.key - .assert_noise(module, &sk_out_exec, &sk_in.data, sigma); -} - -pub(crate) fn test_gglwe_keyswitch<B: Backend>( - module: &Module<B>, - basek: usize, - k_out: usize, - k_in: usize, - k_ksk: usize, - digits: usize, - rank_in_s0s1: usize, - rank_out_s0s1: usize, - rank_out_s1s2: usize, - sigma: f64, -) where - Module<B>: - TestModuleFamily<B> + GGLWEEncryptSkFamily<B> + GLWEDecryptFamily<B> + GLWEKeyswitchFamily<B> + GGLWEExecLayoutFamily<B>, - B: TestScratchFamily<B>, -{ - let n: usize = module.n(); - let rows: usize = k_in.div_ceil(basek * digits); - let digits_in: usize = 1; - - let mut ct_gglwe_s0s1: GLWESwitchingKey<Vec<u8>> = - GLWESwitchingKey::alloc(n, basek, k_in, rows, digits_in, rank_in_s0s1, rank_out_s0s1); - let mut ct_gglwe_s1s2: GLWESwitchingKey<Vec<u8>> = - GLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_out_s0s1, rank_out_s1s2); - let mut ct_gglwe_s0s2: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc( - n, - basek, - k_out, - rows, - digits_in, - rank_in_s0s1, - rank_out_s1s2, - ); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - - let mut scratch_enc: ScratchOwned<B> = ScratchOwned::alloc(GLWESwitchingKey::encrypt_sk_scratch_space( - module, - n, - basek, - k_ksk, - rank_in_s0s1 | rank_out_s0s1, - rank_out_s0s1 | rank_out_s1s2, - )); - let mut scratch_apply: ScratchOwned<B> = ScratchOwned::alloc(GLWESwitchingKey::keyswitch_scratch_space( - module, - n, - basek, - k_out, - k_in, - k_ksk, - digits, - ct_gglwe_s1s2.rank_in(), - ct_gglwe_s1s2.rank_out(), - )); - - let mut sk0: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in_s0s1); - sk0.fill_ternary_prob(0.5, &mut source_xs); - - let mut sk1: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out_s0s1); - sk1.fill_ternary_prob(0.5, &mut source_xs); - - let mut sk2: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out_s1s2); - sk2.fill_ternary_prob(0.5, &mut source_xs); - let sk2_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk2); - - // gglwe_{s1}(s0) = s0 -> s1 - ct_gglwe_s0s1.encrypt_sk( - module, - &sk0, - &sk1, - &mut source_xa, - &mut source_xe, - sigma, - scratch_enc.borrow(), - ); - - // gglwe_{s2}(s1) -> s1 -> s2 - ct_gglwe_s1s2.encrypt_sk( - module, - &sk1, - &sk2, - &mut source_xa, - &mut source_xe, - sigma, - scratch_enc.borrow(), - ); - - let ct_gglwe_s1s2_exec: GLWESwitchingKeyExec<Vec<u8>, B> = - GLWESwitchingKeyExec::from(module, &ct_gglwe_s1s2, scratch_apply.borrow()); - - // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0) - ct_gglwe_s0s2.keyswitch( - module, - &ct_gglwe_s0s1, - &ct_gglwe_s1s2_exec, - scratch_apply.borrow(), - ); - - let max_noise: f64 = log2_std_noise_gglwe_product( - n as f64, - basek * digits, - 0.5, - 0.5, - 0f64, - sigma * sigma, - 0f64, - rank_out_s0s1 as f64, - k_in, - k_ksk, - ); - - ct_gglwe_s0s2 - .key - .assert_noise(module, &sk2_exec, &sk0.data, max_noise + 0.5); -} - -pub(crate) fn test_gglwe_keyswitch_inplace<B: Backend>( - module: &Module<B>, - basek: usize, - k_ct: usize, - k_ksk: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - sigma: f64, -) where - Module<B>: TestModuleFamily<B> - + GLWESwitchingKeyEncryptSkFamily<B> - + GLWEKeyswitchFamily<B> - + GGLWEExecLayoutFamily<B> - + GLWEDecryptFamily<B>, - B: TestScratchFamily<B>, -{ - let n: usize = module.n(); - let rows: usize = k_ct.div_ceil(basek * digits); - let digits_in: usize = 1; - - let mut ct_gglwe_s0s1: GLWESwitchingKey<Vec<u8>> = - GLWESwitchingKey::alloc(n, basek, k_ct, rows, digits_in, rank_in, rank_out); - let mut ct_gglwe_s1s2: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_out, rank_out); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - - let mut scratch_enc: ScratchOwned<B> = ScratchOwned::alloc(GLWESwitchingKey::encrypt_sk_scratch_space( - module, - n, - basek, - k_ksk, - rank_in | rank_out, - rank_out, - )); - let mut scratch_apply: ScratchOwned<B> = ScratchOwned::alloc(GLWESwitchingKey::keyswitch_inplace_scratch_space( - module, n, basek, k_ct, k_ksk, digits, rank_out, - )); - - let var_xs: f64 = 0.5; - - let mut sk0: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in); - sk0.fill_ternary_prob(var_xs, &mut source_xs); - - let mut sk1: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out); - sk1.fill_ternary_prob(var_xs, &mut source_xs); - - let mut sk2: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out); - sk2.fill_ternary_prob(var_xs, &mut source_xs); - let sk2_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk2); - - // gglwe_{s1}(s0) = s0 -> s1 - ct_gglwe_s0s1.encrypt_sk( - module, - &sk0, - &sk1, - &mut source_xa, - &mut source_xe, - sigma, - scratch_enc.borrow(), - ); - - // gglwe_{s2}(s1) -> s1 -> s2 - ct_gglwe_s1s2.encrypt_sk( - module, - &sk1, - &sk2, - &mut source_xa, - &mut source_xe, - sigma, - scratch_enc.borrow(), - ); - - let ct_gglwe_s1s2_exec: GLWESwitchingKeyExec<Vec<u8>, B> = - GLWESwitchingKeyExec::from(module, &ct_gglwe_s1s2, scratch_apply.borrow()); - - // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0) - ct_gglwe_s0s1.keyswitch_inplace(module, &ct_gglwe_s1s2_exec, scratch_apply.borrow()); - - let ct_gglwe_s0s2: GLWESwitchingKey<Vec<u8>> = ct_gglwe_s0s1; - - let max_noise: f64 = log2_std_noise_gglwe_product( - n as f64, - basek * digits, - var_xs, - var_xs, - 0f64, - sigma * sigma, - 0f64, - rank_out as f64, - k_ct, - k_ksk, - ); - - ct_gglwe_s0s2 - .key - .assert_noise(module, &sk2_exec, &sk0.data, max_noise + 0.5); -} - -pub(crate) fn test_gglwe_external_product<B: Backend>( - module: &Module<B>, - basek: usize, - k_out: usize, - k_in: usize, - k_ggsw: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - sigma: f64, -) where - Module<B>: TestModuleFamily<B> - + GLWESwitchingKeyEncryptSkFamily<B> - + GLWEExternalProductFamily<B> - + GGSWLayoutFamily<B> - + GLWEDecryptFamily<B> - + VecZnxRotateInplace, - B: TestScratchFamily<B>, -{ - let n: usize = module.n(); - let rows: usize = k_in.div_ceil(basek * digits); - let digits_in: usize = 1; - - let mut ct_gglwe_in: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(n, basek, k_in, rows, digits_in, rank_in, rank_out); - let mut ct_gglwe_out: GLWESwitchingKey<Vec<u8>> = - GLWESwitchingKey::alloc(n, basek, k_out, rows, digits_in, rank_in, rank_out); - let mut ct_rgsw: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank_out); - - let mut pt_rgsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_in, rank_in, rank_out) - | GLWESwitchingKey::external_product_scratch_space(module, n, basek, k_out, k_in, k_ggsw, digits, rank_out) - | GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ggsw, rank_out), - ); - - let r: usize = 1; - - pt_rgsw.to_mut().raw_mut()[r] = 1; // X^{r} - - let var_xs: f64 = 0.5; - - let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in); - sk_in.fill_ternary_prob(var_xs, &mut source_xs); - - let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out); - sk_out.fill_ternary_prob(var_xs, &mut source_xs); - let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); - - // gglwe_{s1}(s0) = s0 -> s1 - ct_gglwe_in.encrypt_sk( - module, - &sk_in, - &sk_out, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - ct_rgsw.encrypt_sk( - module, - &pt_rgsw, - &sk_out_exec, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut ct_rgsw_exec: GGSWCiphertextExec<Vec<u8>, B> = - GGSWCiphertextExec::alloc(module, n, basek, k_ggsw, rows, digits, rank_out); - - ct_rgsw_exec.prepare(module, &ct_rgsw, scratch.borrow()); - - // gglwe_(m) (x) RGSW_(X^k) = gglwe_(m * X^k) - ct_gglwe_out.external_product(module, &ct_gglwe_in, &ct_rgsw_exec, scratch.borrow()); - - (0..rank_in).for_each(|i| { - module.vec_znx_rotate_inplace(r as i64, &mut sk_in.data.as_vec_znx_mut(), i); // * X^{r} - }); - - let var_gct_err_lhs: f64 = sigma * sigma; - let var_gct_err_rhs: f64 = 0f64; - - let var_msg: f64 = 1f64 / n as f64; // X^{k} - let var_a0_err: f64 = sigma * sigma; - let var_a1_err: f64 = 1f64 / 12f64; - - let max_noise: f64 = noise_ggsw_product( - n as f64, - basek * digits, - var_xs, - var_msg, - var_a0_err, - var_a1_err, - var_gct_err_lhs, - var_gct_err_rhs, - rank_out as f64, - k_in, - k_ggsw, - ); - - ct_gglwe_out - .key - .assert_noise(module, &sk_out_exec, &sk_in.data, max_noise + 0.5); -} - -pub(crate) fn test_gglwe_external_product_inplace<B: Backend>( - module: &Module<B>, - basek: usize, - k_ct: usize, - k_ggsw: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - sigma: f64, -) where - Module<B>: TestModuleFamily<B> - + GLWESwitchingKeyEncryptSkFamily<B> - + GLWEExternalProductFamily<B> - + GGSWLayoutFamily<B> - + GLWEDecryptFamily<B> - + VecZnxRotateInplace, - B: TestScratchFamily<B>, -{ - let n: usize = module.n(); - let rows: usize = k_ct.div_ceil(basek * digits); - - let digits_in: usize = 1; - - let mut ct_gglwe: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(n, basek, k_ct, rows, digits_in, rank_in, rank_out); - let mut ct_rgsw: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank_out); - - let mut pt_rgsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ct, rank_in, rank_out) - | GLWESwitchingKey::external_product_inplace_scratch_space(module, n, basek, k_ct, k_ggsw, digits, rank_out) - | GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ggsw, rank_out), - ); - - let r: usize = 1; - - pt_rgsw.to_mut().raw_mut()[r] = 1; // X^{r} - - let var_xs: f64 = 0.5; - - let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in); - sk_in.fill_ternary_prob(var_xs, &mut source_xs); - - let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out); - sk_out.fill_ternary_prob(var_xs, &mut source_xs); - let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); - - // gglwe_{s1}(s0) = s0 -> s1 - ct_gglwe.encrypt_sk( - module, - &sk_in, - &sk_out, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - ct_rgsw.encrypt_sk( - module, - &pt_rgsw, - &sk_out_exec, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut ct_rgsw_exec: GGSWCiphertextExec<Vec<u8>, B> = - GGSWCiphertextExec::alloc(module, n, basek, k_ggsw, rows, digits, rank_out); - - ct_rgsw_exec.prepare(module, &ct_rgsw, scratch.borrow()); - - // gglwe_(m) (x) RGSW_(X^k) = gglwe_(m * X^k) - ct_gglwe.external_product_inplace(module, &ct_rgsw_exec, scratch.borrow()); - - (0..rank_in).for_each(|i| { - module.vec_znx_rotate_inplace(r as i64, &mut sk_in.data.as_vec_znx_mut(), i); // * X^{r} - }); - - let var_gct_err_lhs: f64 = sigma * sigma; - let var_gct_err_rhs: f64 = 0f64; - - let var_msg: f64 = 1f64 / n as f64; // X^{k} - let var_a0_err: f64 = sigma * sigma; - let var_a1_err: f64 = 1f64 / 12f64; - - let max_noise: f64 = noise_ggsw_product( - n as f64, - basek * digits, - var_xs, - var_msg, - var_a0_err, - var_a1_err, - var_gct_err_lhs, - var_gct_err_rhs, - rank_out as f64, - k_ct, - k_ggsw, - ); - - ct_gglwe - .key - .assert_noise(module, &sk_out_exec, &sk_in.data, max_noise + 0.5); -}
@@ -1,7 +1,7 @@
use backend::hal::{ api::{ ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxBigAlloc, VecZnxCopy, VecZnxDftAlloc, VecZnxStd, - VecZnxSubScalarInplace, VecZnxSwithcDegree, + VecZnxSubScalarInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, }, layouts::{Backend, Module, ScratchOwned, VecZnxDft}, oep::{@@ -12,49 +12,49 @@ };
use sampling::source::Source; use crate::{ - GGLWEEncryptSkFamily, GGLWEExecLayoutFamily, GLWEDecryptFamily, GLWEPlaintext, GLWESecret, GLWESecretExec, GLWETensorKey, - GLWETensorKeyCompressed, GLWETensorKeyEncryptSkFamily, Infos, + layouts::{GGLWETensorKey, GLWEPlaintext, GLWESecret, Infos, compressed::GGLWETensorKeyCompressed, prepared::GLWESecretExec}, + trait_families::{Decompress, GLWEDecryptFamily}, }; -pub(crate) trait TestModuleFamily<B: Backend> = GGLWEEncryptSkFamily<B> - + GLWEDecryptFamily<B> - + VecZnxSwithcDegree - + VecZnxAddScalarInplace - + VecZnxStd - + VecZnxSubScalarInplace; - -pub(crate) trait TestScratchFamily<B: Backend> = TakeVecZnxDftImpl<B> - + TakeVecZnxBigImpl<B> - + TakeSvpPPolImpl<B> - + ScratchOwnedAllocImpl<B> - + ScratchOwnedBorrowImpl<B> - + ScratchAvailableImpl<B> - + TakeScalarZnxImpl<B> - + TakeVecZnxImpl<B> - + VecZnxDftAllocBytesImpl<B> - + VecZnxBigAllocBytesImpl<B> - + TakeSvpPPolImpl<B>; +use crate::trait_families::{GGLWEEncryptSkFamily, GGLWETensorKeyEncryptSkFamily, GLWESecretExecModuleFamily}; -pub(crate) fn test_tensor_key_encrypt_sk<B: Backend>(module: &Module<B>, basek: usize, k: usize, sigma: f64, rank: usize) +pub fn test_glwe_tensor_key_encrypt_sk<B: Backend>(module: &Module<B>, basek: usize, k: usize, sigma: f64, rank: usize) where - Module<B>: TestModuleFamily<B> - + GGLWEExecLayoutFamily<B> - + GLWETensorKeyEncryptSkFamily<B> + Module<B>: GGLWEEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + + GLWEDecryptFamily<B> + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxStd + + VecZnxSubScalarInplace + + VmpPMatAlloc<B> + + VmpPMatPrepare<B> + + GGLWETensorKeyEncryptSkFamily<B> + GLWEDecryptFamily<B> + VecZnxDftAlloc<B> + VecZnxBigAlloc<B>, - B: TestScratchFamily<B>, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B> + + VecZnxDftAllocBytesImpl<B> + + VecZnxBigAllocBytesImpl<B> + + TakeSvpPPolImpl<B>, { let n: usize = module.n(); let rows: usize = k / basek; - let mut tensor_key: GLWETensorKey<Vec<u8>> = GLWETensorKey::alloc(n, basek, k, rows, 1, rank); + let mut tensor_key: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(n, basek, k, rows, 1, rank); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]); let mut source_xa: Source = Source::new([0u8; 32]); - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWETensorKey::encrypt_sk_scratch_space( + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWETensorKey::encrypt_sk_scratch_space( module, n, basek,@@ -116,31 +116,43 @@ })
}) } -pub(crate) fn test_tensor_key_encrypt_sk_compressed<B: Backend>( - module: &Module<B>, - basek: usize, - k: usize, - sigma: f64, - rank: usize, -) where - Module<B>: TestModuleFamily<B> - + GGLWEExecLayoutFamily<B> - + GLWETensorKeyEncryptSkFamily<B> +pub fn test_glwe_tensor_key_compressed_encrypt_sk<B: Backend>(module: &Module<B>, basek: usize, k: usize, sigma: f64, rank: usize) +where + Module<B>: GGLWEEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + + GLWEDecryptFamily<B> + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxStd + + VecZnxSubScalarInplace + + VmpPMatAlloc<B> + + VmpPMatPrepare<B> + + GGLWETensorKeyEncryptSkFamily<B> + GLWEDecryptFamily<B> + VecZnxDftAlloc<B> + VecZnxBigAlloc<B> + VecZnxCopy, - B: TestScratchFamily<B>, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B> + + VecZnxDftAllocBytesImpl<B> + + VecZnxBigAllocBytesImpl<B> + + TakeSvpPPolImpl<B>, { let n: usize = module.n(); let rows: usize = k / basek; - let mut tensor_key_compressed: GLWETensorKeyCompressed<Vec<u8>> = GLWETensorKeyCompressed::alloc(n, basek, k, rows, 1, rank); + let mut tensor_key_compressed: GGLWETensorKeyCompressed<Vec<u8>> = GGLWETensorKeyCompressed::alloc(n, basek, k, rows, 1, rank); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]); - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWETensorKeyCompressed::encrypt_sk_scratch_space( + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWETensorKeyCompressed::encrypt_sk_scratch_space( module, n, basek,@@ -164,7 +176,7 @@ sigma,
scratch.borrow(), ); - let mut tensor_key: GLWETensorKey<Vec<u8>> = GLWETensorKey::alloc(n, basek, k, rows, 1, rank); + let mut tensor_key: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(n, basek, k, rows, 1, rank); tensor_key.decompress(module, &tensor_key_compressed); let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k);
@@ -1,5 +0,0 @@
-mod cpu_spqlios; -mod generic_serialization; -mod generics_automorphism_key; -mod generics_gglwe; -mod generics_tensor_key;
@@ -4,7 +4,11 @@ layouts::{Backend, DataMut, DataRef, Module, Scratch},
}; use crate::{ - AutomorphismKeyExec, GGSWCiphertext, GGSWKeySwitchFamily, GLWECiphertext, GLWEKeyswitchFamily, GLWETensorKeyExec, Infos, + layouts::{ + GGSWCiphertext, GLWECiphertext, Infos, + prepared::{GGLWEAutomorphismKeyExec, GGLWETensorKeyExec}, + }, + trait_families::{GGSWKeySwitchFamily, GLWEKeyswitchFamily}, }; impl GGSWCiphertext<Vec<u8>> {@@ -56,8 +60,8 @@ pub fn automorphism<DataLhs: DataRef, DataAk: DataRef, DataTsk: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GGSWCiphertext<DataLhs>, - auto_key: &AutomorphismKeyExec<DataAk, B>, - tensor_key: &GLWETensorKeyExec<DataTsk, B>, + auto_key: &GGLWEAutomorphismKeyExec<DataAk, B>, + tensor_key: &GGLWETensorKeyExec<DataTsk, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + GGSWKeySwitchFamily<B> + VecZnxAutomorphismInplace + VecZnxNormalizeTmpBytes,@@ -65,8 +69,6 @@ Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnxBig<B>,
{ #[cfg(debug_assertions)] { - use crate::Infos; - assert_eq!(self.n(), auto_key.n()); assert_eq!(lhs.n(), auto_key.n());@@ -115,8 +117,8 @@
pub fn automorphism_inplace<DataKsk: DataRef, DataTsk: DataRef, B: Backend>( &mut self, module: &Module<B>, - auto_key: &AutomorphismKeyExec<DataKsk, B>, - tensor_key: &GLWETensorKeyExec<DataTsk, B>, + auto_key: &GGLWEAutomorphismKeyExec<DataKsk, B>, + tensor_key: &GGLWETensorKeyExec<DataTsk, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + GGSWKeySwitchFamily<B> + VecZnxAutomorphismInplace + VecZnxNormalizeTmpBytes,@@ -132,7 +134,7 @@ fn automorphism_internal<DataLhs: DataRef, DataAk: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GGSWCiphertext<DataLhs>, - auto_key: &AutomorphismKeyExec<DataAk, B>, + auto_key: &GGLWEAutomorphismKeyExec<DataAk, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + GGSWKeySwitchFamily<B> + VecZnxAutomorphismInplace + VecZnxNormalizeTmpBytes,
@@ -1,156 +0,0 @@
-use backend::hal::{ - api::{ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, VecZnxNormalizeInplace, ZnxZero}, - layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch, VecZnx}, -}; -use sampling::source::Source; - -use crate::{ - GGLWEEncryptSkFamily, GGSWCiphertext, GGSWCiphertextCompressed, GLWECiphertext, GLWEEncryptSkFamily, GLWESecretExec, Infos, - TakeGLWEPt, encrypt_sk_internal, -}; - -pub trait GGSWEncryptSkFamily<B: Backend> = GLWEEncryptSkFamily<B>; - -impl GGSWCiphertext<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize - where - Module<B>: GGSWEncryptSkFamily<B>, - { - let size = k.div_ceil(basek); - GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) - + VecZnx::alloc_bytes(n, rank + 1, size) - + VecZnx::alloc_bytes(n, 1, size) - + module.vec_znx_dft_alloc_bytes(n, rank + 1, size) - } -} - -impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> { - pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - pt: &ScalarZnx<DataPt>, - sk: &GLWESecretExec<DataSk, B>, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, - ) where - Module<B>: GGSWEncryptSkFamily<B> + VecZnxAddScalarInplace, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - use backend::hal::api::ZnxInfos; - - assert_eq!(self.rank(), sk.rank()); - assert_eq!(self.n(), sk.n()); - assert_eq!(pt.n(), sk.n()); - } - - let basek: usize = self.basek(); - let k: usize = self.k(); - let rank: usize = self.rank(); - let digits: usize = self.digits(); - - let (mut tmp_pt, scratch1) = scratch.take_glwe_pt(self.n(), basek, k); - - (0..self.rows()).for_each(|row_i| { - tmp_pt.data.zero(); - - // Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt - module.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (digits - 1) + row_i * digits, pt, 0); - module.vec_znx_normalize_inplace(basek, &mut tmp_pt.data, 0, scratch1); - - (0..rank + 1).for_each(|col_j| { - // rlwe encrypt of vec_znx_pt into vec_znx_ct - - self.at_mut(row_i, col_j).encrypt_sk_internal( - module, - Some((&tmp_pt, col_j)), - sk, - source_xa, - source_xe, - sigma, - scratch1, - ); - }); - }); - } -} - -impl GGSWCiphertextCompressed<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize - where - Module<B>: GGSWEncryptSkFamily<B>, - { - GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k, rank) - } -} - -impl<DataSelf: DataMut> GGSWCiphertextCompressed<DataSelf> { - pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - pt: &ScalarZnx<DataPt>, - sk: &GLWESecretExec<DataSk, B>, - seed_xa: [u8; 32], - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, - ) where - Module<B>: GGSWEncryptSkFamily<B> + VecZnxAddScalarInplace, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - use backend::hal::api::ZnxInfos; - - assert_eq!(self.rank(), sk.rank()); - assert_eq!(self.n(), sk.n()); - assert_eq!(pt.n(), sk.n()); - } - - let basek: usize = self.basek(); - let k: usize = self.k(); - let rank: usize = self.rank(); - let cols: usize = rank + 1; - let digits: usize = self.digits(); - - let (mut tmp_pt, scratch_1) = scratch.take_glwe_pt(self.n(), basek, k); - - let mut source = Source::new(seed_xa); - - self.seed = vec![[0u8; 32]; self.rows() * cols]; - - (0..self.rows()).for_each(|row_i| { - tmp_pt.data.zero(); - - // Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt - module.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (digits - 1) + row_i * digits, pt, 0); - module.vec_znx_normalize_inplace(basek, &mut tmp_pt.data, 0, scratch_1); - - (0..rank + 1).for_each(|col_j| { - // rlwe encrypt of vec_znx_pt into vec_znx_ct - - let (seed, mut source_xa_tmp) = source.branch(); - - self.seed[row_i * cols + col_j] = seed; - - encrypt_sk_internal( - module, - self.basek(), - self.k(), - &mut self.at_mut(row_i, col_j).data, - cols, - true, - Some((&tmp_pt, col_j)), - sk, - &mut source_xa_tmp, - source_xe, - sigma, - scratch_1, - ); - }); - }); - } -}
@@ -3,7 +3,10 @@ api::{ScratchAvailable, TakeVecZnxDft, ZnxZero},
layouts::{Backend, DataMut, DataRef, Module, Scratch}, }; -use crate::{GGSWCiphertext, GGSWCiphertextExec, GLWECiphertext, GLWEExternalProductFamily, Infos}; +use crate::{ + layouts::{GGSWCiphertext, GLWECiphertext, Infos, prepared::GGSWCiphertextExec}, + trait_families::GLWEExternalProductFamily, +}; impl GGSWCiphertext<Vec<u8>> { pub fn external_product_scratch_space<B: Backend>(@@ -51,7 +54,7 @@ Scratch<B>: ScratchAvailable + TakeVecZnxDft<B>,
{ #[cfg(debug_assertions)] { - use crate::{GGSWCiphertext, Infos}; + use crate::layouts::Infos; assert_eq!(lhs.n(), self.n()); assert_eq!(rhs.n(), self.n());
@@ -7,11 +7,13 @@ layouts::{Backend, DataMut, DataRef, Module, Scratch, VecZnx, VmpPMat},
}; use crate::{ - GGLWECiphertext, GGSWCiphertext, GLWECiphertext, GLWEKeyswitchFamily, GLWEOps, GLWESwitchingKeyExec, GLWETensorKeyExec, Infos, + layouts::{ + GGLWECiphertext, GGSWCiphertext, GLWECiphertext, Infos, + prepared::{GGLWESwitchingKeyExec, GGLWETensorKeyExec}, + }, + operations::GLWEOperations, + trait_families::{GGSWKeySwitchFamily, GLWEKeyswitchFamily}, }; - -pub trait GGSWKeySwitchFamily<B> = - GLWEKeyswitchFamily<B> + VecZnxBigAllocBytes + VecZnxDftCopy<B> + VecZnxDftAddInplace<B> + VecZnxDftToVecZnxBigTmpA<B>; impl GGSWCiphertext<Vec<u8>> { pub(crate) fn expand_row_scratch_space<B: Backend>(@@ -95,7 +97,7 @@ pub fn from_gglwe<DataA, DataTsk, B: Backend>(
&mut self, module: &Module<B>, a: &GGLWECiphertext<DataA>, - tsk: &GLWETensorKeyExec<DataTsk, B>, + tsk: &GGLWETensorKeyExec<DataTsk, B>, scratch: &mut Scratch<B>, ) where DataA: DataRef,@@ -121,8 +123,8 @@ pub fn keyswitch<DataLhs: DataRef, DataKsk: DataRef, DataTsk: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GGSWCiphertext<DataLhs>, - ksk: &GLWESwitchingKeyExec<DataKsk, B>, - tsk: &GLWETensorKeyExec<DataTsk, B>, + ksk: &GGLWESwitchingKeyExec<DataKsk, B>, + tsk: &GGLWETensorKeyExec<DataTsk, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + GGSWKeySwitchFamily<B> + VecZnxNormalizeTmpBytes,@@ -135,8 +137,8 @@
pub fn keyswitch_inplace<DataKsk: DataRef, DataTsk: DataRef, B: Backend>( &mut self, module: &Module<B>, - ksk: &GLWESwitchingKeyExec<DataKsk, B>, - tsk: &GLWETensorKeyExec<DataTsk, B>, + ksk: &GGLWESwitchingKeyExec<DataKsk, B>, + tsk: &GGLWETensorKeyExec<DataTsk, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + GGSWKeySwitchFamily<B> + VecZnxNormalizeTmpBytes,@@ -151,7 +153,7 @@
pub fn expand_row<DataTsk: DataRef, B: Backend>( &mut self, module: &Module<B>, - tsk: &GLWETensorKeyExec<DataTsk, B>, + tsk: &GGLWETensorKeyExec<DataTsk, B>, scratch: &mut Scratch<B>, ) where Module<B>: GGSWKeySwitchFamily<B> + VecZnxNormalizeTmpBytes,@@ -276,7 +278,7 @@ fn keyswitch_internal<DataLhs: DataRef, DataKsk: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GGSWCiphertext<DataLhs>, - ksk: &GLWESwitchingKeyExec<DataKsk, B>, + ksk: &GGLWESwitchingKeyExec<DataKsk, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + GGSWKeySwitchFamily<B> + VecZnxNormalizeTmpBytes,
@@ -1,12 +1,10 @@
use backend::hal::{ - api::{FillUniform, Reset, VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare}, - layouts::{Backend, Data, DataMut, DataRef, MatZnx, ReaderFrom, WriterTo}, + api::{FillUniform, Reset}, + layouts::{Data, DataMut, DataRef, MatZnx, ReaderFrom, WriterTo}, }; use std::fmt; -use crate::{GLWECiphertext, Infos}; - -pub trait GGSWLayoutFamily<B: Backend> = VmpPMatAlloc<B> + VmpPMatAllocBytes + VmpPMatPrepare<B>; +use crate::layouts::{GLWECiphertext, Infos}; #[derive(PartialEq, Eq, Clone)] pub struct GGSWCiphertext<D: Data> {
@@ -3,7 +3,10 @@ api::{FillUniform, Reset, VecZnxCopy, VecZnxFillUniform},
layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, WriterTo}, }; -use crate::{Decompress, GGSWCiphertext, GLWECiphertextCompressed, Infos}; +use crate::{ + layouts::{GGSWCiphertext, Infos, compressed::GLWECiphertextCompressed}, + trait_families::Decompress, +}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use std::fmt;
@@ -3,7 +3,7 @@ api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare},
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}, }; -use crate::{GGSWCiphertext, GGSWLayoutFamily, Infos}; +use crate::layouts::{GGSWCiphertext, Infos}; #[derive(PartialEq, Eq)] pub struct GGSWCiphertextExec<D: Data, B: Backend> {@@ -16,7 +16,7 @@
impl<B: Backend> GGSWCiphertextExec<Vec<u8>, B> { pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self where - Module<B>: GGSWLayoutFamily<B>, + Module<B>: VmpPMatAlloc<B>, { let size: usize = k.div_ceil(basek); debug_assert!(digits > 0, "invalid ggsw: `digits` == 0");@@ -46,7 +46,7 @@ }
pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize where - Module<B>: GGSWLayoutFamily<B>, + Module<B>: VmpPMatAllocBytes, { let size: usize = k.div_ceil(basek); debug_assert!(@@ -73,7 +73,7 @@ other: &GGSWCiphertext<DataOther>,
scratch: &mut Scratch<B>, ) -> GGSWCiphertextExec<Vec<u8>, B> where - Module<B>: GGSWLayoutFamily<B>, + Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, { let mut ggsw_exec: GGSWCiphertextExec<Vec<u8>, B> = Self::alloc( module,@@ -119,7 +119,7 @@ impl<DataSelf: DataMut, B: Backend> GGSWCiphertextExec<DataSelf, B> {
pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGSWCiphertext<DataOther>, scratch: &mut Scratch<B>) where DataOther: DataRef, - Module<B>: GGSWLayoutFamily<B>, + Module<B>: VmpPMatPrepare<B>, { module.vmp_prepare(&mut self.data, &other.data, scratch); self.k = other.k;
@@ -1,18 +0,0 @@
-mod automorphism; -mod encryption; -mod external_product; -mod keyswitch; -mod layout; -mod layout_compressed; -mod layout_exec; -mod noise; - -pub use encryption::*; -pub use keyswitch::*; -pub use layout::*; -pub use layout_compressed::*; -pub use layout_exec::*; -pub use noise::*; - -#[cfg(test)] -mod test;
@@ -1,21 +1,16 @@
use backend::hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxBigAlloc, VecZnxBigNormalize, - VecZnxBigNormalizeTmpBytes, VecZnxDftAlloc, VecZnxDftToVecZnxBigTmpA, VecZnxNormalizeTmpBytes, VecZnxStd, - VecZnxSubABInplace, ZnxZero, + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxBigAlloc, VecZnxBigNormalize, VecZnxDftAlloc, + VecZnxDftToVecZnxBigTmpA, VecZnxNormalizeTmpBytes, VecZnxStd, VecZnxSubABInplace, ZnxZero, }, layouts::{Backend, DataRef, Module, ScalarZnx, ScratchOwned, VecZnxBig, VecZnxDft}, oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl}, }; -use crate::{GGSWCiphertext, GLWECiphertext, GLWEDecryptFamily, GLWEPlaintext, GLWESecretExec, Infos}; - -pub trait GGSWAssertNoiseFamily<B: Backend> = GLWEDecryptFamily<B> - + VecZnxBigAlloc<B> - + VecZnxDftAlloc<B> - + VecZnxBigNormalizeTmpBytes - + VecZnxBigNormalize<B> - + VecZnxDftToVecZnxBigTmpA<B>; +use crate::{ + layouts::{GGSWCiphertext, GLWECiphertext, GLWEPlaintext, Infos, prepared::GLWESecretExec}, + trait_families::GGSWAssertNoiseFamily, +}; impl<D: DataRef> GGSWCiphertext<D> { pub fn assert_noise<B: Backend, DataSk, DataScalar, F>(
@@ -3,13 +3,15 @@ hal::{api::ModuleNew, layouts::Module},
implementation::cpu_spqlios::FFT64, }; -use crate::ggsw::test::generic_tests::{ - test_automorphism, test_automorphism_inplace, test_encrypt_sk, test_encrypt_sk_compressed, test_external_product, - test_external_product_inplace, test_keyswitch, test_keyswitch_inplace, +use crate::tests::generics::{ + automorphism::{test_ggsw_automorphism, test_ggsw_automorphism_inplace}, + encryption::{test_ggsw_compressed_encrypt_sk, test_ggsw_encrypt_sk}, + external_product::{test_ggsw_external_product, test_ggsw_external_product_inplace}, + keyswitch::{test_ggsw_keyswitch, test_ggsw_keyswitch_inplace}, }; #[test] -fn encrypt_sk() { +fn ggsw_encrypt_sk() { let log_n: usize = 8; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); let basek: usize = 12;@@ -17,14 +19,14 @@ let k_ct: usize = 54;
let digits: usize = k_ct / basek; (1..4).for_each(|rank| { (1..digits + 1).for_each(|di| { - println!("test encrypt_sk digits: {} rank: {}", di, rank); - test_encrypt_sk(&module, basek, k_ct, di, rank, 3.2); + println!("test_ggsw_encrypt_sk digits: {} rank: {}", di, rank); + test_ggsw_encrypt_sk(&module, basek, k_ct, di, rank, 3.2); }); }); } #[test] -fn encrypt_sk_compressed() { +fn ggsw_compressed_encrypt_sk() { let log_n: usize = 8; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); let basek: usize = 12;@@ -32,14 +34,17 @@ let k_ct: usize = 54;
let digits: usize = k_ct / basek; (1..4).for_each(|rank| { (1..digits + 1).for_each(|di| { - println!("test encrypt_sk_compressed digits: {} rank: {}", di, rank); - test_encrypt_sk_compressed(&module, basek, k_ct, di, rank, 3.2); + println!( + "test_ggsw_compressed_encrypt_sk digits: {} rank: {}", + di, rank + ); + test_ggsw_compressed_encrypt_sk(&module, basek, k_ct, di, rank, 3.2); }); }); } #[test] -fn keyswitch() { +fn ggsw_keyswitch() { let log_n: usize = 8; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); let basek: usize = 12;@@ -49,15 +54,15 @@ (1..4).for_each(|rank| {
(1..digits + 1).for_each(|di| { let k_ksk: usize = k_in + basek * di; let k_tsk: usize = k_ksk; - println!("test keyswitch digits: {} rank: {}", di, rank); + println!("test_ggsw_keyswitch digits: {} rank: {}", di, rank); let k_out: usize = k_ksk; // Better capture noise. - test_keyswitch(&module, basek, k_out, k_in, k_ksk, k_tsk, di, rank, 3.2); + test_ggsw_keyswitch(&module, basek, k_out, k_in, k_ksk, k_tsk, di, rank, 3.2); }); }); } #[test] -fn keyswitch_inplace() { +fn ggsw_keyswitch_inplace() { let log_n: usize = 8; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); let basek: usize = 12;@@ -67,14 +72,14 @@ (1..4).for_each(|rank| {
(1..digits + 1).for_each(|di| { let k_ksk: usize = k_ct + basek * di; let k_tsk: usize = k_ksk; - println!("test keyswitch_inplace digits: {} rank: {}", di, rank); - test_keyswitch_inplace(&module, basek, k_ct, k_ksk, k_tsk, di, rank, 3.2); + println!("test_ggsw_keyswitch_inplace digits: {} rank: {}", di, rank); + test_ggsw_keyswitch_inplace(&module, basek, k_ct, k_ksk, k_tsk, di, rank, 3.2); }); }); } #[test] -fn automorphism() { +fn ggsw_automorphism() { let log_n: usize = 8; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); let basek: usize = 12;@@ -84,15 +89,15 @@ (1..4).for_each(|rank| {
(1..digits + 1).for_each(|di| { let k_ksk: usize = k_in + basek * di; let k_tsk: usize = k_ksk; - println!("test automorphism rank: {}", rank); + println!("test_ggsw_automorphism rank: {}", rank); let k_out: usize = k_ksk; // Better capture noise. - test_automorphism(-5, &module, basek, k_out, k_in, k_ksk, k_tsk, di, rank, 3.2); + test_ggsw_automorphism(-5, &module, basek, k_out, k_in, k_ksk, k_tsk, di, rank, 3.2); }); }); } #[test] -fn automorphism_inplace() { +fn ggsw_automorphism_inplace() { let log_n: usize = 8; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); let basek: usize = 12;@@ -102,14 +107,14 @@ (1..4).for_each(|rank| {
(1..digits + 1).for_each(|di| { let k_ksk: usize = k_ct + basek * di; let k_tsk: usize = k_ksk; - println!("test automorphism_inplace rank: {}", rank); - test_automorphism_inplace(-5, &module, basek, k_ct, k_ksk, k_tsk, di, rank, 3.2); + println!("test_ggsw_automorphism_inplace rank: {}", rank); + test_ggsw_automorphism_inplace(-5, &module, basek, k_ct, k_ksk, k_tsk, di, rank, 3.2); }); }); } #[test] -fn external_product() { +fn ggsw_external_product() { let log_n: usize = 8; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); let basek: usize = 12;@@ -120,13 +125,13 @@ (1..digits + 1).for_each(|di| {
let k_ggsw: usize = k_in + basek * di; println!("test external_product digits: {} ranks: {}", di, rank); let k_out: usize = k_in; // Better capture noise. - test_external_product(&module, basek, k_in, k_out, k_ggsw, di, rank, 3.2); + test_ggsw_external_product(&module, basek, k_in, k_out, k_ggsw, di, rank, 3.2); }); }); } #[test] -fn external_product_inplace() { +fn ggsw_external_product_inplace() { let log_n: usize = 8; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); let basek: usize = 12;@@ -135,8 +140,11 @@ let digits: usize = k_ct.div_ceil(basek);
(1..4).for_each(|rank| { (1..digits).for_each(|di| { let k_ggsw: usize = k_ct + basek * di; - println!("test external_product digits: {} rank: {}", di, rank); - test_external_product_inplace(&module, basek, k_ct, k_ggsw, di, rank, 3.2); + println!( + "test_ggsw_external_product_inplace digits: {} rank: {}", + di, rank + ); + test_ggsw_external_product_inplace(&module, basek, k_ct, k_ggsw, di, rank, 3.2); }); }); }
@@ -1,15 +0,0 @@
-use backend::hal::tests::serialization::test_reader_writer_interface; - -use crate::{GGSWCiphertext, GGSWCiphertextCompressed}; - -#[test] -fn ggsw_test_serialization() { - let original: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(1024, 12, 54, 3, 1, 2); - test_reader_writer_interface(original); -} - -#[test] -fn ggsw_test_compressed_serialization() { - let original: GGSWCiphertextCompressed<Vec<u8>> = GGSWCiphertextCompressed::alloc(1024, 12, 54, 3, 1, 2); - test_reader_writer_interface(original); -}
@@ -1,781 +0,0 @@
-use backend::hal::{ - api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxCopy, - VecZnxRotateInplace, VecZnxStd, VecZnxSubABInplace, VecZnxSwithcDegree, ZnxViewMut, - }, - layouts::{Backend, Module, ScalarZnx, ScalarZnxToMut, ScratchOwned}, - oep::{ - ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, - TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl, - }, -}; -use sampling::source::Source; - -use crate::{ - AutomorphismKey, AutomorphismKeyExec, Decompress, GGLWEExecLayoutFamily, GGSWAssertNoiseFamily, GGSWCiphertext, - GGSWCiphertextCompressed, GGSWCiphertextExec, GGSWEncryptSkFamily, GGSWKeySwitchFamily, GLWESecret, GLWESecretExec, - GLWESecretFamily, GLWESwitchingKey, GLWESwitchingKeyEncryptSkFamily, GLWESwitchingKeyExec, GLWETensorKey, - GLWETensorKeyEncryptSkFamily, GLWETensorKeyExec, - noise::{noise_ggsw_keyswitch, noise_ggsw_product}, -}; - -pub(crate) trait TestModuleFamily<B: Backend> = GLWESecretFamily<B> - + GGSWEncryptSkFamily<B> - + GGSWAssertNoiseFamily<B> - + VecZnxAddScalarInplace - + VecZnxSubABInplace - + VecZnxStd - + VecZnxCopy; -pub(crate) trait TestScratchFamily<B: Backend> = TakeVecZnxDftImpl<B> - + TakeVecZnxBigImpl<B> - + TakeSvpPPolImpl<B> - + ScratchOwnedAllocImpl<B> - + ScratchOwnedBorrowImpl<B> - + ScratchAvailableImpl<B> - + TakeScalarZnxImpl<B> - + TakeVecZnxImpl<B> - + VecZnxDftAllocBytesImpl<B> - + VecZnxBigAllocBytesImpl<B> - + TakeSvpPPolImpl<B>; - -pub(crate) fn test_encrypt_sk<B: Backend>(module: &Module<B>, basek: usize, k: usize, digits: usize, rank: usize, sigma: f64) -where - Module<B>: TestModuleFamily<B>, - B: TestScratchFamily<B>, -{ - let n: usize = module.n(); - let rows: usize = (k - digits * basek) / (digits * basek); - - let mut ct: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k, rows, digits, rank); - - let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - - pt_scalar.fill_ternary_hw(0, n, &mut source_xs); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGSWCiphertext::encrypt_sk_scratch_space( - module, n, basek, k, rank, - )); - - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk.fill_ternary_prob(0.5, &mut source_xs); - let mut sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); - sk_exec.prepare(module, &sk); - - ct.encrypt_sk( - module, - &pt_scalar, - &sk_exec, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let noise_f = |_col_i: usize| -(k as f64) + sigma.log2() + 0.5; - - ct.assert_noise(module, &sk_exec, &pt_scalar, &noise_f); -} - -pub(crate) fn test_encrypt_sk_compressed<B: Backend>( - module: &Module<B>, - basek: usize, - k: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module<B>: TestModuleFamily<B>, - B: TestScratchFamily<B>, -{ - let n: usize = module.n(); - let rows: usize = (k - digits * basek) / (digits * basek); - - let mut ct_compressed: GGSWCiphertextCompressed<Vec<u8>> = GGSWCiphertextCompressed::alloc(n, basek, k, rows, digits, rank); - - let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - - pt_scalar.fill_ternary_hw(0, n, &mut source_xs); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGSWCiphertextCompressed::encrypt_sk_scratch_space( - module, n, basek, k, rank, - )); - - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk.fill_ternary_prob(0.5, &mut source_xs); - let mut sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); - sk_exec.prepare(module, &sk); - - let seed_xa: [u8; 32] = [1u8; 32]; - - ct_compressed.encrypt_sk( - module, - &pt_scalar, - &sk_exec, - seed_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let noise_f = |_col_i: usize| -(k as f64) + sigma.log2() + 0.5; - - let mut ct: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k, rows, digits, rank); - ct.decompress(module, &ct_compressed); - - ct.assert_noise(module, &sk_exec, &pt_scalar, &noise_f); -} - -pub(crate) fn test_keyswitch<B: Backend>( - module: &Module<B>, - basek: usize, - k_out: usize, - k_in: usize, - k_ksk: usize, - k_tsk: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module<B>: TestModuleFamily<B> - + GGSWAssertNoiseFamily<B> - + GGSWKeySwitchFamily<B> - + GLWESwitchingKeyEncryptSkFamily<B> - + GLWETensorKeyEncryptSkFamily<B> - + GGLWEExecLayoutFamily<B> - + VecZnxSwithcDegree, - B: TestScratchFamily<B> + VecZnxDftAllocBytesImpl<B> + VecZnxBigAllocBytesImpl<B> + TakeSvpPPolImpl<B>, -{ - let n: usize = module.n(); - let rows: usize = k_in.div_ceil(digits * basek); - - let digits_in: usize = 1; - - let mut ct_in: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_in, rows, digits_in, rank); - let mut ct_out: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_out, rows, digits_in, rank); - let mut tsk: GLWETensorKey<Vec<u8>> = GLWETensorKey::alloc(n, basek, k_ksk, rows, digits, rank); - let mut ksk: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank, rank); - let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_in, rank) - | GLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank, rank) - | GLWETensorKey::encrypt_sk_scratch_space(module, n, basek, k_tsk, rank) - | GGSWCiphertext::keyswitch_scratch_space( - module, n, basek, k_out, k_in, k_ksk, digits, k_tsk, digits, rank, - ), - ); - - let var_xs: f64 = 0.5; - - let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk_in.fill_ternary_prob(var_xs, &mut source_xs); - let sk_in_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_in); - - let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk_out.fill_ternary_prob(var_xs, &mut source_xs); - let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); - - ksk.encrypt_sk( - module, - &sk_in, - &sk_out, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - tsk.encrypt_sk( - module, - &sk_out, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - pt_scalar.fill_ternary_hw(0, n, &mut source_xs); - - ct_in.encrypt_sk( - module, - &pt_scalar, - &sk_in_dft, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut ksk_exec: GLWESwitchingKeyExec<Vec<u8>, B> = - GLWESwitchingKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank, rank); - let mut tsk_exec: GLWETensorKeyExec<Vec<u8>, B> = GLWETensorKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); - - ksk_exec.prepare(module, &ksk, scratch.borrow()); - tsk_exec.prepare(module, &tsk, scratch.borrow()); - - ct_out.keyswitch(module, &ct_in, &ksk_exec, &tsk_exec, scratch.borrow()); - - let max_noise = |col_j: usize| -> f64 { - noise_ggsw_keyswitch( - n as f64, - basek * digits, - col_j, - var_xs, - 0f64, - sigma * sigma, - 0f64, - rank as f64, - k_in, - k_ksk, - k_tsk, - ) + 0.5 - }; - - ct_out.assert_noise(module, &sk_out_exec, &pt_scalar, &max_noise); -} - -pub(crate) fn test_keyswitch_inplace<B: Backend>( - module: &Module<B>, - basek: usize, - k_ct: usize, - k_ksk: usize, - k_tsk: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module<B>: TestModuleFamily<B> - + GGSWAssertNoiseFamily<B> - + GGSWKeySwitchFamily<B> - + GLWESwitchingKeyEncryptSkFamily<B> - + GLWETensorKeyEncryptSkFamily<B> - + GGLWEExecLayoutFamily<B> - + VecZnxSwithcDegree, - B: TestScratchFamily<B>, -{ - let n: usize = module.n(); - let rows: usize = k_ct.div_ceil(digits * basek); - - let digits_in: usize = 1; - - let mut ct: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ct, rows, digits_in, rank); - let mut tsk: GLWETensorKey<Vec<u8>> = GLWETensorKey::alloc(n, basek, k_tsk, rows, digits, rank); - let mut ksk: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank, rank); - let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ct, rank) - | GLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank, rank) - | GLWETensorKey::encrypt_sk_scratch_space(module, n, basek, k_tsk, rank) - | GGSWCiphertext::keyswitch_inplace_scratch_space(module, n, basek, k_ct, k_ksk, digits, k_tsk, digits, rank), - ); - - let var_xs: f64 = 0.5; - - let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk_in.fill_ternary_prob(var_xs, &mut source_xs); - let sk_in_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_in); - - let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk_out.fill_ternary_prob(var_xs, &mut source_xs); - let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); - - ksk.encrypt_sk( - module, - &sk_in, - &sk_out, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - tsk.encrypt_sk( - module, - &sk_out, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - pt_scalar.fill_ternary_hw(0, n, &mut source_xs); - - ct.encrypt_sk( - module, - &pt_scalar, - &sk_in_dft, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut ksk_exec: GLWESwitchingKeyExec<Vec<u8>, B> = - GLWESwitchingKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank, rank); - let mut tsk_exec: GLWETensorKeyExec<Vec<u8>, B> = GLWETensorKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); - - ksk_exec.prepare(module, &ksk, scratch.borrow()); - tsk_exec.prepare(module, &tsk, scratch.borrow()); - - ct.keyswitch_inplace(module, &ksk_exec, &tsk_exec, scratch.borrow()); - - let max_noise = |col_j: usize| -> f64 { - noise_ggsw_keyswitch( - n as f64, - basek * digits, - col_j, - var_xs, - 0f64, - sigma * sigma, - 0f64, - rank as f64, - k_ct, - k_ksk, - k_tsk, - ) + 0.5 - }; - - ct.assert_noise(module, &sk_out_exec, &pt_scalar, &max_noise); -} - -pub(crate) fn test_automorphism<B: Backend>( - p: i64, - module: &Module<B>, - basek: usize, - k_out: usize, - k_in: usize, - k_ksk: usize, - k_tsk: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module<B>: TestModuleFamily<B> - + GGSWAssertNoiseFamily<B> - + GGSWKeySwitchFamily<B> - + GLWESwitchingKeyEncryptSkFamily<B> - + GLWETensorKeyEncryptSkFamily<B> - + GGLWEExecLayoutFamily<B> - + VecZnxSwithcDegree - + VecZnxAutomorphismInplace - + VecZnxAutomorphismInplace - + VecZnxAutomorphism, - B: TestScratchFamily<B>, -{ - let n: usize = module.n(); - let rows: usize = k_in.div_ceil(basek * digits); - let rows_in: usize = k_in.div_euclid(basek * digits); - - let digits_in: usize = 1; - - let mut ct_in: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_in, rows_in, digits_in, rank); - let mut ct_out: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_out, rows_in, digits_in, rank); - let mut tensor_key: GLWETensorKey<Vec<u8>> = GLWETensorKey::alloc(n, basek, k_tsk, rows, digits, rank); - let mut auto_key: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); - let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_in, rank) - | AutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank) - | GLWETensorKey::encrypt_sk_scratch_space(module, n, basek, k_tsk, rank) - | GGSWCiphertext::automorphism_scratch_space( - module, n, basek, k_out, k_in, k_ksk, digits, k_tsk, digits, rank, - ), - ); - - let var_xs: f64 = 0.5; - - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk.fill_ternary_prob(var_xs, &mut source_xs); - let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); - - auto_key.encrypt_sk( - module, - p, - &sk, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - tensor_key.encrypt_sk( - module, - &sk, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - pt_scalar.fill_ternary_hw(0, n, &mut source_xs); - - ct_in.encrypt_sk( - module, - &pt_scalar, - &sk_exec, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut auto_key_exec: AutomorphismKeyExec<Vec<u8>, B> = - AutomorphismKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); - auto_key_exec.prepare(module, &auto_key, scratch.borrow()); - - let mut tsk_exec: GLWETensorKeyExec<Vec<u8>, B> = GLWETensorKeyExec::alloc(module, n, basek, k_tsk, rows, digits, rank); - tsk_exec.prepare(module, &tensor_key, scratch.borrow()); - - ct_out.automorphism(module, &ct_in, &auto_key_exec, &tsk_exec, scratch.borrow()); - - module.vec_znx_automorphism_inplace(p, &mut pt_scalar.as_vec_znx_mut(), 0); - - let max_noise = |col_j: usize| -> f64 { - noise_ggsw_keyswitch( - n as f64, - basek * digits, - col_j, - var_xs, - 0f64, - sigma * sigma, - 0f64, - rank as f64, - k_in, - k_ksk, - k_tsk, - ) + 0.5 - }; - - ct_out.assert_noise(module, &sk_exec, &pt_scalar, &max_noise); -} - -pub(crate) fn test_automorphism_inplace<B: Backend>( - p: i64, - module: &Module<B>, - basek: usize, - k_ct: usize, - k_ksk: usize, - k_tsk: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module<B>: TestModuleFamily<B> - + GGSWAssertNoiseFamily<B> - + GGSWKeySwitchFamily<B> - + GLWESwitchingKeyEncryptSkFamily<B> - + GLWETensorKeyEncryptSkFamily<B> - + GGLWEExecLayoutFamily<B> - + VecZnxSwithcDegree - + VecZnxAutomorphismInplace - + VecZnxAutomorphism - + VecZnxAutomorphismInplace, - B: TestScratchFamily<B>, -{ - let n: usize = module.n(); - let rows: usize = k_ct.div_ceil(digits * basek); - let rows_in: usize = k_ct.div_euclid(basek * digits); - let digits_in: usize = 1; - - let mut ct: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ct, rows_in, digits_in, rank); - let mut tensor_key: GLWETensorKey<Vec<u8>> = GLWETensorKey::alloc(n, basek, k_tsk, rows, digits, rank); - let mut auto_key: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); - let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ct, rank) - | AutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank) - | GLWETensorKey::encrypt_sk_scratch_space(module, n, basek, k_tsk, rank) - | GGSWCiphertext::automorphism_inplace_scratch_space(module, n, basek, k_ct, k_ksk, digits, k_tsk, digits, rank), - ); - - let var_xs: f64 = 0.5; - - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk.fill_ternary_prob(var_xs, &mut source_xs); - let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); - - auto_key.encrypt_sk( - module, - p, - &sk, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - tensor_key.encrypt_sk( - module, - &sk, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - pt_scalar.fill_ternary_hw(0, n, &mut source_xs); - - ct.encrypt_sk( - module, - &pt_scalar, - &sk_exec, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut auto_key_exec: AutomorphismKeyExec<Vec<u8>, B> = - AutomorphismKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); - auto_key_exec.prepare(module, &auto_key, scratch.borrow()); - - let mut tsk_exec: GLWETensorKeyExec<Vec<u8>, B> = GLWETensorKeyExec::alloc(module, n, basek, k_tsk, rows, digits, rank); - tsk_exec.prepare(module, &tensor_key, scratch.borrow()); - - ct.automorphism_inplace(module, &auto_key_exec, &tsk_exec, scratch.borrow()); - - module.vec_znx_automorphism_inplace(p, &mut pt_scalar.as_vec_znx_mut(), 0); - - let max_noise = |col_j: usize| -> f64 { - noise_ggsw_keyswitch( - n as f64, - basek * digits, - col_j, - var_xs, - 0f64, - sigma * sigma, - 0f64, - rank as f64, - k_ct, - k_ksk, - k_tsk, - ) + 0.5 - }; - - ct.assert_noise(module, &sk_exec, &pt_scalar, &max_noise); -} - -pub(crate) fn test_external_product<B: Backend>( - module: &Module<B>, - basek: usize, - k_in: usize, - k_out: usize, - k_ggsw: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module<B>: TestModuleFamily<B> - + GGSWAssertNoiseFamily<B> - + GGSWKeySwitchFamily<B> - + GLWESwitchingKeyEncryptSkFamily<B> - + GLWETensorKeyEncryptSkFamily<B> - + GGLWEExecLayoutFamily<B> - + VecZnxRotateInplace, - B: TestScratchFamily<B>, -{ - let n: usize = module.n(); - let rows: usize = k_in.div_ceil(basek * digits); - let rows_in: usize = k_in.div_euclid(basek * digits); - let digits_in: usize = 1; - - let mut ct_ggsw_lhs_in: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_in, rows_in, digits_in, rank); - let mut ct_ggsw_lhs_out: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_out, rows_in, digits_in, rank); - let mut ct_ggsw_rhs: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank); - let mut pt_ggsw_lhs: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); - let mut pt_ggsw_rhs: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - - pt_ggsw_lhs.fill_ternary_prob(0, 0.5, &mut source_xs); - - let k: usize = 1; - - pt_ggsw_rhs.to_mut().raw_mut()[k] = 1; //X^{k} - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ggsw, rank) - | GGSWCiphertext::external_product_scratch_space(module, n, basek, k_out, k_in, k_ggsw, digits, rank), - ); - - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk.fill_ternary_prob(0.5, &mut source_xs); - let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); - - ct_ggsw_rhs.encrypt_sk( - module, - &pt_ggsw_rhs, - &sk_exec, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - ct_ggsw_lhs_in.encrypt_sk( - module, - &pt_ggsw_lhs, - &sk_exec, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut ct_rhs_exec: GGSWCiphertextExec<Vec<u8>, B> = GGSWCiphertextExec::alloc(module, n, basek, k_ggsw, rows, digits, rank); - ct_rhs_exec.prepare(module, &ct_ggsw_rhs, scratch.borrow()); - - ct_ggsw_lhs_out.external_product(module, &ct_ggsw_lhs_in, &ct_rhs_exec, scratch.borrow()); - - module.vec_znx_rotate_inplace(k as i64, &mut pt_ggsw_lhs.as_vec_znx_mut(), 0); - - let var_gct_err_lhs: f64 = sigma * sigma; - let var_gct_err_rhs: f64 = 0f64; - - let var_msg: f64 = 1f64 / n as f64; // X^{k} - let var_a0_err: f64 = sigma * sigma; - let var_a1_err: f64 = 1f64 / 12f64; - - let max_noise = |_col_j: usize| -> f64 { - noise_ggsw_product( - n as f64, - basek * digits, - 0.5, - var_msg, - var_a0_err, - var_a1_err, - var_gct_err_lhs, - var_gct_err_rhs, - rank as f64, - k_in, - k_ggsw, - ) + 0.5 - }; - - ct_ggsw_lhs_out.assert_noise(module, &sk_exec, &pt_ggsw_lhs, &max_noise); -} - -pub(crate) fn test_external_product_inplace<B: Backend>( - module: &Module<B>, - basek: usize, - k_ct: usize, - k_ggsw: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module<B>: TestModuleFamily<B> - + GGSWAssertNoiseFamily<B> - + GGSWKeySwitchFamily<B> - + GLWESwitchingKeyEncryptSkFamily<B> - + GLWETensorKeyEncryptSkFamily<B> - + GGLWEExecLayoutFamily<B> - + VecZnxRotateInplace, - B: TestScratchFamily<B>, -{ - let n: usize = module.n(); - let rows: usize = k_ct.div_ceil(digits * basek); - let rows_in: usize = k_ct.div_euclid(basek * digits); - let digits_in: usize = 1; - - let mut ct_ggsw_lhs: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ct, rows_in, digits_in, rank); - let mut ct_ggsw_rhs: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank); - - let mut pt_ggsw_lhs: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); - let mut pt_ggsw_rhs: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - - pt_ggsw_lhs.fill_ternary_prob(0, 0.5, &mut source_xs); - - let k: usize = 1; - - pt_ggsw_rhs.to_mut().raw_mut()[k] = 1; //X^{k} - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ggsw, rank) - | GGSWCiphertext::external_product_inplace_scratch_space(module, n, basek, k_ct, k_ggsw, digits, rank), - ); - - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk.fill_ternary_prob(0.5, &mut source_xs); - let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); - - ct_ggsw_rhs.encrypt_sk( - module, - &pt_ggsw_rhs, - &sk_exec, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - ct_ggsw_lhs.encrypt_sk( - module, - &pt_ggsw_lhs, - &sk_exec, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut ct_rhs_exec: GGSWCiphertextExec<Vec<u8>, B> = GGSWCiphertextExec::alloc(module, n, basek, k_ggsw, rows, digits, rank); - ct_rhs_exec.prepare(module, &ct_ggsw_rhs, scratch.borrow()); - - ct_ggsw_lhs.external_product_inplace(module, &ct_rhs_exec, scratch.borrow()); - - module.vec_znx_rotate_inplace(k as i64, &mut pt_ggsw_lhs.as_vec_znx_mut(), 0); - - let var_gct_err_lhs: f64 = sigma * sigma; - let var_gct_err_rhs: f64 = 0f64; - - let var_msg: f64 = 1f64 / n as f64; // X^{k} - let var_a0_err: f64 = sigma * sigma; - let var_a1_err: f64 = 1f64 / 12f64; - - let max_noise = |_col_j: usize| -> f64 { - noise_ggsw_product( - n as f64, - basek * digits, - 0.5, - var_msg, - var_a0_err, - var_a1_err, - var_gct_err_lhs, - var_gct_err_rhs, - rank as f64, - k_ct, - k_ggsw, - ) + 0.5 - }; - - ct_ggsw_lhs.assert_noise(module, &sk_exec, &pt_ggsw_lhs, &max_noise); -}
@@ -1,3 +0,0 @@
-mod cpu_spqlios; -mod generic_serialization; -mod generic_tests;
@@ -6,7 +6,10 @@ },
layouts::{Backend, DataMut, DataRef, Module, Scratch, VecZnxBig}, }; -use crate::{AutomorphismKeyExec, GLWECiphertext, GLWEKeyswitchFamily, Infos, glwe::keyswitch::keyswitch}; +use crate::{ + layouts::{GLWECiphertext, Infos, prepared::GGLWEAutomorphismKeyExec}, + trait_families::GLWEKeyswitchFamily, +}; impl GLWECiphertext<Vec<u8>> { pub fn automorphism_scratch_space<B: Backend>(@@ -46,7 +49,7 @@ pub fn automorphism<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GLWECiphertext<DataLhs>, - rhs: &AutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxAutomorphismInplace,@@ -61,7 +64,7 @@
pub fn automorphism_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &AutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxAutomorphismInplace,@@ -77,7 +80,7 @@ pub fn automorphism_add<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GLWECiphertext<DataLhs>, - rhs: &AutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxBigAutomorphismInplace<B>,@@ -88,7 +91,7 @@ {
self.assert_keyswitch(module, lhs, &rhs.key, scratch); } let (res_dft, scratch1) = scratch.take_vec_znx_dft(self.n(), self.cols(), rhs.size()); // TODO: optimise size - let mut res_big: VecZnxBig<_, B> = keyswitch(module, res_dft, lhs, &rhs.key, scratch1); + let mut res_big: VecZnxBig<_, B> = lhs.keyswitch_internal(module, res_dft, &rhs.key, scratch1); (0..self.cols()).for_each(|i| { module.vec_znx_big_automorphism_inplace(rhs.p(), &mut res_big, i); module.vec_znx_big_add_small_inplace(&mut res_big, i, &lhs.data, i);@@ -99,7 +102,7 @@
pub fn automorphism_add_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &AutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxBigAutomorphismInplace<B>,@@ -115,7 +118,7 @@ pub fn automorphism_sub_ab<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GLWECiphertext<DataLhs>, - rhs: &AutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxBigAutomorphismInplace<B> + VecZnxBigSubSmallAInplace<B>,@@ -126,7 +129,7 @@ {
self.assert_keyswitch(module, lhs, &rhs.key, scratch); } let (res_dft, scratch1) = scratch.take_vec_znx_dft(self.n(), self.cols(), rhs.size()); // TODO: optimise size - let mut res_big: VecZnxBig<_, B> = keyswitch(module, res_dft, lhs, &rhs.key, scratch1); + let mut res_big: VecZnxBig<_, B> = lhs.keyswitch_internal(module, res_dft, &rhs.key, scratch1); (0..self.cols()).for_each(|i| { module.vec_znx_big_automorphism_inplace(rhs.p(), &mut res_big, i); module.vec_znx_big_sub_small_a_inplace(&mut res_big, i, &lhs.data, i);@@ -137,7 +140,7 @@
pub fn automorphism_sub_ab_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &AutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxBigAutomorphismInplace<B> + VecZnxBigSubSmallAInplace<B>,@@ -153,7 +156,7 @@ pub fn automorphism_sub_ba<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GLWECiphertext<DataLhs>, - rhs: &AutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxBigAutomorphismInplace<B> + VecZnxBigSubSmallBInplace<B>,@@ -164,7 +167,7 @@ {
self.assert_keyswitch(module, lhs, &rhs.key, scratch); } let (res_dft, scratch1) = scratch.take_vec_znx_dft(self.n(), self.cols(), rhs.size()); // TODO: optimise size - let mut res_big: VecZnxBig<_, B> = keyswitch(module, res_dft, lhs, &rhs.key, scratch1); + let mut res_big: VecZnxBig<_, B> = lhs.keyswitch_internal(module, res_dft, &rhs.key, scratch1); (0..self.cols()).for_each(|i| { module.vec_znx_big_automorphism_inplace(rhs.p(), &mut res_big, i); module.vec_znx_big_sub_small_b_inplace(&mut res_big, i, &lhs.data, i);@@ -175,7 +178,7 @@
pub fn automorphism_sub_ba_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &AutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxBigAutomorphismInplace<B> + VecZnxBigSubSmallBInplace<B>,
@@ -1,23 +1,15 @@
use backend::hal::{ api::{ DataViewMut, SvpApplyInplace, TakeVecZnxBig, TakeVecZnxDft, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, - VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigConsume, - VecZnxNormalizeTmpBytes, + VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigConsume, VecZnxNormalizeTmpBytes, }, layouts::{Backend, DataMut, DataRef, Module, Scratch}, }; -use crate::{GLWECiphertext, GLWEPlaintext, GLWESecretExec, Infos}; - -pub trait GLWEDecryptFamily<B: Backend> = VecZnxDftAllocBytes - + VecZnxBigAllocBytes - + VecZnxDftFromVecZnx<B> - + SvpApplyInplace<B> - + VecZnxDftToVecZnxBigConsume<B> - + VecZnxBigAddInplace<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxBigNormalize<B> - + VecZnxNormalizeTmpBytes; +use crate::{ + layouts::{GLWECiphertext, GLWEPlaintext, Infos, prepared::GLWESecretExec}, + trait_families::GLWEDecryptFamily, +}; impl GLWECiphertext<Vec<u8>> { pub fn decrypt_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize) -> usize
@@ -1,44 +1,23 @@
use backend::hal::{ api::{ - ScratchAvailable, SvpApply, SvpApplyInplace, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx, TakeSvpPPol, TakeVecZnx, - TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal, VecZnxBigAddNormal, VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, - VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigConsume, VecZnxFillUniform, - VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubABInplace, ZnxInfos, ZnxZero, + ScratchAvailable, SvpApply, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx, TakeSvpPPol, TakeVecZnx, TakeVecZnxDft, + VecZnxBigAddNormal, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftToVecZnxBigConsume, + ZnxInfos, ZnxZero, }, layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch, VecZnx, VecZnxBig}, }; use sampling::source::Source; use crate::{ - GLWECiphertext, GLWECiphertextCompressed, GLWEPlaintext, GLWEPublicKeyExec, GLWESecretExec, Infos, SIX_SIGMA, + SIX_SIGMA, dist::Distribution, + layouts::{ + GLWECiphertext, GLWEPlaintext, Infos, + prepared::{GLWEPublicKeyExec, GLWESecretExec}, + }, + trait_families::{GLWEEncryptPkFamily, GLWEEncryptSkFamily}, }; -pub trait GLWEEncryptSkFamily<B: Backend> = VecZnxDftAllocBytes - + VecZnxBigNormalize<B> - + VecZnxDftFromVecZnx<B> - + SvpApplyInplace<B> - + VecZnxDftToVecZnxBigConsume<B> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubABInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<B> - + VecZnxAddNormal - + VecZnxNormalize<B> - + VecZnxSub; - -pub trait GLWEEncryptPkFamily<B: Backend> = VecZnxDftAllocBytes - + VecZnxBigAllocBytes - + SvpPPolAllocBytes - + SvpPrepare<B> - + SvpApply<B> - + VecZnxDftToVecZnxBigConsume<B> - + VecZnxBigAddNormal<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxBigNormalize<B> - + VecZnxNormalizeTmpBytes; - impl GLWECiphertext<Vec<u8>> { pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize) -> usize where@@ -144,7 +123,7 @@ Module<B>: GLWEEncryptSkFamily<B>,
Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, { let cols: usize = self.rank() + 1; - encrypt_sk_internal( + glwe_encrypt_sk_internal( module, self.basek(), self.k(),@@ -296,73 +275,7 @@ });
} } -impl GLWECiphertextCompressed<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize) -> usize - where - Module<B>: GLWEEncryptSkFamily<B>, - { - GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) - } -} -impl<D: DataMut> GLWECiphertextCompressed<D> { - pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - pt: &GLWEPlaintext<DataPt>, - sk: &GLWESecretExec<DataSk, B>, - seed_xa: [u8; 32], - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, - ) where - Module<B>: GLWEEncryptSkFamily<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, - { - self.encrypt_sk_internal( - module, - Some((pt, 0)), - sk, - seed_xa, - source_xe, - sigma, - scratch, - ); - } - - pub(crate) fn encrypt_sk_internal<DataPt: DataRef, DataSk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - pt: Option<(&GLWEPlaintext<DataPt>, usize)>, - sk: &GLWESecretExec<DataSk, B>, - seed_xa: [u8; 32], - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, - ) where - Module<B>: GLWEEncryptSkFamily<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, - { - let mut source_xa = Source::new(seed_xa); - let cols: usize = self.rank() + 1; - encrypt_sk_internal( - module, - self.basek(), - self.k(), - &mut self.data, - cols, - true, - pt, - sk, - &mut source_xa, - source_xe, - sigma, - scratch, - ); - self.seed = seed_xa; - } -} - -pub(crate) fn encrypt_sk_internal<DataCt: DataMut, DataPt: DataRef, DataSk: DataRef, B: Backend>( +pub(crate) fn glwe_encrypt_sk_internal<DataCt: DataMut, DataPt: DataRef, DataSk: DataRef, B: Backend>( module: &Module<B>, basek: usize, k: usize,@@ -382,6 +295,8 @@ {
#[cfg(debug_assertions)] { if compressed { + use backend::hal::api::ZnxInfos; + assert_eq!( ct.cols(), 1,
@@ -6,16 +6,10 @@ },
layouts::{Backend, DataMut, DataRef, Module, Scratch, VecZnxBig}, }; -use crate::{GGSWCiphertextExec, GLWECiphertext, Infos}; - -pub trait GLWEExternalProductFamily<B: Backend> = VecZnxDftAllocBytes - + VmpApplyTmpBytes - + VmpApply<B> - + VmpApplyAdd<B> - + VecZnxDftFromVecZnx<B> - + VecZnxDftToVecZnxBigConsume<B> - + VecZnxBigNormalize<B> - + VecZnxNormalizeTmpBytes; +use crate::{ + layouts::{GLWECiphertext, Infos, prepared::GGSWCiphertextExec}, + trait_families::GLWEExternalProductFamily, +}; impl GLWECiphertext<Vec<u8>> { pub fn external_product_scratch_space<B: Backend>(
@@ -6,18 +6,10 @@ },
layouts::{Backend, DataMut, DataRef, Module, Scratch, VecZnx, VecZnxBig, VecZnxDft, VmpPMat}, }; -use crate::{GLWECiphertext, GLWESwitchingKeyExec, Infos}; - -pub trait GLWEKeyswitchFamily<B: Backend> = VecZnxDftAllocBytes - + VmpApplyTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyTmpBytes - + VmpApply<B> - + VmpApplyAdd<B> - + VecZnxDftFromVecZnx<B> - + VecZnxDftToVecZnxBigConsume<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxBigNormalize<B>; +use crate::{ + layouts::{GLWECiphertext, Infos, prepared::GGLWESwitchingKeyExec}, + trait_families::GLWEKeyswitchFamily, +}; impl GLWECiphertext<Vec<u8>> { pub fn keyswitch_scratch_space<B: Backend>(@@ -52,25 +44,6 @@ let normalize: usize = module.vec_znx_big_normalize_tmp_bytes(n);
return res_dft + ((ai_dft + vmp) | normalize); } - pub fn keyswitch_from_fourier_scratch_space<B: Backend>( - module: &Module<B>, - n: usize, - basek: usize, - k_out: usize, - k_in: usize, - k_ksk: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - ) -> usize - where - Module<B>: GLWEKeyswitchFamily<B>, - { - Self::keyswitch_scratch_space( - module, n, basek, k_out, k_in, k_ksk, digits, rank_in, rank_out, - ) - } - pub fn keyswitch_inplace_scratch_space<B: Backend>( module: &Module<B>, n: usize,@@ -92,7 +65,7 @@ pub(crate) fn assert_keyswitch<B: Backend, DataLhs, DataRhs>(
&self, module: &Module<B>, lhs: &GLWECiphertext<DataLhs>, - rhs: &GLWESwitchingKeyExec<DataRhs, B>, + rhs: &GGLWESwitchingKeyExec<DataRhs, B>, scratch: &Scratch<B>, ) where DataLhs: DataRef,@@ -163,7 +136,7 @@ pub fn keyswitch<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GLWECiphertext<DataLhs>, - rhs: &GLWESwitchingKeyExec<DataRhs, B>, + rhs: &GGLWESwitchingKeyExec<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B>,@@ -174,7 +147,7 @@ {
self.assert_keyswitch(module, lhs, rhs, scratch); } let (res_dft, scratch1) = scratch.take_vec_znx_dft(self.n(), self.cols(), rhs.size()); // Todo optimise - let res_big: VecZnxBig<_, B> = keyswitch(module, res_dft, lhs, rhs, scratch1); + let res_big: VecZnxBig<_, B> = lhs.keyswitch_internal(module, res_dft, rhs, scratch1); (0..self.cols()).for_each(|i| { module.vec_znx_big_normalize(self.basek(), &mut self.data, i, &res_big, i, scratch1); })@@ -183,7 +156,7 @@
pub fn keyswitch_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &GLWESwitchingKeyExec<DataRhs, B>, + rhs: &GGLWESwitchingKeyExec<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B>,@@ -196,32 +169,33 @@ }
} } -pub(crate) fn keyswitch<B: Backend, DataRes, DataIn, DataKey>( - module: &Module<B>, - res_dft: VecZnxDft<DataRes, B>, - lhs: &GLWECiphertext<DataIn>, - rhs: &GLWESwitchingKeyExec<DataKey, B>, - scratch: &mut Scratch<B>, -) -> VecZnxBig<DataRes, B> -where - DataRes: DataMut, - DataIn: DataRef, - DataKey: DataRef, - Module<B>: GLWEKeyswitchFamily<B>, - Scratch<B>: TakeVecZnxDft<B>, -{ - if rhs.digits() == 1 { - return keyswitch_vmp_one_digit(module, res_dft, &lhs.data, &rhs.key.data, scratch); +impl<D: DataRef> GLWECiphertext<D> { + pub(crate) fn keyswitch_internal<B: Backend, DataRes, DataKey>( + &self, + module: &Module<B>, + res_dft: VecZnxDft<DataRes, B>, + rhs: &GGLWESwitchingKeyExec<DataKey, B>, + scratch: &mut Scratch<B>, + ) -> VecZnxBig<DataRes, B> + where + DataRes: DataMut, + DataKey: DataRef, + Module<B>: GLWEKeyswitchFamily<B>, + Scratch<B>: TakeVecZnxDft<B>, + { + if rhs.digits() == 1 { + return keyswitch_vmp_one_digit(module, res_dft, &self.data, &rhs.key.data, scratch); + } + + keyswitch_vmp_multiple_digits( + module, + res_dft, + &self.data, + &rhs.key.data, + rhs.digits(), + scratch, + ) } - - keyswitch_vmp_multiple_digits( - module, - res_dft, - &lhs.data, - &rhs.key.data, - rhs.digits(), - scratch, - ) } fn keyswitch_vmp_one_digit<B: Backend, DataRes, DataIn, DataVmp>(
@@ -1,328 +0,0 @@
-use backend::hal::{ - api::{FillUniform, Reset, VecZnxCopy, VecZnxFillUniform, ZnxInfos}, - layouts::{Backend, Data, DataMut, DataRef, Module, ReaderFrom, VecZnx, VecZnxToMut, VecZnxToRef, WriterTo}, -}; -use sampling::source::Source; - -use crate::{Decompress, GLWEOps, Infos, SetMetaData}; -use std::fmt; - -#[derive(PartialEq, Eq, Clone)] -pub struct GLWECiphertext<D: Data> { - pub data: VecZnx<D>, - pub basek: usize, - pub k: usize, -} - -impl<D: DataRef> fmt::Debug for GLWECiphertext<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl<D: DataRef> fmt::Display for GLWECiphertext<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "GLWECiphertext: basek={} k={}: {}", - self.basek(), - self.k(), - self.data - ) - } -} - -impl<D: DataMut> Reset for GLWECiphertext<D> -where - VecZnx<D>: Reset, -{ - fn reset(&mut self) { - self.data.reset(); - self.basek = 0; - self.k = 0; - } -} - -impl<D: DataMut> FillUniform for GLWECiphertext<D> -where - VecZnx<D>: FillUniform, -{ - fn fill_uniform(&mut self, source: &mut Source) { - self.data.fill_uniform(source); - } -} - -impl GLWECiphertext<Vec<u8>> { - pub fn alloc(n: usize, basek: usize, k: usize, rank: usize) -> Self { - Self { - data: VecZnx::alloc(n, rank + 1, k.div_ceil(basek)), - basek, - k, - } - } - - pub fn bytes_of(n: usize, basek: usize, k: usize, rank: usize) -> usize { - VecZnx::alloc_bytes(n, rank + 1, k.div_ceil(basek)) - } -} - -impl<D: Data> Infos for GLWECiphertext<D> { - type Inner = VecZnx<D>; - - fn inner(&self) -> &Self::Inner { - &self.data - } - - fn basek(&self) -> usize { - self.basek - } - - fn k(&self) -> usize { - self.k - } -} - -impl<D: Data> GLWECiphertext<D> { - pub fn rank(&self) -> usize { - self.cols() - 1 - } -} - -impl<D: DataRef> GLWECiphertext<D> { - pub fn clone(&self) -> GLWECiphertext<Vec<u8>> { - GLWECiphertext { - data: self.data.clone(), - basek: self.basek(), - k: self.k(), - } - } -} - -impl<D: DataMut> SetMetaData for GLWECiphertext<D> { - fn set_k(&mut self, k: usize) { - self.k = k - } - - fn set_basek(&mut self, basek: usize) { - self.basek = basek - } -} - -pub trait GLWECiphertextToRef: Infos { - fn to_ref(&self) -> GLWECiphertext<&[u8]>; -} - -impl<D: DataRef> GLWECiphertextToRef for GLWECiphertext<D> { - fn to_ref(&self) -> GLWECiphertext<&[u8]> { - GLWECiphertext { - data: self.data.to_ref(), - basek: self.basek, - k: self.k, - } - } -} - -pub trait GLWECiphertextToMut: Infos { - fn to_mut(&mut self) -> GLWECiphertext<&mut [u8]>; -} - -impl<D: DataMut> GLWECiphertextToMut for GLWECiphertext<D> { - fn to_mut(&mut self) -> GLWECiphertext<&mut [u8]> { - GLWECiphertext { - data: self.data.to_mut(), - basek: self.basek, - k: self.k, - } - } -} - -impl<D: DataMut> GLWEOps for GLWECiphertext<D> where GLWECiphertext<D>: GLWECiphertextToMut + Infos + SetMetaData {} - -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; - -impl<D: DataMut> ReaderFrom for GLWECiphertext<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - self.k = reader.read_u64::<LittleEndian>()? as usize; - self.basek = reader.read_u64::<LittleEndian>()? as usize; - self.data.read_from(reader) - } -} - -impl<D: DataRef> WriterTo for GLWECiphertext<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::<LittleEndian>(self.k as u64)?; - writer.write_u64::<LittleEndian>(self.basek as u64)?; - self.data.write_to(writer) - } -} - -#[derive(PartialEq, Eq, Clone)] -pub struct GLWECiphertextCompressed<D: Data> { - pub(crate) data: VecZnx<D>, - pub(crate) basek: usize, - pub(crate) k: usize, - pub(crate) rank: usize, - pub(crate) seed: [u8; 32], -} - -impl<D: DataRef> fmt::Debug for GLWECiphertextCompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl<D: DataRef> fmt::Display for GLWECiphertextCompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "GLWECiphertextCompressed: basek={} k={} rank={} seed={:?}: {}", - self.basek(), - self.k(), - self.rank, - self.seed, - self.data - ) - } -} - -impl<D: DataMut> Reset for GLWECiphertextCompressed<D> -where - VecZnx<D>: Reset, -{ - fn reset(&mut self) { - self.data.reset(); - self.basek = 0; - self.k = 0; - self.rank = 0; - self.seed = [0u8; 32]; - } -} - -impl<D: DataMut> FillUniform for GLWECiphertextCompressed<D> -where - VecZnx<D>: FillUniform, -{ - fn fill_uniform(&mut self, source: &mut Source) { - self.data.fill_uniform(source); - } -} - -impl<D: Data> Infos for GLWECiphertextCompressed<D> { - type Inner = VecZnx<D>; - - fn inner(&self) -> &Self::Inner { - &self.data - } - - fn basek(&self) -> usize { - self.basek - } - - fn k(&self) -> usize { - self.k - } -} - -impl<D: Data> GLWECiphertextCompressed<D> { - pub fn rank(&self) -> usize { - self.rank - } -} - -impl GLWECiphertextCompressed<Vec<u8>> { - pub fn alloc(n: usize, basek: usize, k: usize, rank: usize) -> Self { - Self { - data: VecZnx::alloc(n, 1, k.div_ceil(basek)), - basek, - k, - rank, - seed: [0u8; 32], - } - } - - pub fn bytes_of(n: usize, basek: usize, k: usize) -> usize { - GLWECiphertext::bytes_of(n, basek, k, 1) - } -} - -impl<D: DataMut> ReaderFrom for GLWECiphertextCompressed<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - self.k = reader.read_u64::<LittleEndian>()? as usize; - self.basek = reader.read_u64::<LittleEndian>()? as usize; - self.rank = reader.read_u64::<LittleEndian>()? as usize; - reader.read(&mut self.seed)?; - self.data.read_from(reader) - } -} - -impl<D: DataRef> WriterTo for GLWECiphertextCompressed<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::<LittleEndian>(self.k as u64)?; - writer.write_u64::<LittleEndian>(self.basek as u64)?; - writer.write_u64::<LittleEndian>(self.rank as u64)?; - writer.write_all(&self.seed)?; - self.data.write_to(writer) - } -} - -impl<D: DataMut, B: Backend, DR: DataRef> Decompress<B, GLWECiphertextCompressed<DR>> for GLWECiphertext<D> { - fn decompress(&mut self, module: &Module<B>, other: &GLWECiphertextCompressed<DR>) - where - Module<B>: VecZnxFillUniform + VecZnxCopy, - { - #[cfg(debug_assertions)] - { - assert_eq!( - self.n(), - other.data.n(), - "invalid receiver: self.n()={} != other.n()={}", - self.n(), - other.data.n() - ); - assert_eq!( - self.size(), - other.size(), - "invalid receiver: self.size()={} != other.size()={}", - self.size(), - other.size() - ); - assert_eq!( - self.rank(), - other.rank(), - "invalid receiver: self.rank()={} != other.rank()={}", - self.rank(), - other.rank() - ); - let mut source: Source = Source::new(other.seed); - self.decompress_internal(module, other, &mut source); - } - } -} - -impl<D: DataMut> GLWECiphertext<D> { - pub(crate) fn decompress_internal<DataOther, B: Backend>( - &mut self, - module: &Module<B>, - other: &GLWECiphertextCompressed<DataOther>, - source: &mut Source, - ) where - DataOther: DataRef, - Module<B>: VecZnxFillUniform + VecZnxCopy, - { - #[cfg(debug_assertions)] - { - assert_eq!(self.rank(), other.rank()) - } - - let k: usize = other.k; - let basek: usize = other.basek; - let cols: usize = other.rank() + 1; - module.vec_znx_copy(&mut self.data, 0, &other.data, 0); - (1..cols).for_each(|i| { - module.vec_znx_fill_uniform(basek, &mut self.data, i, k, source); - }); - - self.basek = basek; - self.k = k; - } -}
@@ -1,28 +0,0 @@
-mod automorphism; -mod decryption; -mod encryption; -mod external_product; -mod keyswitch; -mod layout; -mod noise; -mod ops; -mod packing; -mod plaintext; -mod public_key; -mod secret; -mod trace; - -#[cfg(test)] -mod tests; - -pub use decryption::*; -pub use encryption::*; -pub use external_product::*; -pub use keyswitch::*; -pub use layout::*; -pub use ops::GLWEOps; -pub use packing::*; -pub use plaintext::*; -pub use public_key::*; -pub use secret::*; -pub use trace::*;
@@ -4,7 +4,12 @@ layouts::{Backend, DataRef, Module, ScratchOwned},
oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl}, }; -use crate::{GLWECiphertext, GLWEDecryptFamily, GLWEPlaintext, GLWESecretExec, Infos}; +use crate::{ + layouts::GLWEPlaintext, + layouts::prepared::GLWESecretExec, + layouts::{GLWECiphertext, Infos}, + trait_families::GLWEDecryptFamily, +}; impl<D: DataRef> GLWECiphertext<D> { pub fn assert_noise<B: Backend, DataSk, DataPt>(
@@ -4,12 +4,21 @@ VecZnxAdd, VecZnxAddInplace, VecZnxCopy, VecZnxMulXpMinusOne, VecZnxMulXpMinusOneInplace, VecZnxNegateInplace,
VecZnxNormalize, VecZnxNormalizeInplace, VecZnxRotate, VecZnxRotateInplace, VecZnxRshInplace, VecZnxSub, VecZnxSubABInplace, VecZnxSubBAInplace, ZnxZero, }, - layouts::{Backend, Module, Scratch, VecZnx}, + layouts::{Backend, DataMut, Module, Scratch, VecZnx}, }; -use crate::{GLWECiphertext, GLWECiphertextToMut, GLWECiphertextToRef, Infos, SetMetaData}; +use crate::layouts::{GLWECiphertext, GLWECiphertextToMut, GLWECiphertextToRef, GLWEPlaintext, Infos, SetMetaData}; + +impl<D> GLWEOperations for GLWEPlaintext<D> +where + D: DataMut, + GLWEPlaintext<D>: GLWECiphertextToMut + Infos + SetMetaData, +{ +} + +impl<D: DataMut> GLWEOperations for GLWECiphertext<D> where GLWECiphertext<D>: GLWECiphertextToMut + Infos + SetMetaData {} -pub trait GLWEOps: GLWECiphertextToMut + SetMetaData + Sized { +pub trait GLWEOperations: GLWECiphertextToMut + SetMetaData + Sized { fn add<A, B, BACKEND: Backend>(&mut self, module: &Module<BACKEND>, a: &A, b: &B) where A: GLWECiphertextToRef,
@@ -1,29 +1,16 @@
use std::collections::HashMap; use backend::hal::{ - api::{ - ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxAddInplace, VecZnxAutomorphismInplace, VecZnxBigAutomorphismInplace, - VecZnxBigSubSmallBInplace, VecZnxCopy, VecZnxNegateInplace, VecZnxNormalizeInplace, VecZnxRotate, VecZnxRotateInplace, - VecZnxRshInplace, VecZnxSub, VecZnxSubABInplace, - }, + api::{ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxCopy}, layouts::{Backend, DataMut, DataRef, Module, Scratch}, }; -use crate::{AutomorphismKeyExec, GLWECiphertext, GLWEKeyswitchFamily, GLWEOps, Infos, TakeGLWECt}; +use crate::{ + GLWEOperations, TakeGLWECt, + layouts::{GLWECiphertext, Infos, prepared::GGLWEAutomorphismKeyExec}, +}; -pub trait GLWEPackingFamily<B: Backend> = GLWEKeyswitchFamily<B> - + VecZnxCopy - + VecZnxRotateInplace - + VecZnxSub - + VecZnxNegateInplace - + VecZnxRshInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<B> - + VecZnxSubABInplace - + VecZnxRotate - + VecZnxAutomorphismInplace - + VecZnxBigSubSmallBInplace<B> - + VecZnxBigAutomorphismInplace<B>; +use crate::trait_families::{GLWEKeyswitchFamily, GLWEPackingFamily}; /// [GLWEPacker] enables only the fly GLWE packing /// with constant memory of Log(N) ciphertexts.@@ -128,7 +115,7 @@ pub fn add<DataA: DataRef, DataAK: DataRef, B: Backend>(
&mut self, module: &Module<B>, a: Option<&GLWECiphertext<DataA>>, - auto_keys: &HashMap<i64, AutomorphismKeyExec<DataAK, B>>, + auto_keys: &HashMap<i64, GGLWEAutomorphismKeyExec<DataAK, B>>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEPackingFamily<B>,@@ -187,7 +174,7 @@ module: &Module<B>,
a: Option<&GLWECiphertext<D>>, accumulators: &mut [Accumulator], i: usize, - auto_keys: &HashMap<i64, AutomorphismKeyExec<DataAK, B>>, + auto_keys: &HashMap<i64, GGLWEAutomorphismKeyExec<DataAK, B>>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEPackingFamily<B>,@@ -265,7 +252,7 @@ module: &Module<B>,
acc: &mut Accumulator, b: Option<&GLWECiphertext<D>>, i: usize, - auto_keys: &HashMap<i64, AutomorphismKeyExec<DataAK, B>>, + auto_keys: &HashMap<i64, GGLWEAutomorphismKeyExec<DataAK, B>>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEPackingFamily<B>,
@@ -1,6 +1,6 @@
use backend::hal::layouts::{Data, DataMut, DataRef, VecZnx, VecZnxToMut, VecZnxToRef}; -use crate::{GLWECiphertext, GLWECiphertextToMut, GLWECiphertextToRef, GLWEOps, Infos, SetMetaData}; +use crate::layouts::{GLWECiphertext, GLWECiphertextToMut, GLWECiphertextToRef, Infos, SetMetaData}; pub struct GLWEPlaintext<D: Data> { pub data: VecZnx<D>,@@ -67,10 +67,3 @@ k: self.k,
} } } - -impl<D> GLWEOps for GLWEPlaintext<D> -where - D: DataMut, - GLWEPlaintext<D>: GLWECiphertextToMut + Infos + SetMetaData, -{ -}
@@ -1,204 +0,0 @@
-use backend::hal::{ - api::{ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftFromVecZnx}, - layouts::{Backend, Data, DataMut, DataRef, Module, ReaderFrom, Scratch, ScratchOwned, VecZnx, VecZnxDft, WriterTo}, - oep::{ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeVecZnxDftImpl, TakeVecZnxImpl}, -}; -use sampling::source::Source; - -use crate::{GLWECiphertext, GLWEEncryptSkFamily, GLWESecretExec, Infos, dist::Distribution}; - -pub trait GLWEPublicKeyFamily<B: Backend> = GLWEEncryptSkFamily<B>; - -#[derive(PartialEq, Eq)] -pub struct GLWEPublicKey<D: Data> { - pub(crate) data: VecZnx<D>, - pub(crate) basek: usize, - pub(crate) k: usize, - pub(crate) dist: Distribution, -} - -impl GLWEPublicKey<Vec<u8>> { - pub fn alloc(n: usize, basek: usize, k: usize, rank: usize) -> Self { - Self { - data: VecZnx::alloc(n, rank + 1, k.div_ceil(basek)), - basek: basek, - k: k, - dist: Distribution::NONE, - } - } - - pub fn bytes_of(n: usize, basek: usize, k: usize, rank: usize) -> usize { - VecZnx::alloc_bytes(n, rank + 1, k.div_ceil(basek)) - } -} - -impl<D: Data> Infos for GLWEPublicKey<D> { - type Inner = VecZnx<D>; - - fn inner(&self) -> &Self::Inner { - &self.data - } - - fn basek(&self) -> usize { - self.basek - } - - fn k(&self) -> usize { - self.k - } -} - -impl<D: Data> GLWEPublicKey<D> { - pub fn rank(&self) -> usize { - self.cols() - 1 - } -} - -impl<D: DataMut> GLWEPublicKey<D> { - pub fn generate_from_sk<S: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - sk: &GLWESecretExec<S, B>, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - ) where - Module<B>: GLWEPublicKeyFamily<B>, - B: ScratchOwnedAllocImpl<B> - + ScratchOwnedBorrowImpl<B> - + TakeVecZnxDftImpl<B> - + ScratchAvailableImpl<B> - + TakeVecZnxImpl<B>, - { - #[cfg(debug_assertions)] - { - assert_eq!(self.n(), sk.n()); - - match sk.dist { - Distribution::NONE => panic!("invalid sk: SecretDistribution::NONE"), - _ => {} - } - } - - // Its ok to allocate scratch space here since pk is usually generated only once. - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWECiphertext::encrypt_sk_scratch_space( - module, - self.n(), - self.basek(), - self.k(), - )); - - let mut tmp: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(self.n(), self.basek(), self.k(), self.rank()); - tmp.encrypt_zero_sk(module, sk, source_xa, source_xe, sigma, scratch.borrow()); - self.dist = sk.dist; - } -} - -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; - -impl<D: DataMut> ReaderFrom for GLWEPublicKey<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - self.k = reader.read_u64::<LittleEndian>()? as usize; - self.basek = reader.read_u64::<LittleEndian>()? as usize; - match Distribution::read_from(reader) { - Ok(dist) => self.dist = dist, - Err(e) => return Err(e), - } - self.data.read_from(reader) - } -} - -impl<D: DataRef> WriterTo for GLWEPublicKey<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::<LittleEndian>(self.k as u64)?; - writer.write_u64::<LittleEndian>(self.basek as u64)?; - match self.dist.write_to(writer) { - Ok(()) => {} - Err(e) => return Err(e), - } - self.data.write_to(writer) - } -} - -#[derive(PartialEq, Eq)] -pub struct GLWEPublicKeyExec<D: Data, B: Backend> { - pub(crate) data: VecZnxDft<D, B>, - pub(crate) basek: usize, - pub(crate) k: usize, - pub(crate) dist: Distribution, -} - -impl<D: Data, B: Backend> Infos for GLWEPublicKeyExec<D, B> { - type Inner = VecZnxDft<D, B>; - - fn inner(&self) -> &Self::Inner { - &self.data - } - - fn basek(&self) -> usize { - self.basek - } - - fn k(&self) -> usize { - self.k - } -} - -impl<D: Data, B: Backend> GLWEPublicKeyExec<D, B> { - pub fn rank(&self) -> usize { - self.cols() - 1 - } -} - -impl<B: Backend> GLWEPublicKeyExec<Vec<u8>, B> { - pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> Self - where - Module<B>: VecZnxDftAlloc<B>, - { - Self { - data: module.vec_znx_dft_alloc(n, rank + 1, k.div_ceil(basek)), - basek: basek, - k: k, - dist: Distribution::NONE, - } - } - - pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize - where - Module<B>: VecZnxDftAllocBytes, - { - module.vec_znx_dft_alloc_bytes(n, rank + 1, k.div_ceil(basek)) - } - - pub fn from<DataOther>(module: &Module<B>, other: &GLWEPublicKey<DataOther>, scratch: &mut Scratch<B>) -> Self - where - DataOther: DataRef, - Module<B>: VecZnxDftAlloc<B> + VecZnxDftFromVecZnx<B>, - { - let mut pk_exec: GLWEPublicKeyExec<Vec<u8>, B> = - GLWEPublicKeyExec::alloc(module, other.n(), other.basek(), other.k(), other.rank()); - pk_exec.prepare(module, other, scratch); - pk_exec - } -} - -impl<D: DataMut, B: Backend> GLWEPublicKeyExec<D, B> { - pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GLWEPublicKey<DataOther>, _scratch: &mut Scratch<B>) - where - DataOther: DataRef, - Module<B>: VecZnxDftFromVecZnx<B>, - { - #[cfg(debug_assertions)] - { - assert_eq!(self.n(), other.n()); - assert_eq!(self.size(), other.size()); - } - - (0..self.cols()).for_each(|i| { - module.vec_znx_dft_from_vec_znx(1, 0, &mut self.data, i, &other.data, i); - }); - self.k = other.k; - self.basek = other.basek; - self.dist = other.dist; - } -}
@@ -1,167 +0,0 @@
-use backend::hal::{ - api::{SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, ZnxInfos, ZnxZero}, - layouts::{Backend, Data, DataMut, DataRef, Module, ReaderFrom, ScalarZnx, SvpPPol, WriterTo}, -}; -use sampling::source::Source; - -use crate::dist::Distribution; - -pub trait GLWESecretFamily<B: Backend> = SvpPrepare<B> + SvpPPolAllocBytes + SvpPPolAlloc<B>; - -#[derive(PartialEq, Eq, Clone)] -pub struct GLWESecret<D: Data> { - pub(crate) data: ScalarZnx<D>, - pub(crate) dist: Distribution, -} - -impl GLWESecret<Vec<u8>> { - pub fn alloc(n: usize, rank: usize) -> Self { - Self { - data: ScalarZnx::alloc(n, rank), - dist: Distribution::NONE, - } - } - - pub fn bytes_of(n: usize, rank: usize) -> usize { - ScalarZnx::alloc_bytes(n, rank) - } -} - -impl<D: Data> GLWESecret<D> { - pub fn n(&self) -> usize { - self.data.n() - } - - pub fn log_n(&self) -> usize { - self.data.log_n() - } - - pub fn rank(&self) -> usize { - self.data.cols() - } -} - -impl<D: DataMut> GLWESecret<D> { - pub fn fill_ternary_prob(&mut self, prob: f64, source: &mut Source) { - (0..self.rank()).for_each(|i| { - self.data.fill_ternary_prob(i, prob, source); - }); - self.dist = Distribution::TernaryProb(prob); - } - - pub fn fill_ternary_hw(&mut self, hw: usize, source: &mut Source) { - (0..self.rank()).for_each(|i| { - self.data.fill_ternary_hw(i, hw, source); - }); - self.dist = Distribution::TernaryFixed(hw); - } - - pub fn fill_binary_prob(&mut self, prob: f64, source: &mut Source) { - (0..self.rank()).for_each(|i| { - self.data.fill_binary_prob(i, prob, source); - }); - self.dist = Distribution::BinaryProb(prob); - } - - pub fn fill_binary_hw(&mut self, hw: usize, source: &mut Source) { - (0..self.rank()).for_each(|i| { - self.data.fill_binary_hw(i, hw, source); - }); - self.dist = Distribution::BinaryFixed(hw); - } - - pub fn fill_binary_block(&mut self, block_size: usize, source: &mut Source) { - (0..self.rank()).for_each(|i| { - self.data.fill_binary_block(i, block_size, source); - }); - self.dist = Distribution::BinaryBlock(block_size); - } - - pub fn fill_zero(&mut self) { - self.data.zero(); - self.dist = Distribution::ZERO; - } -} - -impl<D: DataMut> ReaderFrom for GLWESecret<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - match Distribution::read_from(reader) { - Ok(dist) => self.dist = dist, - Err(e) => return Err(e), - } - self.data.read_from(reader) - } -} - -impl<D: DataRef> WriterTo for GLWESecret<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - match self.dist.write_to(writer) { - Ok(()) => {} - Err(e) => return Err(e), - } - self.data.write_to(writer) - } -} - -pub struct GLWESecretExec<D: Data, B: Backend> { - pub(crate) data: SvpPPol<D, B>, - pub(crate) dist: Distribution, -} - -impl<B: Backend> GLWESecretExec<Vec<u8>, B> { - pub fn alloc(module: &Module<B>, n: usize, rank: usize) -> Self - where - Module<B>: SvpPPolAlloc<B>, - { - Self { - data: module.svp_ppol_alloc(n, rank), - dist: Distribution::NONE, - } - } - - pub fn bytes_of(module: &Module<B>, n: usize, rank: usize) -> usize - where - Module<B>: SvpPPolAllocBytes, - { - module.svp_ppol_alloc_bytes(n, rank) - } -} - -impl<B: Backend> GLWESecretExec<Vec<u8>, B> { - pub fn from<D>(module: &Module<B>, sk: &GLWESecret<D>) -> Self - where - D: DataRef, - Module<B>: SvpPrepare<B> + SvpPPolAlloc<B>, - { - let mut sk_dft: GLWESecretExec<Vec<u8>, B> = Self::alloc(module, sk.n(), sk.rank()); - sk_dft.prepare(module, sk); - sk_dft - } -} - -impl<D: Data, B: Backend> GLWESecretExec<D, B> { - pub fn n(&self) -> usize { - self.data.n() - } - - pub fn log_n(&self) -> usize { - self.data.log_n() - } - - pub fn rank(&self) -> usize { - self.data.cols() - } -} - -impl<D: DataMut, B: Backend> GLWESecretExec<D, B> { - pub(crate) fn prepare<O>(&mut self, module: &Module<B>, sk: &GLWESecret<O>) - where - O: DataRef, - Module<B>: SvpPrepare<B>, - { - (0..self.rank()).for_each(|i| { - module.svp_prepare(&mut self.data, i, &sk.data, i); - }); - self.dist = sk.dist - } -}
@@ -1,176 +0,0 @@
-use backend::{ - hal::{api::ModuleNew, layouts::Module}, - implementation::cpu_spqlios::FFT64, -}; - -use crate::glwe::tests::{ - generic_automorphism::{test_automorphism, test_automorphism_inplace}, - generic_encryption::{test_encrypt_pk, test_encrypt_sk, test_encrypt_sk_compressed, test_encrypt_zero_sk}, - generic_external_product::{test_external_product, test_external_product_inplace}, - generic_keyswitch::{test_keyswitch, test_keyswitch_inplace}, - packing::test_packing, - trace::test_trace_inplace, -}; - -#[test] -fn encrypt_sk() { - let log_n: usize = 8; - let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); - (1..4).for_each(|rank| { - println!("test encrypt_sk rank: {}", rank); - test_encrypt_sk(&module, 8, 54, 30, 3.2, rank); - }); -} - -#[test] -fn encrypt_sk_compressed() { - let log_n: usize = 8; - let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); - (1..4).for_each(|rank| { - println!("test encrypt_sk rank: {}", rank); - test_encrypt_sk_compressed(&module, 8, 54, 30, 3.2, rank); - }); -} - -#[test] -fn encrypt_zero_sk() { - let log_n: usize = 8; - let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); - (1..4).for_each(|rank| { - println!("test encrypt_zero_sk rank: {}", rank); - test_encrypt_zero_sk(&module, 8, 64, 3.2, rank); - }); -} - -#[test] -fn encrypt_pk() { - let log_n: usize = 8; - let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); - (1..4).for_each(|rank| { - println!("test encrypt_pk rank: {}", rank); - test_encrypt_pk(&module, 8, 64, 64, 3.2, rank) - }); -} - -#[test] -fn apply() { - let log_n: usize = 8; - let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); - let basek: usize = 12; - let k_in: usize = 45; - let digits: usize = k_in.div_ceil(basek); - (1..4).for_each(|rank_in| { - (1..4).for_each(|rank_out| { - (1..digits + 1).for_each(|di| { - let k_ksk: usize = k_in + basek * di; - let k_out: usize = k_ksk; // better capture noise - println!( - "test keyswitch digits: {} rank_in: {} rank_out: {}", - di, rank_in, rank_out - ); - test_keyswitch( - &module, basek, k_out, k_in, k_ksk, di, rank_in, rank_out, 3.2, - ); - }) - }); - }); -} - -#[test] -fn apply_inplace() { - let log_n: usize = 8; - let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); - let basek: usize = 12; - let k_ct: usize = 45; - let digits: usize = k_ct.div_ceil(basek); - (1..4).for_each(|rank| { - (1..digits + 1).for_each(|di| { - let k_ksk: usize = k_ct + basek * di; - println!("test keyswitch_inplace digits: {} rank: {}", di, rank); - test_keyswitch_inplace(&module, basek, k_ct, k_ksk, di, rank, 3.2); - }); - }); -} - -#[test] -fn automorphism_inplace() { - let log_n: usize = 8; - let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); - let basek: usize = 12; - let k_ct: usize = 60; - let digits: usize = k_ct.div_ceil(basek); - (1..4).for_each(|rank| { - (1..digits + 1).for_each(|di| { - let k_ksk: usize = k_ct + basek * di; - println!("test automorphism_inplace digits: {} rank: {}", di, rank); - test_automorphism_inplace(&module, basek, -5, k_ct, k_ksk, di, rank, 3.2); - }); - }); -} - -#[test] -fn automorphism() { - let log_n: usize = 8; - let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); - let basek: usize = 12; - let k_in: usize = 60; - let digits: usize = k_in.div_ceil(basek); - (1..4).for_each(|rank| { - (1..digits + 1).for_each(|di| { - let k_ksk: usize = k_in + basek * di; - let k_out: usize = k_ksk; // Better capture noise. - println!("test automorphism digits: {} rank: {}", di, rank); - test_automorphism(&module, basek, -5, k_out, k_in, k_ksk, di, rank, 3.2); - }) - }); -} - -#[test] -fn external_product() { - let log_n: usize = 8; - let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); - let basek: usize = 12; - let k_in: usize = 45; - let digits: usize = k_in.div_ceil(basek); - (1..4).for_each(|rank| { - (1..digits + 1).for_each(|di| { - let k_ggsw: usize = k_in + basek * di; - let k_out: usize = k_ggsw; // Better capture noise - println!("test external_product digits: {} rank: {}", di, rank); - test_external_product(&module, basek, k_out, k_in, k_ggsw, di, rank, 3.2); - }); - }); -} - -#[test] -fn external_product_inplace() { - let log_n: usize = 8; - let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); - let basek: usize = 12; - let k_ct: usize = 60; - let digits: usize = k_ct.div_ceil(basek); - (1..4).for_each(|rank| { - (1..digits + 1).for_each(|di| { - let k_ggsw: usize = k_ct + basek * di; - println!("test external_product digits: {} rank: {}", di, rank); - test_external_product_inplace(&module, basek, k_ct, k_ggsw, di, rank, 3.2); - }); - }); -} - -#[test] -fn trace_inplace() { - let log_n: usize = 8; - let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); - (1..4).for_each(|rank| { - println!("test trace_inplace rank: {}", rank); - test_trace_inplace(&module, 8, 54, 3.2, rank); - }); -} - -#[test] -fn packing() { - let log_n: usize = 5; - let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); - test_packing(&module); -}
@@ -1,7 +1,7 @@
use backend::hal::{ api::{ ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, - VecZnxFillUniform, VecZnxStd, VecZnxSwithcDegree, + VecZnxFillUniform, VecZnxStd, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, }, layouts::{Backend, Module, ScratchOwned}, oep::{@@ -12,30 +12,17 @@ };
use sampling::source::Source; use crate::{ - AutomorphismKey, AutomorphismKeyEncryptSkFamily, AutomorphismKeyExec, GGLWEExecLayoutFamily, GLWECiphertext, - GLWEDecryptFamily, GLWEKeyswitchFamily, GLWEPlaintext, GLWESecret, GLWESecretExec, Infos, + layouts::{ + GGLWEAutomorphismKey, GLWECiphertext, GLWEPlaintext, GLWESecret, Infos, + prepared::{GGLWEAutomorphismKeyExec, GLWESecretExec}, + }, noise::log2_std_noise_gglwe_product, + trait_families::{GLWEDecryptFamily, GLWEKeyswitchFamily}, }; -pub(crate) trait AutomorphismTestModuleFamily<B: Backend> = AutomorphismKeyEncryptSkFamily<B> - + GLWEDecryptFamily<B> - + GGLWEExecLayoutFamily<B> - + GLWEKeyswitchFamily<B> - + VecZnxAutomorphism - + VecZnxSwithcDegree - + VecZnxAddScalarInplace - + VecZnxAutomorphismInplace - + VecZnxStd; -pub(crate) trait AutomorphismTestScratchFamily<B: Backend> = TakeVecZnxDftImpl<B> - + TakeVecZnxBigImpl<B> - + TakeSvpPPolImpl<B> - + ScratchOwnedAllocImpl<B> - + ScratchOwnedBorrowImpl<B> - + ScratchAvailableImpl<B> - + TakeScalarZnxImpl<B> - + TakeVecZnxImpl<B>; +use crate::trait_families::{GGLWEAutomorphismKeyEncryptSkFamily, GLWESecretExecModuleFamily}; -pub(crate) fn test_automorphism<B: Backend>( +pub fn test_glwe_automorphism<B: Backend>( module: &Module<B>, basek: usize, p: i64,@@ -46,13 +33,30 @@ digits: usize,
rank: usize, sigma: f64, ) where - Module<B>: AutomorphismTestModuleFamily<B>, - B: AutomorphismTestScratchFamily<B>, + Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + + GLWEDecryptFamily<B> + + GLWEKeyswitchFamily<B> + + VecZnxAutomorphism + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxAutomorphismInplace + + VecZnxStd + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B>, { let n: usize = module.n(); let rows: usize = k_in.div_ceil(basek * digits); - let mut autokey: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); + let mut autokey: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); let mut ct_in: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_in, rank); let mut ct_out: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_out, rank); let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_in);@@ -64,7 +68,7 @@
module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_in, &mut source_xa); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - AutomorphismKey::encrypt_sk_scratch_space(module, n, basek, autokey.k(), rank) + GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, n, basek, autokey.k(), rank) | GLWECiphertext::decrypt_scratch_space(module, n, basek, ct_out.k()) | GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, ct_in.k()) | GLWECiphertext::automorphism_scratch_space(@@ -103,8 +107,8 @@ sigma,
scratch.borrow(), ); - let mut autokey_exec: AutomorphismKeyExec<Vec<u8>, B> = - AutomorphismKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); + let mut autokey_exec: GGLWEAutomorphismKeyExec<Vec<u8>, B> = + GGLWEAutomorphismKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); autokey_exec.prepare(module, &autokey, scratch.borrow()); ct_out.automorphism(module, &ct_in, &autokey_exec, scratch.borrow());@@ -127,7 +131,7 @@
ct_out.assert_noise(module, &sk_exec, &pt_want, max_noise + 1.0); } -pub(crate) fn test_automorphism_inplace<B: Backend>( +pub fn test_glwe_automorphism_inplace<B: Backend>( module: &Module<B>, basek: usize, p: i64,@@ -137,13 +141,30 @@ digits: usize,
rank: usize, sigma: f64, ) where - Module<B>: AutomorphismTestModuleFamily<B>, - B: AutomorphismTestScratchFamily<B>, + Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + + GLWEDecryptFamily<B> + + GLWEKeyswitchFamily<B> + + VecZnxAutomorphism + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxAutomorphismInplace + + VecZnxStd + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B>, { let n: usize = module.n(); let rows: usize = k_ct.div_ceil(basek * digits); - let mut autokey: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); + let mut autokey: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank); let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_ct);@@ -154,7 +175,7 @@
module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_ct, &mut source_xa); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - AutomorphismKey::encrypt_sk_scratch_space(module, n, basek, autokey.k(), rank) + GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, n, basek, autokey.k(), rank) | GLWECiphertext::decrypt_scratch_space(module, n, basek, ct.k()) | GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, ct.k()) | GLWECiphertext::automorphism_inplace_scratch_space(module, n, basek, ct.k(), autokey.k(), digits, rank),@@ -184,8 +205,8 @@ sigma,
scratch.borrow(), ); - let mut autokey_exec: AutomorphismKeyExec<Vec<u8>, B> = - AutomorphismKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); + let mut autokey_exec: GGLWEAutomorphismKeyExec<Vec<u8>, B> = + GGLWEAutomorphismKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); autokey_exec.prepare(module, &autokey, scratch.borrow()); ct.automorphism_inplace(module, &autokey_exec, scratch.borrow());
@@ -9,25 +9,31 @@ };
use sampling::source::Source; use crate::{ - Decompress, GLWECiphertext, GLWECiphertextCompressed, GLWEDecryptFamily, GLWEEncryptPkFamily, GLWEEncryptSkFamily, GLWEOps, - GLWEPlaintext, GLWEPublicKey, GLWEPublicKeyExec, GLWESecret, GLWESecretExec, GLWESecretFamily, Infos, + layouts::{ + GLWECiphertext, GLWEPlaintext, GLWEPublicKey, GLWESecret, Infos, + compressed::GLWECiphertextCompressed, + prepared::{GLWEPublicKeyExec, GLWESecretExec}, + }, + operations::GLWEOperations, + trait_families::Decompress, }; -pub(crate) trait EncryptionTestModuleFamily<B: Backend> = GLWEDecryptFamily<B> + GLWESecretFamily<B> + VecZnxStd; +use crate::trait_families::{GLWEDecryptFamily, GLWEEncryptPkFamily, GLWEEncryptSkFamily, GLWESecretExecModuleFamily}; -pub(crate) trait EncryptionTestScratchFamily<B: Backend> = TakeVecZnxDftImpl<B> - + TakeVecZnxBigImpl<B> - + TakeSvpPPolImpl<B> - + ScratchOwnedAllocImpl<B> - + ScratchOwnedBorrowImpl<B> - + ScratchAvailableImpl<B> - + TakeScalarZnxImpl<B> - + TakeVecZnxImpl<B>; +pub trait EncryptionTestModuleFamily<B: Backend> = + GLWEDecryptFamily<B> + VecZnxStd + GLWESecretExecModuleFamily<B> + GLWEEncryptPkFamily<B>; -pub(crate) fn test_encrypt_sk<B: Backend>(module: &Module<B>, basek: usize, k_ct: usize, k_pt: usize, sigma: f64, rank: usize) +pub fn test_glwe_encrypt_sk<B: Backend>(module: &Module<B>, basek: usize, k_ct: usize, k_pt: usize, sigma: f64, rank: usize) where Module<B>: EncryptionTestModuleFamily<B> + GLWEEncryptSkFamily<B>, - B: EncryptionTestScratchFamily<B>, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B>, { let n = module.n(); let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank);@@ -69,7 +75,7 @@
assert!(noise_have <= noise_want + 0.2); } -pub(crate) fn test_encrypt_sk_compressed<B: Backend>( +pub fn test_glwe_compressed_encrypt_sk<B: Backend>( module: &Module<B>, basek: usize, k_ct: usize,@@ -78,7 +84,14 @@ sigma: f64,
rank: usize, ) where Module<B>: EncryptionTestModuleFamily<B> + GLWEEncryptSkFamily<B> + VecZnxCopy, - B: EncryptionTestScratchFamily<B>, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B>, { let n = module.n(); let mut ct_compressed: GLWECiphertextCompressed<Vec<u8>> = GLWECiphertextCompressed::alloc(n, basek, k_ct, rank);@@ -131,10 +144,17 @@ noise_want + 0.2
); } -pub(crate) fn test_encrypt_zero_sk<B: Backend>(module: &Module<B>, basek: usize, k_ct: usize, sigma: f64, rank: usize) +pub fn test_glwe_encrypt_zero_sk<B: Backend>(module: &Module<B>, basek: usize, k_ct: usize, sigma: f64, rank: usize) where Module<B>: EncryptionTestModuleFamily<B> + GLWEEncryptSkFamily<B>, - B: EncryptionTestScratchFamily<B>, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B>, { let n = module.n(); let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_ct);@@ -167,15 +187,18 @@
assert!((sigma - module.vec_znx_std(basek, &pt.data, 0) * (k_ct as f64).exp2()) <= 0.2); } -pub(crate) fn test_encrypt_pk<B: Backend>(module: &Module<B>, basek: usize, k_ct: usize, k_pk: usize, sigma: f64, rank: usize) +pub fn test_glwe_encrypt_pk<B: Backend>(module: &Module<B>, basek: usize, k_ct: usize, k_pk: usize, sigma: f64, rank: usize) where - Module<B>: EncryptionTestModuleFamily<B> - + GLWEEncryptPkFamily<B> - + GLWEEncryptSkFamily<B> - + VecZnxDftAlloc<B> - + VecZnxFillUniform - + VecZnxSubABInplace, - B: EncryptionTestScratchFamily<B>, + Module<B>: + EncryptionTestModuleFamily<B> + GLWEEncryptSkFamily<B> + VecZnxDftAlloc<B> + VecZnxFillUniform + VecZnxSubABInplace, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B>, { let n: usize = module.n(); let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank);
@@ -1,7 +1,7 @@
use backend::hal::{ api::{ ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxFillUniform, VecZnxRotateInplace, VecZnxStd, - ZnxViewMut, + VmpPMatAlloc, VmpPMatPrepare, ZnxViewMut, }, layouts::{Backend, Module, ScalarZnx, ScratchOwned}, oep::{@@ -12,29 +12,16 @@ };
use sampling::source::Source; use crate::{ - GGSWCiphertext, GGSWCiphertextExec, GGSWLayoutFamily, GLWECiphertext, GLWEDecryptFamily, GLWEEncryptSkFamily, - GLWEExternalProductFamily, GLWEPlaintext, GLWESecret, GLWESecretExec, GLWESecretFamily, Infos, noise::noise_ggsw_product, + layouts::{ + GGSWCiphertext, GLWECiphertext, GLWEPlaintext, GLWESecret, Infos, + prepared::{GGSWCiphertextExec, GLWESecretExec}, + }, + noise::noise_ggsw_product, }; -pub(crate) trait ExternalProductTestModuleFamily<B: Backend> = GLWEEncryptSkFamily<B> - + GLWEDecryptFamily<B> - + GLWESecretFamily<B> - + GLWEExternalProductFamily<B> - + GGSWLayoutFamily<B> - + VecZnxAddScalarInplace - + VecZnxRotateInplace - + VecZnxStd; - -pub(crate) trait ExternalProductTestScratchFamily<B: Backend> = TakeVecZnxDftImpl<B> - + TakeVecZnxBigImpl<B> - + TakeSvpPPolImpl<B> - + ScratchOwnedAllocImpl<B> - + ScratchOwnedBorrowImpl<B> - + ScratchAvailableImpl<B> - + TakeScalarZnxImpl<B> - + TakeVecZnxImpl<B>; +use crate::trait_families::{GLWEDecryptFamily, GLWEEncryptSkFamily, GLWEExternalProductFamily, GLWESecretExecModuleFamily}; -pub(crate) fn test_external_product<B: Backend>( +pub fn test_glwe_external_product<B: Backend>( module: &Module<B>, basek: usize, k_out: usize,@@ -44,8 +31,23 @@ digits: usize,
rank: usize, sigma: f64, ) where - Module<B>: ExternalProductTestModuleFamily<B>, - B: ExternalProductTestScratchFamily<B>, + Module<B>: GLWEEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + + GLWEDecryptFamily<B> + + GLWEExternalProductFamily<B> + + VecZnxAddScalarInplace + + VecZnxRotateInplace + + VecZnxStd + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B>, { let n: usize = module.n(); let rows: usize = k_in.div_ceil(basek * digits);@@ -138,7 +140,7 @@
ct_glwe_out.assert_noise(module, &sk_exec, &pt_want, max_noise + 0.5); } -pub(crate) fn test_external_product_inplace<B: Backend>( +pub fn test_glwe_external_product_inplace<B: Backend>( module: &Module<B>, basek: usize, k_ct: usize,@@ -147,8 +149,23 @@ digits: usize,
rank: usize, sigma: f64, ) where - Module<B>: ExternalProductTestModuleFamily<B>, - B: ExternalProductTestScratchFamily<B>, + Module<B>: GLWEEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + + GLWEDecryptFamily<B> + + GLWEExternalProductFamily<B> + + VecZnxAddScalarInplace + + VecZnxRotateInplace + + VecZnxStd + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B>, { let n: usize = module.n(); let rows: usize = k_ct.div_ceil(basek * digits);
@@ -1,5 +1,8 @@
use backend::hal::{ - api::{ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxFillUniform, VecZnxStd, VecZnxSwithcDegree}, + api::{ + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxFillUniform, VecZnxStd, VecZnxSwithcDegree, + VmpPMatAlloc, VmpPMatPrepare, + }, layouts::{Backend, Module, ScratchOwned}, oep::{ ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,@@ -9,30 +12,17 @@ };
use sampling::source::Source; use crate::{ - GGLWEExecLayoutFamily, GLWECiphertext, GLWEDecryptFamily, GLWEKeyswitchFamily, GLWEPlaintext, GLWESecret, GLWESecretExec, - GLWESecretFamily, GLWESwitchingKey, GLWESwitchingKeyEncryptSkFamily, GLWESwitchingKeyExec, Infos, + layouts::{ + GLWECiphertext, GLWEPlaintext, GLWESecret, GGLWESwitchingKey, Infos, + prepared::{GLWESecretExec, GGLWESwitchingKeyExec}, + }, noise::log2_std_noise_gglwe_product, + trait_families::{GLWEDecryptFamily, GLWEKeyswitchFamily}, }; -pub(crate) trait KeySwitchTestModuleFamily<B: Backend> = GLWESecretFamily<B> - + GLWESwitchingKeyEncryptSkFamily<B> - + GLWEKeyswitchFamily<B> - + GLWEDecryptFamily<B> - + GGLWEExecLayoutFamily<B> - + VecZnxStd - + VecZnxSwithcDegree - + VecZnxAddScalarInplace; - -pub(crate) trait KeySwitchTestScratchFamily<B: Backend> = TakeVecZnxDftImpl<B> - + TakeVecZnxBigImpl<B> - + TakeSvpPPolImpl<B> - + ScratchOwnedAllocImpl<B> - + ScratchOwnedBorrowImpl<B> - + ScratchAvailableImpl<B> - + TakeScalarZnxImpl<B> - + TakeVecZnxImpl<B>; +use crate::trait_families::{GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; -pub(crate) fn test_keyswitch<B: Backend>( +pub fn test_glwe_keyswitch<B: Backend>( module: &Module<B>, basek: usize, k_out: usize,@@ -43,13 +33,28 @@ rank_in: usize,
rank_out: usize, sigma: f64, ) where - Module<B>: KeySwitchTestModuleFamily<B>, - B: KeySwitchTestScratchFamily<B>, + Module<B>: GGLWESwitchingKeyEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + + GLWEKeyswitchFamily<B> + + GLWEDecryptFamily<B> + + VecZnxStd + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B>, { let n = module.n(); let rows: usize = k_in.div_ceil(basek * digits); - let mut ksk: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_in, rank_out); + let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_in, rank_out); let mut ct_in: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_in, rank_in); let mut ct_out: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_out, rank_out); let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_in);@@ -61,7 +66,7 @@
module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_in, &mut source_xa); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, ksk.k(), rank_in, rank_out) + GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, ksk.k(), rank_in, rank_out) | GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, ct_in.k()) | GLWECiphertext::keyswitch_scratch_space( module,@@ -104,7 +109,7 @@ sigma,
scratch.borrow(), ); - let ksk_exec: GLWESwitchingKeyExec<Vec<u8>, B> = GLWESwitchingKeyExec::from(module, &ksk, scratch.borrow()); + let ksk_exec: GGLWESwitchingKeyExec<Vec<u8>, B> = GGLWESwitchingKeyExec::from(module, &ksk, scratch.borrow()); ct_out.keyswitch(module, &ct_in, &ksk_exec, scratch.borrow());@@ -124,7 +129,7 @@
ct_out.assert_noise(module, &sk_out_exec, &pt_want, max_noise + 0.5); } -pub(crate) fn test_keyswitch_inplace<B: Backend>( +pub fn test_glwe_keyswitch_inplace<B: Backend>( module: &Module<B>, basek: usize, k_ct: usize,@@ -133,13 +138,28 @@ digits: usize,
rank: usize, sigma: f64, ) where - Module<B>: KeySwitchTestModuleFamily<B>, - B: KeySwitchTestScratchFamily<B>, + Module<B>: GGLWESwitchingKeyEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + + GLWEKeyswitchFamily<B> + + GLWEDecryptFamily<B> + + VecZnxStd + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B>, { let n: usize = module.n(); let rows: usize = k_ct.div_ceil(basek * digits); - let mut ksk: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank, rank); + let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank, rank); let mut ct_glwe: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank); let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_ct);@@ -150,7 +170,7 @@
module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_ct, &mut source_xa); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, ksk.k(), rank, rank) + GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, ksk.k(), rank, rank) | GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, ct_glwe.k()) | GLWECiphertext::keyswitch_inplace_scratch_space(module, n, basek, ct_glwe.k(), ksk.k(), digits, rank), );@@ -183,7 +203,7 @@ sigma,
scratch.borrow(), ); - let ksk_exec: GLWESwitchingKeyExec<Vec<u8>, B> = GLWESwitchingKeyExec::from(module, &ksk, scratch.borrow()); + let ksk_exec: GGLWESwitchingKeyExec<Vec<u8>, B> = GGLWESwitchingKeyExec::from(module, &ksk, scratch.borrow()); ct_glwe.keyswitch_inplace(module, &ksk_exec, scratch.borrow());
@@ -1,15 +0,0 @@
-use backend::hal::tests::serialization::test_reader_writer_interface; - -use crate::{GLWECiphertext, GLWECiphertextCompressed}; - -#[test] -fn test_serialization() { - let original: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(1024, 12, 54, 3); - test_reader_writer_interface(original); -} - -#[test] -fn test_compressed_serialization() { - let original: GLWECiphertextCompressed<Vec<u8>> = GLWECiphertextCompressed::alloc(1024, 12, 54, 3); - test_reader_writer_interface(original); -}
@@ -1,8 +0,0 @@
-mod cpu_spqlios; -mod generic_automorphism; -mod generic_encryption; -mod generic_external_product; -mod generic_keyswitch; -mod generic_serialization; -mod packing; -mod trace;
@@ -3,7 +3,7 @@
use backend::hal::{ api::{ ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxBigSubSmallBInplace, - VecZnxEncodeVeci64, VecZnxRotateInplace, VecZnxStd, VecZnxSwithcDegree, + VecZnxEncodeVeci64, VecZnxRotateInplace, VecZnxStd, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, }, layouts::{Backend, Module, ScratchOwned}, oep::{@@ -14,25 +14,32 @@ };
use sampling::source::Source; use crate::{ - AutomorphismKey, AutomorphismKeyExec, GGLWEExecLayoutFamily, GLWECiphertext, GLWEDecryptFamily, GLWEKeyswitchFamily, GLWEOps, - GLWEPacker, GLWEPackingFamily, GLWEPlaintext, GLWESecret, GLWESecretExec, GLWESecretFamily, GLWESwitchingKeyEncryptSkFamily, + GLWEOperations, GLWEPacker, + layouts::{ + GGLWEAutomorphismKey, GLWECiphertext, GLWEPlaintext, GLWESecret, + prepared::{GGLWEAutomorphismKeyExec, GLWESecretExec}, + }, + trait_families::{GLWEDecryptFamily, GLWEKeyswitchFamily, GLWEPackingFamily}, }; -pub(crate) trait PackingTestModuleFamily<B: Backend> = GLWEPackingFamily<B> - + GLWESecretFamily<B> - + GLWESwitchingKeyEncryptSkFamily<B> +use crate::trait_families::{GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; + +pub trait PackingTestModuleFamily<B: Backend> = GLWEPackingFamily<B> + + GLWESecretExecModuleFamily<B> + + GGLWESwitchingKeyEncryptSkFamily<B> + GLWEKeyswitchFamily<B> + GLWEDecryptFamily<B> - + GGLWEExecLayoutFamily<B> + VecZnxStd + VecZnxSwithcDegree + VecZnxAddScalarInplace + VecZnxEncodeVeci64 + VecZnxRotateInplace + VecZnxAutomorphism - + VecZnxBigSubSmallBInplace<B>; + + VecZnxBigSubSmallBInplace<B> + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>; -pub(crate) trait PackingTestScratchFamily<B: Backend> = TakeVecZnxDftImpl<B> +pub trait PackingTestScratchFamily<B: Backend> = TakeVecZnxDftImpl<B> + TakeVecZnxBigImpl<B> + TakeSvpPPolImpl<B> + ScratchOwnedAllocImpl<B>@@ -41,7 +48,7 @@ + ScratchAvailableImpl<B>
+ TakeScalarZnxImpl<B> + TakeVecZnxImpl<B>; -pub(crate) fn test_packing<B: Backend>(module: &Module<B>) +pub fn test_glwe_packing<B: Backend>(module: &Module<B>) where Module<B>: PackingTestModuleFamily<B>, B: PackingTestScratchFamily<B>,@@ -63,7 +70,7 @@ let rows: usize = k_ct.div_ceil(basek * digits);
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k_ct) - | AutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank) + | GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank) | GLWEPacker::scratch_space(module, n, basek, k_ct, k_ksk, digits, rank), );@@ -81,8 +88,8 @@ module.encode_vec_i64(basek, &mut pt.data, 0, pt_k, &data, 32);
let gal_els: Vec<i64> = GLWEPacker::galois_elements(module); - let mut auto_keys: HashMap<i64, AutomorphismKeyExec<Vec<u8>, B>> = HashMap::new(); - let mut tmp: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); + let mut auto_keys: HashMap<i64, GGLWEAutomorphismKeyExec<Vec<u8>, B>> = HashMap::new(); + let mut tmp: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); gal_els.iter().for_each(|gal_el| { tmp.encrypt_sk( module,@@ -93,7 +100,7 @@ &mut source_xe,
sigma, scratch.borrow(), ); - let atk_exec: AutomorphismKeyExec<Vec<u8>, B> = AutomorphismKeyExec::from(module, &tmp, scratch.borrow()); + let atk_exec: GGLWEAutomorphismKeyExec<Vec<u8>, B> = GGLWEAutomorphismKeyExec::from(module, &tmp, scratch.borrow()); auto_keys.insert(*gal_el, atk_exec); });
@@ -4,7 +4,8 @@ use backend::hal::{
api::{ ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxBigAutomorphismInplace, VecZnxBigSubSmallBInplace, VecZnxCopy, VecZnxEncodeVeci64, VecZnxFillUniform, VecZnxNormalizeInplace, - VecZnxRotateInplace, VecZnxRshInplace, VecZnxStd, VecZnxSubABInplace, VecZnxSwithcDegree, ZnxView, ZnxViewMut, + VecZnxRotateInplace, VecZnxRshInplace, VecZnxStd, VecZnxSubABInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, + ZnxView, ZnxViewMut, }, layouts::{Backend, Module, ScratchOwned}, oep::{@@ -15,16 +16,20 @@ };
use sampling::source::Source; use crate::{ - AutomorphismKey, AutomorphismKeyExec, GGLWEExecLayoutFamily, GLWECiphertext, GLWEDecryptFamily, GLWEKeyswitchFamily, - GLWEPlaintext, GLWESecret, GLWESecretExec, GLWESecretFamily, GLWESwitchingKeyEncryptSkFamily, Infos, + layouts::{ + GGLWEAutomorphismKey, GLWECiphertext, GLWEPlaintext, GLWESecret, Infos, + prepared::{GGLWEAutomorphismKeyExec, GLWESecretExec}, + }, noise::var_noise_gglwe_product, + trait_families::{GLWEDecryptFamily, GLWEKeyswitchFamily}, }; -pub(crate) trait TraceTestModuleFamily<B: Backend> = GLWESecretFamily<B> - + GLWESwitchingKeyEncryptSkFamily<B> +use crate::trait_families::{GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; + +pub trait TraceTestModuleFamily<B: Backend> = GGLWESwitchingKeyEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + GLWEKeyswitchFamily<B> + GLWEDecryptFamily<B> - + GGLWEExecLayoutFamily<B> + VecZnxStd + VecZnxSwithcDegree + VecZnxAddScalarInplace@@ -34,9 +39,11 @@ + VecZnxBigSubSmallBInplace<B>
+ VecZnxBigAutomorphismInplace<B> + VecZnxCopy + VecZnxAutomorphism - + VecZnxRshInplace; + + VecZnxRshInplace + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>; -pub(crate) trait TraceTestScratchFamily<B: Backend> = TakeVecZnxDftImpl<B> +pub trait TraceTestScratchFamily<B: Backend> = TakeVecZnxDftImpl<B> + TakeVecZnxBigImpl<B> + TakeSvpPPolImpl<B> + ScratchOwnedAllocImpl<B>@@ -45,7 +52,7 @@ + ScratchAvailableImpl<B>
+ TakeScalarZnxImpl<B> + TakeVecZnxImpl<B>; -pub(crate) fn test_trace_inplace<B: Backend>(module: &Module<B>, basek: usize, k: usize, sigma: f64, rank: usize) +pub fn test_glwe_trace_inplace<B: Backend>(module: &Module<B>, basek: usize, k: usize, sigma: f64, rank: usize) where Module<B>: TraceTestModuleFamily<B>, B: TraceTestScratchFamily<B>,@@ -67,7 +74,7 @@
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, ct.k()) | GLWECiphertext::decrypt_scratch_space(module, n, basek, ct.k()) - | AutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_autokey, rank) + | GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_autokey, rank) | GLWECiphertext::trace_inplace_scratch_space(module, n, basek, ct.k(), k_autokey, digits, rank), );@@ -93,9 +100,9 @@ sigma,
scratch.borrow(), ); - let mut auto_keys: HashMap<i64, AutomorphismKeyExec<Vec<u8>, B>> = HashMap::new(); + let mut auto_keys: HashMap<i64, GGLWEAutomorphismKeyExec<Vec<u8>, B>> = HashMap::new(); let gal_els: Vec<i64> = GLWECiphertext::trace_galois_elements(module); - let mut tmp: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_autokey, rows, digits, rank); + let mut tmp: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_autokey, rows, digits, rank); gal_els.iter().for_each(|gal_el| { tmp.encrypt_sk( module,@@ -106,7 +113,7 @@ &mut source_xe,
sigma, scratch.borrow(), ); - let atk_exec: AutomorphismKeyExec<Vec<u8>, B> = AutomorphismKeyExec::from(module, &tmp, scratch.borrow()); + let atk_exec: GGLWEAutomorphismKeyExec<Vec<u8>, B> = GGLWEAutomorphismKeyExec::from(module, &tmp, scratch.borrow()); auto_keys.insert(*gal_el, atk_exec); });
@@ -1,13 +1,13 @@
use std::collections::HashMap; -use backend::hal::{ - api::{ScratchAvailable, TakeVecZnxDft, VecZnxBigAutomorphismInplace, VecZnxCopy, VecZnxRshInplace}, - layouts::{Backend, DataMut, DataRef, Module, Scratch}, +use backend::hal::layouts::{Backend, DataMut, DataRef, Module, Scratch}; + +use crate::{ + layouts::{GLWECiphertext, prepared::GGLWEAutomorphismKeyExec}, + operations::GLWEOperations, }; -use crate::{AutomorphismKeyExec, GLWECiphertext, GLWECiphertextToMut, GLWEKeyswitchFamily, GLWEOps, Infos, SetMetaData}; - -pub trait GLWETraceFamily<B: Backend> = GLWEKeyswitchFamily<B> + VecZnxCopy + VecZnxRshInplace + VecZnxBigAutomorphismInplace<B>; +use crate::trait_families::{GLWETraceModuleFamily, GLWETraceScratchFamily}; impl GLWECiphertext<Vec<u8>> { pub fn trace_galois_elements<B: Backend>(module: &Module<B>) -> Vec<i64> {@@ -33,7 +33,7 @@ digits: usize,
rank: usize, ) -> usize where - Module<B>: GLWEKeyswitchFamily<B>, + Module<B>: GLWETraceModuleFamily<B>, { Self::automorphism_inplace_scratch_space(module, n, basek, out_k.min(in_k), ksk_k, digits, rank) }@@ -48,27 +48,24 @@ digits: usize,
rank: usize, ) -> usize where - Module<B>: GLWEKeyswitchFamily<B>, + Module<B>: GLWETraceModuleFamily<B>, { Self::automorphism_inplace_scratch_space(module, n, basek, out_k, ksk_k, digits, rank) } } -impl<DataSelf: DataMut> GLWECiphertext<DataSelf> -where - GLWECiphertext<DataSelf>: GLWECiphertextToMut + Infos + SetMetaData, -{ +impl<DataSelf: DataMut> GLWECiphertext<DataSelf> { pub fn trace<DataLhs: DataRef, DataAK: DataRef, B: Backend>( &mut self, module: &Module<B>, start: usize, end: usize, lhs: &GLWECiphertext<DataLhs>, - auto_keys: &HashMap<i64, AutomorphismKeyExec<DataAK, B>>, + auto_keys: &HashMap<i64, GGLWEAutomorphismKeyExec<DataAK, B>>, scratch: &mut Scratch<B>, ) where - Module<B>: GLWETraceFamily<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable, + Module<B>: GLWETraceModuleFamily<B>, + Scratch<B>: GLWETraceScratchFamily<B>, { self.copy(module, lhs); self.trace_inplace(module, start, end, auto_keys, scratch);@@ -79,11 +76,11 @@ &mut self,
module: &Module<B>, start: usize, end: usize, - auto_keys: &HashMap<i64, AutomorphismKeyExec<DataAK, B>>, + auto_keys: &HashMap<i64, GGLWEAutomorphismKeyExec<DataAK, B>>, scratch: &mut Scratch<B>, ) where - Module<B>: GLWETraceFamily<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable, + Module<B>: GLWETraceModuleFamily<B>, + Scratch<B>: GLWETraceScratchFamily<B>, { (start..end).for_each(|i| { self.rsh(module, 1);
@@ -0,0 +1,68 @@
+use backend::hal::{ + api::{ScratchAvailable, TakeVecZnx, TakeVecZnxDft, ZnxView, ZnxViewMut, ZnxZero}, + layouts::{Backend, DataMut, DataRef, Module, Scratch}, +}; + +use crate::{ + TakeGLWECt, + layouts::{GLWECiphertext, Infos, LWECiphertext, prepared::LWESwitchingKeyExec}, +}; + +use crate::trait_families::GLWEKeyswitchFamily; + +impl LWECiphertext<Vec<u8>> { + pub fn keyswitch_scratch_space<B: Backend>( + module: &Module<B>, + n: usize, + basek: usize, + k_lwe_out: usize, + k_lwe_in: usize, + k_ksk: usize, + ) -> usize + where + Module<B>: GLWEKeyswitchFamily<B>, + { + GLWECiphertext::bytes_of(n, basek, k_lwe_out.max(k_lwe_in), 1) + + GLWECiphertext::keyswitch_inplace_scratch_space(module, n, basek, k_lwe_out, k_ksk, 1, 1) + } +} + +impl<DLwe: DataMut> LWECiphertext<DLwe> { + pub fn keyswitch<A, DKs, B: Backend>( + &mut self, + module: &Module<B>, + a: &LWECiphertext<A>, + ksk: &LWESwitchingKeyExec<DKs, B>, + scratch: &mut Scratch<B>, + ) where + A: DataRef, + DKs: DataRef, + Module<B>: GLWEKeyswitchFamily<B>, + Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + { + #[cfg(debug_assertions)] + { + assert!(self.n() <= module.n()); + assert!(a.n() <= module.n()); + assert_eq!(self.basek(), a.basek()); + } + + let max_k: usize = self.k().max(a.k()); + let basek: usize = self.basek(); + + let (mut glwe, scratch1) = scratch.take_glwe_ct(ksk.n(), basek, max_k, 1); + glwe.data.zero(); + + let n_lwe: usize = a.n(); + + (0..a.size()).for_each(|i| { + let data_lwe: &[i64] = a.data.at(0, i); + glwe.data.at_mut(0, i)[0] = data_lwe[0]; + glwe.data.at_mut(1, i)[..n_lwe].copy_from_slice(&data_lwe[1..]); + }); + + glwe.keyswitch_inplace(module, &ksk.0, scratch1); + + self.sample_extract(&glwe); + } +}
@@ -0,0 +1,4 @@
+mod gglwe_ct; +mod ggsw_ct; +mod glwe_ct; +mod lwe_ct;
@@ -0,0 +1,115 @@
+use backend::hal::{ + api::{FillUniform, Reset, VecZnxCopy, VecZnxFillUniform}, + layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, WriterTo}, +}; + +use crate::layouts::{GGLWEAutomorphismKey, Infos, compressed::GGLWESwitchingKeyCompressed}; +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use std::fmt; + +use crate::trait_families::Decompress; + +#[derive(PartialEq, Eq, Clone)] +pub struct GGLWEAutomorphismKeyCompressed<D: Data> { + pub(crate) key: GGLWESwitchingKeyCompressed<D>, + pub(crate) p: i64, +} + +impl<D: DataRef> fmt::Debug for GGLWEAutomorphismKeyCompressed<D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl<D: DataMut> FillUniform for GGLWEAutomorphismKeyCompressed<D> { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.key.fill_uniform(source); + } +} + +impl<D: DataMut> Reset for GGLWEAutomorphismKeyCompressed<D> +where + MatZnx<D>: Reset, +{ + fn reset(&mut self) { + self.key.reset(); + self.p = 0; + } +} + +impl<D: DataRef> fmt::Display for GGLWEAutomorphismKeyCompressed<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(AutomorphismKeyCompressed: p={}) {}", self.p, self.key) + } +} + +impl GGLWEAutomorphismKeyCompressed<Vec<u8>> { + pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self { + GGLWEAutomorphismKeyCompressed { + key: GGLWESwitchingKeyCompressed::alloc(n, basek, k, rows, digits, rank, rank), + p: 0, + } + } + + pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize { + GGLWESwitchingKeyCompressed::<Vec<u8>>::bytes_of(n, basek, k, rows, digits, rank) + } +} + +impl<D: Data> Infos for GGLWEAutomorphismKeyCompressed<D> { + type Inner = MatZnx<D>; + + fn inner(&self) -> &Self::Inner { + &self.key.inner() + } + + fn basek(&self) -> usize { + self.key.basek() + } + + fn k(&self) -> usize { + self.key.k() + } +} + +impl<D: Data> GGLWEAutomorphismKeyCompressed<D> { + pub fn rank(&self) -> usize { + self.key.rank() + } + + pub fn digits(&self) -> usize { + self.key.digits() + } + + pub fn rank_in(&self) -> usize { + self.key.rank_in() + } + + pub fn rank_out(&self) -> usize { + self.key.rank_out() + } +} + +impl<D: DataMut> ReaderFrom for GGLWEAutomorphismKeyCompressed<D> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + self.p = reader.read_u64::<LittleEndian>()? as i64; + self.key.read_from(reader) + } +} + +impl<D: DataRef> WriterTo for GGLWEAutomorphismKeyCompressed<D> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::<LittleEndian>(self.p as u64)?; + self.key.write_to(writer) + } +} + +impl<D: DataMut, DR: DataRef, B: Backend> Decompress<B, GGLWEAutomorphismKeyCompressed<DR>> for GGLWEAutomorphismKey<D> { + fn decompress(&mut self, module: &Module<B>, other: &GGLWEAutomorphismKeyCompressed<DR>) + where + Module<B>: VecZnxFillUniform + VecZnxCopy, + { + self.key.decompress(module, &other.key); + self.p = other.p; + } +}
@@ -0,0 +1,252 @@
+use backend::hal::{ + api::{FillUniform, Reset, VecZnxCopy, VecZnxFillUniform}, + layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, WriterTo}, +}; + +use crate::layouts::{GGLWECiphertext, Infos, compressed::GLWECiphertextCompressed}; +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use std::fmt; + +use crate::trait_families::Decompress; + +#[derive(PartialEq, Eq, Clone)] +pub struct GGLWECiphertextCompressed<D: Data> { + pub(crate) data: MatZnx<D>, + pub(crate) basek: usize, + pub(crate) k: usize, + pub(crate) rank_out: usize, + pub(crate) digits: usize, + pub(crate) seed: Vec<[u8; 32]>, +} + +impl<D: DataRef> fmt::Debug for GGLWECiphertextCompressed<D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl<D: DataMut> FillUniform for GGLWECiphertextCompressed<D> { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.data.fill_uniform(source); + } +} + +impl<D: DataMut> Reset for GGLWECiphertextCompressed<D> +where + MatZnx<D>: Reset, +{ + fn reset(&mut self) { + self.data.reset(); + self.basek = 0; + self.k = 0; + self.digits = 0; + self.rank_out = 0; + self.seed = Vec::new(); + } +} + +impl<D: DataRef> fmt::Display for GGLWECiphertextCompressed<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "(GGLWECiphertextCompressed: basek={} k={} digits={}) {}", + self.basek, self.k, self.digits, self.data + ) + } +} + +impl GGLWECiphertextCompressed<Vec<u8>> { + pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self { + let size: usize = k.div_ceil(basek); + debug_assert!( + size > digits, + "invalid gglwe: ceil(k/basek): {} <= digits: {}", + size, + digits + ); + + assert!( + rows * digits <= size, + "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}", + rows, + digits, + size + ); + + Self { + data: MatZnx::alloc(n, rows, rank_in, 1, size), + basek: basek, + k, + rank_out, + digits, + seed: vec![[0u8; 32]; rows * rank_in], + } + } + + pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize) -> usize { + let size: usize = k.div_ceil(basek); + debug_assert!( + size > digits, + "invalid gglwe: ceil(k/basek): {} <= digits: {}", + size, + digits + ); + + assert!( + rows * digits <= size, + "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}", + rows, + digits, + size + ); + + MatZnx::alloc_bytes(n, rows, rank_in, 1, rows) + } +} + +impl<D: Data> Infos for GGLWECiphertextCompressed<D> { + type Inner = MatZnx<D>; + + fn inner(&self) -> &Self::Inner { + &self.data + } + + fn basek(&self) -> usize { + self.basek + } + + fn k(&self) -> usize { + self.k + } +} + +impl<D: Data> GGLWECiphertextCompressed<D> { + pub fn rank(&self) -> usize { + self.rank_out + } + + pub fn digits(&self) -> usize { + self.digits + } + + pub fn rank_in(&self) -> usize { + self.data.cols_in() + } + + pub fn rank_out(&self) -> usize { + self.rank_out + } +} + +impl<D: DataRef> GGLWECiphertextCompressed<D> { + pub(crate) fn at(&self, row: usize, col: usize) -> GLWECiphertextCompressed<&[u8]> { + GLWECiphertextCompressed { + data: self.data.at(row, col), + basek: self.basek, + k: self.k, + rank: self.rank_out, + seed: self.seed[self.rank_in() * row + col], + } + } +} + +impl<D: DataMut> GGLWECiphertextCompressed<D> { + pub(crate) fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertextCompressed<&mut [u8]> { + let rank_in: usize = self.rank_in(); + GLWECiphertextCompressed { + data: self.data.at_mut(row, col), + basek: self.basek, + k: self.k, + rank: self.rank_out, + seed: self.seed[rank_in * row + col], // Warning: value is copied and not borrow mut + } + } +} + +impl<D: DataMut> ReaderFrom for GGLWECiphertextCompressed<D> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + self.k = reader.read_u64::<LittleEndian>()? as usize; + self.basek = reader.read_u64::<LittleEndian>()? as usize; + self.digits = reader.read_u64::<LittleEndian>()? as usize; + self.rank_out = reader.read_u64::<LittleEndian>()? as usize; + let seed_len = reader.read_u64::<LittleEndian>()? as usize; + self.seed = vec![[0u8; 32]; seed_len]; + for s in &mut self.seed { + reader.read_exact(s)?; + } + self.data.read_from(reader) + } +} + +impl<D: DataRef> WriterTo for GGLWECiphertextCompressed<D> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::<LittleEndian>(self.k as u64)?; + writer.write_u64::<LittleEndian>(self.basek as u64)?; + writer.write_u64::<LittleEndian>(self.digits as u64)?; + writer.write_u64::<LittleEndian>(self.rank_out as u64)?; + writer.write_u64::<LittleEndian>(self.seed.len() as u64)?; + for s in &self.seed { + writer.write_all(s)?; + } + self.data.write_to(writer) + } +} + +impl<D: DataMut, B: Backend, DR: DataRef> Decompress<B, GGLWECiphertextCompressed<DR>> for GGLWECiphertext<D> { + fn decompress(&mut self, module: &Module<B>, other: &GGLWECiphertextCompressed<DR>) + where + Module<B>: VecZnxFillUniform + VecZnxCopy, + { + #[cfg(debug_assertions)] + { + use backend::hal::api::ZnxInfos; + + assert_eq!( + self.n(), + other.data.n(), + "invalid receiver: self.n()={} != other.n()={}", + self.n(), + other.data.n() + ); + assert_eq!( + self.size(), + other.size(), + "invalid receiver: self.size()={} != other.size()={}", + self.size(), + other.size() + ); + assert_eq!( + self.rank_in(), + other.rank_in(), + "invalid receiver: self.rank_in()={} != other.rank_in()={}", + self.rank_in(), + other.rank_in() + ); + assert_eq!( + self.rank_out(), + other.rank_out(), + "invalid receiver: self.rank_out()={} != other.rank_out()={}", + self.rank_out(), + other.rank_out() + ); + + assert_eq!( + self.rows(), + other.rows(), + "invalid receiver: self.rows()={} != other.rows()={}", + self.rows(), + other.rows() + ); + } + + let rank_in: usize = self.rank_in(); + let rows: usize = self.rows(); + + (0..rank_in).for_each(|col_i| { + (0..rows).for_each(|row_i| { + self.at_mut(row_i, col_i) + .decompress(module, &other.at(row_i, col_i)); + }); + }); + } +}
@@ -0,0 +1,126 @@
+use backend::hal::{ + api::{FillUniform, Reset, VecZnxCopy, VecZnxFillUniform}, + layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, WriterTo}, +}; + +use crate::{ + layouts::{GGLWESwitchingKey, Infos, compressed::GGLWECiphertextCompressed}, + trait_families::Decompress, +}; +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use std::fmt; + +#[derive(PartialEq, Eq, Clone)] +pub struct GGLWESwitchingKeyCompressed<D: Data> { + pub(crate) key: GGLWECiphertextCompressed<D>, + pub(crate) sk_in_n: usize, // Degree of sk_in + pub(crate) sk_out_n: usize, // Degree of sk_out +} + +impl<D: DataRef> fmt::Debug for GGLWESwitchingKeyCompressed<D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl<D: DataMut> FillUniform for GGLWESwitchingKeyCompressed<D> { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.key.fill_uniform(source); + } +} + +impl<D: DataMut> Reset for GGLWESwitchingKeyCompressed<D> +where + MatZnx<D>: Reset, +{ + fn reset(&mut self) { + self.key.reset(); + self.sk_in_n = 0; + self.sk_out_n = 0; + } +} + +impl<D: DataRef> fmt::Display for GGLWESwitchingKeyCompressed<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "(GLWESwitchingKeyCompressed: sk_in_n={} sk_out_n={}) {}", + self.sk_in_n, self.sk_out_n, self.key.data + ) + } +} + +impl<D: Data> Infos for GGLWESwitchingKeyCompressed<D> { + type Inner = MatZnx<D>; + + fn inner(&self) -> &Self::Inner { + &self.key.inner() + } + + fn basek(&self) -> usize { + self.key.basek() + } + + fn k(&self) -> usize { + self.key.k() + } +} + +impl<D: Data> GGLWESwitchingKeyCompressed<D> { + pub fn rank(&self) -> usize { + self.key.rank() + } + + pub fn digits(&self) -> usize { + self.key.digits() + } + + pub fn rank_in(&self) -> usize { + self.key.rank_in() + } + + pub fn rank_out(&self) -> usize { + self.key.rank_out() + } +} + +impl GGLWESwitchingKeyCompressed<Vec<u8>> { + pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self { + GGLWESwitchingKeyCompressed { + key: GGLWECiphertextCompressed::alloc(n, basek, k, rows, digits, rank_in, rank_out), + sk_in_n: 0, + sk_out_n: 0, + } + } + + pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize) -> usize { + GGLWECiphertextCompressed::bytes_of(n, basek, k, rows, digits, rank_in) + } +} + +impl<D: DataMut> ReaderFrom for GGLWESwitchingKeyCompressed<D> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + self.sk_in_n = reader.read_u64::<LittleEndian>()? as usize; + self.sk_out_n = reader.read_u64::<LittleEndian>()? as usize; + self.key.read_from(reader) + } +} + +impl<D: DataRef> WriterTo for GGLWESwitchingKeyCompressed<D> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::<LittleEndian>(self.sk_in_n as u64)?; + writer.write_u64::<LittleEndian>(self.sk_out_n as u64)?; + self.key.write_to(writer) + } +} + +impl<D: DataMut, DR: DataRef, B: Backend> Decompress<B, GGLWESwitchingKeyCompressed<DR>> for GGLWESwitchingKey<D> { + fn decompress(&mut self, module: &Module<B>, other: &GGLWESwitchingKeyCompressed<DR>) + where + Module<B>: VecZnxFillUniform + VecZnxCopy, + { + self.key.decompress(module, &other.key); + self.sk_in_n = other.sk_in_n; + self.sk_out_n = other.sk_out_n; + } +}
@@ -0,0 +1,163 @@
+use backend::hal::{ + api::{FillUniform, Reset, VecZnxCopy, VecZnxFillUniform}, + layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, WriterTo}, +}; + +use crate::layouts::{GGLWETensorKey, Infos, compressed::GGLWESwitchingKeyCompressed}; +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use std::fmt; + +use crate::trait_families::Decompress; + +#[derive(PartialEq, Eq, Clone)] +pub struct GGLWETensorKeyCompressed<D: Data> { + pub(crate) keys: Vec<GGLWESwitchingKeyCompressed<D>>, +} + +impl<D: DataRef> fmt::Debug for GGLWETensorKeyCompressed<D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl<D: DataMut> FillUniform for GGLWETensorKeyCompressed<D> { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.keys + .iter_mut() + .for_each(|key: &mut GGLWESwitchingKeyCompressed<D>| key.fill_uniform(source)) + } +} + +impl<D: DataMut> Reset for GGLWETensorKeyCompressed<D> +where + MatZnx<D>: Reset, +{ + fn reset(&mut self) { + self.keys + .iter_mut() + .for_each(|key: &mut GGLWESwitchingKeyCompressed<D>| key.reset()) + } +} + +impl<D: DataRef> fmt::Display for GGLWETensorKeyCompressed<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "(GLWETensorKeyCompressed)",)?; + for (i, key) in self.keys.iter().enumerate() { + write!(f, "{}: {}", i, key)?; + } + Ok(()) + } +} + +impl GGLWETensorKeyCompressed<Vec<u8>> { + pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self { + let mut keys: Vec<GGLWESwitchingKeyCompressed<Vec<u8>>> = Vec::new(); + let pairs: usize = (((rank + 1) * rank) >> 1).max(1); + (0..pairs).for_each(|_| { + keys.push(GGLWESwitchingKeyCompressed::alloc( + n, basek, k, rows, digits, 1, rank, + )); + }); + Self { keys: keys } + } + + pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize { + let pairs: usize = (((rank + 1) * rank) >> 1).max(1); + pairs * GGLWESwitchingKeyCompressed::bytes_of(n, basek, k, rows, digits, 1) + } +} + +impl<D: Data> Infos for GGLWETensorKeyCompressed<D> { + type Inner = MatZnx<D>; + + fn inner(&self) -> &Self::Inner { + &self.keys[0].inner() + } + + fn basek(&self) -> usize { + self.keys[0].basek() + } + + fn k(&self) -> usize { + self.keys[0].k() + } +} + +impl<D: Data> GGLWETensorKeyCompressed<D> { + pub fn rank(&self) -> usize { + self.keys[0].rank() + } + + pub fn digits(&self) -> usize { + self.keys[0].digits() + } + + pub fn rank_in(&self) -> usize { + self.keys[0].rank_in() + } + + pub fn rank_out(&self) -> usize { + self.keys[0].rank_out() + } +} + +impl<D: DataMut> ReaderFrom for GGLWETensorKeyCompressed<D> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + let len: usize = reader.read_u64::<LittleEndian>()? as usize; + if self.keys.len() != len { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + format!("self.keys.len()={} != read len={}", self.keys.len(), len), + )); + } + for key in &mut self.keys { + key.read_from(reader)?; + } + Ok(()) + } +} + +impl<D: DataRef> WriterTo for GGLWETensorKeyCompressed<D> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::<LittleEndian>(self.keys.len() as u64)?; + for key in &self.keys { + key.write_to(writer)?; + } + Ok(()) + } +} + +impl<D: DataMut> GGLWETensorKeyCompressed<D> { + pub(crate) fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWESwitchingKeyCompressed<D> { + if i > j { + std::mem::swap(&mut i, &mut j); + }; + let rank: usize = self.rank(); + &mut self.keys[i * rank + j - (i * (i + 1) / 2)] + } +} + +impl<D: DataMut, DR: DataRef, B: Backend> Decompress<B, GGLWETensorKeyCompressed<DR>> for GGLWETensorKey<D> { + fn decompress(&mut self, module: &Module<B>, other: &GGLWETensorKeyCompressed<DR>) + where + Module<B>: VecZnxFillUniform + VecZnxCopy, + { + #[cfg(debug_assertions)] + { + assert_eq!( + self.keys.len(), + other.keys.len(), + "invalid receiver: self.keys.len()={} != other.keys.len()={}", + self.keys.len(), + other.keys.len() + ); + } + + self.keys + .iter_mut() + .zip(other.keys.iter()) + .for_each(|(a, b)| { + a.decompress(module, b); + }); + } +}
@@ -0,0 +1,177 @@
+use backend::hal::{ + api::{FillUniform, Reset, VecZnxCopy, VecZnxFillUniform, ZnxInfos}, + layouts::{Backend, Data, DataMut, DataRef, Module, ReaderFrom, VecZnx, WriterTo}, +}; +use sampling::source::Source; + +use crate::{ + layouts::{GLWECiphertext, Infos}, + trait_families::{Decompress, DecompressFamily}, +}; +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use std::fmt; + +#[derive(PartialEq, Eq, Clone)] +pub struct GLWECiphertextCompressed<D: Data> { + pub(crate) data: VecZnx<D>, + pub(crate) basek: usize, + pub(crate) k: usize, + pub(crate) rank: usize, + pub(crate) seed: [u8; 32], +} + +impl<D: DataRef> fmt::Debug for GLWECiphertextCompressed<D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl<D: DataRef> fmt::Display for GLWECiphertextCompressed<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "GLWECiphertextCompressed: basek={} k={} rank={} seed={:?}: {}", + self.basek(), + self.k(), + self.rank, + self.seed, + self.data + ) + } +} + +impl<D: DataMut> Reset for GLWECiphertextCompressed<D> { + fn reset(&mut self) { + self.data.reset(); + self.basek = 0; + self.k = 0; + self.rank = 0; + self.seed = [0u8; 32]; + } +} + +impl<D: DataMut> FillUniform for GLWECiphertextCompressed<D> { + fn fill_uniform(&mut self, source: &mut Source) { + self.data.fill_uniform(source); + } +} + +impl<D: Data> Infos for GLWECiphertextCompressed<D> { + type Inner = VecZnx<D>; + + fn inner(&self) -> &Self::Inner { + &self.data + } + + fn basek(&self) -> usize { + self.basek + } + + fn k(&self) -> usize { + self.k + } +} + +impl<D: Data> GLWECiphertextCompressed<D> { + pub fn rank(&self) -> usize { + self.rank + } +} + +impl GLWECiphertextCompressed<Vec<u8>> { + pub fn alloc(n: usize, basek: usize, k: usize, rank: usize) -> Self { + Self { + data: VecZnx::alloc(n, 1, k.div_ceil(basek)), + basek, + k, + rank, + seed: [0u8; 32], + } + } + + pub fn bytes_of(n: usize, basek: usize, k: usize) -> usize { + GLWECiphertext::bytes_of(n, basek, k, 1) + } +} + +impl<D: DataMut> ReaderFrom for GLWECiphertextCompressed<D> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + self.k = reader.read_u64::<LittleEndian>()? as usize; + self.basek = reader.read_u64::<LittleEndian>()? as usize; + self.rank = reader.read_u64::<LittleEndian>()? as usize; + reader.read(&mut self.seed)?; + self.data.read_from(reader) + } +} + +impl<D: DataRef> WriterTo for GLWECiphertextCompressed<D> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::<LittleEndian>(self.k as u64)?; + writer.write_u64::<LittleEndian>(self.basek as u64)?; + writer.write_u64::<LittleEndian>(self.rank as u64)?; + writer.write_all(&self.seed)?; + self.data.write_to(writer) + } +} + +impl<D: DataMut, B: Backend, DR: DataRef> Decompress<B, GLWECiphertextCompressed<DR>> for GLWECiphertext<D> { + fn decompress(&mut self, module: &Module<B>, other: &GLWECiphertextCompressed<DR>) + where + Module<B>: DecompressFamily<B>, + { + #[cfg(debug_assertions)] + { + assert_eq!( + self.n(), + other.data.n(), + "invalid receiver: self.n()={} != other.n()={}", + self.n(), + other.data.n() + ); + assert_eq!( + self.size(), + other.size(), + "invalid receiver: self.size()={} != other.size()={}", + self.size(), + other.size() + ); + assert_eq!( + self.rank(), + other.rank(), + "invalid receiver: self.rank()={} != other.rank()={}", + self.rank(), + other.rank() + ); + let mut source: Source = Source::new(other.seed); + self.decompress_internal(module, other, &mut source); + } + } +} + +impl<D: DataMut> GLWECiphertext<D> { + pub(crate) fn decompress_internal<DataOther, B: Backend>( + &mut self, + module: &Module<B>, + other: &GLWECiphertextCompressed<DataOther>, + source: &mut Source, + ) where + DataOther: DataRef, + Module<B>: DecompressFamily<B>, + { + #[cfg(debug_assertions)] + { + assert_eq!(self.rank(), other.rank()) + } + + let k: usize = other.k; + let basek: usize = other.basek; + let cols: usize = other.rank() + 1; + module.vec_znx_copy(&mut self.data, 0, &other.data, 0); + (1..cols).for_each(|i| { + module.vec_znx_fill_uniform(basek, &mut self.data, i, k, source); + }); + + self.basek = basek; + self.k = k; + } +}
@@ -0,0 +1,98 @@
+use std::fmt; + +use backend::hal::{ + api::{FillUniform, Reset}, + layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, WriterTo}, +}; + +use crate::layouts::{GLWEToLWESwitchingKey, Infos, compressed::GGLWESwitchingKeyCompressed}; + +use crate::trait_families::{GGLWEEncryptSkFamily, GLWESecretExecModuleFamily}; + +#[derive(PartialEq, Eq, Clone)] +pub struct GLWEToLWESwitchingKeyCompressed<D: Data>(pub(crate) GGLWESwitchingKeyCompressed<D>); + +impl<D: DataRef> fmt::Debug for GLWEToLWESwitchingKeyCompressed<D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl<D: DataMut> FillUniform for GLWEToLWESwitchingKeyCompressed<D> { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.0.fill_uniform(source); + } +} + +impl<D: DataMut> Reset for GLWEToLWESwitchingKeyCompressed<D> { + fn reset(&mut self) { + self.0.reset(); + } +} + +impl<D: DataRef> fmt::Display for GLWEToLWESwitchingKeyCompressed<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(GLWEToLWESwitchingKeyCompressed) {}", self.0) + } +} + +impl<D: Data> Infos for GLWEToLWESwitchingKeyCompressed<D> { + type Inner = MatZnx<D>; + + fn inner(&self) -> &Self::Inner { + &self.0.inner() + } + + fn basek(&self) -> usize { + self.0.basek() + } + + fn k(&self) -> usize { + self.0.k() + } +} + +impl<D: Data> GLWEToLWESwitchingKeyCompressed<D> { + pub fn digits(&self) -> usize { + self.0.digits() + } + + pub fn rank(&self) -> usize { + self.0.rank() + } + + pub fn rank_in(&self) -> usize { + self.0.rank_in() + } + + pub fn rank_out(&self) -> usize { + self.0.rank_out() + } +} + +impl<D: DataMut> ReaderFrom for GLWEToLWESwitchingKeyCompressed<D> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + self.0.read_from(reader) + } +} + +impl<D: DataRef> WriterTo for GLWEToLWESwitchingKeyCompressed<D> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + self.0.write_to(writer) + } +} + +impl GLWEToLWESwitchingKeyCompressed<Vec<u8>> { + pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, rank_in: usize) -> Self { + Self(GGLWESwitchingKeyCompressed::alloc( + n, basek, k, rows, 1, rank_in, 1, + )) + } + + pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank_in: usize) -> usize + where + Module<B>: GGLWEEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + { + GLWEToLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank_in) + } +}
@@ -0,0 +1,134 @@
+use std::fmt; + +use backend::hal::{ + api::{FillUniform, Reset, VecZnxFillUniform, ZnxInfos, ZnxView, ZnxViewMut}, + layouts::{Backend, Data, DataMut, DataRef, Module, ReaderFrom, VecZnx, WriterTo}, +}; +use sampling::source::Source; + +use crate::{ + layouts::{Infos, LWECiphertext, SetMetaData}, + trait_families::Decompress, +}; + +#[derive(PartialEq, Eq, Clone)] +pub struct LWECiphertextCompressed<D: Data> { + pub(crate) data: VecZnx<D>, + pub(crate) k: usize, + pub(crate) basek: usize, + pub(crate) seed: [u8; 32], +} + +impl<D: DataRef> fmt::Debug for LWECiphertextCompressed<D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl<D: DataRef> fmt::Display for LWECiphertextCompressed<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "LWECiphertextCompressed: basek={} k={} seed={:?}: {}", + self.basek(), + self.k(), + self.seed, + self.data + ) + } +} + +impl<D: DataMut> Reset for LWECiphertextCompressed<D> +where + VecZnx<D>: Reset, +{ + fn reset(&mut self) { + self.data.reset(); + self.basek = 0; + self.k = 0; + self.seed = [0u8; 32]; + } +} + +impl<D: DataMut> FillUniform for LWECiphertextCompressed<D> { + fn fill_uniform(&mut self, source: &mut Source) { + self.data.fill_uniform(source); + } +} + +impl LWECiphertextCompressed<Vec<u8>> { + pub fn alloc(basek: usize, k: usize) -> Self { + Self { + data: VecZnx::alloc(1, 1, k.div_ceil(basek)), + k: k, + basek: basek, + seed: [0u8; 32], + } + } +} + +impl<D: Data> Infos for LWECiphertextCompressed<D> +where + VecZnx<D>: ZnxInfos, +{ + type Inner = VecZnx<D>; + + fn n(&self) -> usize { + &self.inner().n() - 1 + } + + fn inner(&self) -> &Self::Inner { + &self.data + } + + fn basek(&self) -> usize { + self.basek + } + + fn k(&self) -> usize { + self.k + } +} + +impl<DataSelf: DataMut> SetMetaData for LWECiphertextCompressed<DataSelf> { + fn set_k(&mut self, k: usize) { + self.k = k + } + + fn set_basek(&mut self, basek: usize) { + self.basek = basek + } +} + +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; + +impl<D: DataMut> ReaderFrom for LWECiphertextCompressed<D> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + self.k = reader.read_u64::<LittleEndian>()? as usize; + self.basek = reader.read_u64::<LittleEndian>()? as usize; + reader.read(&mut self.seed)?; + self.data.read_from(reader) + } +} + +impl<D: DataRef> WriterTo for LWECiphertextCompressed<D> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::<LittleEndian>(self.k as u64)?; + writer.write_u64::<LittleEndian>(self.basek as u64)?; + writer.write_all(&self.seed)?; + self.data.write_to(writer) + } +} + +impl<D: DataMut, B: Backend, DR: DataRef> Decompress<B, LWECiphertextCompressed<DR>> for LWECiphertext<D> { + fn decompress(&mut self, module: &Module<B>, other: &LWECiphertextCompressed<DR>) + where + Module<B>: VecZnxFillUniform, + { + let mut source = Source::new(other.seed); + module.vec_znx_fill_uniform(other.basek(), &mut self.data, 0, other.k(), &mut source); + (0..self.size()).for_each(|i| { + self.data.at_mut(0, i)[0] = other.data.at(0, i)[0]; + }); + } +}
@@ -0,0 +1,106 @@
+use backend::hal::{ + api::{FillUniform, Reset}, + layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, WriterTo}, +}; + +use crate::layouts::{Infos, LWESwitchingKey, compressed::GGLWESwitchingKeyCompressed}; +use std::fmt; + +use crate::trait_families::{Decompress, GGLWEEncryptSkFamily, GLWESecretExecModuleFamily}; + +#[derive(PartialEq, Eq, Clone)] +pub struct LWESwitchingKeyCompressed<D: Data>(pub(crate) GGLWESwitchingKeyCompressed<D>); + +impl<D: DataRef> fmt::Debug for LWESwitchingKeyCompressed<D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl<D: DataMut> FillUniform for LWESwitchingKeyCompressed<D> { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.0.fill_uniform(source); + } +} + +impl<D: DataMut> Reset for LWESwitchingKeyCompressed<D> { + fn reset(&mut self) { + self.0.reset(); + } +} + +impl<D: DataRef> fmt::Display for LWESwitchingKeyCompressed<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(LWESwitchingKeyCompressed) {}", self.0) + } +} + +impl<D: Data> Infos for LWESwitchingKeyCompressed<D> { + type Inner = MatZnx<D>; + + fn inner(&self) -> &Self::Inner { + &self.0.inner() + } + + fn basek(&self) -> usize { + self.0.basek() + } + + fn k(&self) -> usize { + self.0.k() + } +} + +impl<D: Data> LWESwitchingKeyCompressed<D> { + pub fn digits(&self) -> usize { + self.0.digits() + } + + pub fn rank(&self) -> usize { + self.0.rank() + } + + pub fn rank_in(&self) -> usize { + self.0.rank_in() + } + + pub fn rank_out(&self) -> usize { + self.0.rank_out() + } +} + +impl<D: DataMut> ReaderFrom for LWESwitchingKeyCompressed<D> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + self.0.read_from(reader) + } +} + +impl<D: DataRef> WriterTo for LWESwitchingKeyCompressed<D> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + self.0.write_to(writer) + } +} + +impl LWESwitchingKeyCompressed<Vec<u8>> { + pub fn alloc(n: usize, basek: usize, k: usize, rows: usize) -> Self { + Self(GGLWESwitchingKeyCompressed::alloc( + n, basek, k, rows, 1, 1, 1, + )) + } + + pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize) -> usize + where + Module<B>: GGLWEEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + { + LWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k) + } +} + +impl<D: DataMut, DR: DataRef, B: Backend> Decompress<B, LWESwitchingKeyCompressed<DR>> for LWESwitchingKey<D> { + fn decompress(&mut self, module: &Module<B>, other: &LWESwitchingKeyCompressed<DR>) + where + Module<B>: crate::trait_families::DecompressFamily<B>, + { + self.0.decompress(module, &other.0); + } +}
@@ -0,0 +1,109 @@
+use backend::hal::{ + api::{FillUniform, Reset}, + layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, WriterTo}, +}; + +use crate::{ + layouts::{Infos, LWEToGLWESwitchingKey, compressed::GGLWESwitchingKeyCompressed}, + trait_families::Decompress, +}; +use std::fmt; + +use crate::trait_families::{GGLWEEncryptSkFamily, GLWESecretExecModuleFamily}; + +#[derive(PartialEq, Eq, Clone)] +pub struct LWEToGLWESwitchingKeyCompressed<D: Data>(pub(crate) GGLWESwitchingKeyCompressed<D>); + +impl<D: DataRef> fmt::Debug for LWEToGLWESwitchingKeyCompressed<D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl<D: DataMut> FillUniform for LWEToGLWESwitchingKeyCompressed<D> { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.0.fill_uniform(source); + } +} + +impl<D: DataMut> Reset for LWEToGLWESwitchingKeyCompressed<D> { + fn reset(&mut self) { + self.0.reset(); + } +} + +impl<D: DataRef> fmt::Display for LWEToGLWESwitchingKeyCompressed<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(LWEToGLWESwitchingKeyCompressed) {}", self.0) + } +} + +impl<D: Data> Infos for LWEToGLWESwitchingKeyCompressed<D> { + type Inner = MatZnx<D>; + + fn inner(&self) -> &Self::Inner { + &self.0.inner() + } + + fn basek(&self) -> usize { + self.0.basek() + } + + fn k(&self) -> usize { + self.0.k() + } +} + +impl<D: Data> LWEToGLWESwitchingKeyCompressed<D> { + pub fn digits(&self) -> usize { + self.0.digits() + } + + pub fn rank(&self) -> usize { + self.0.rank() + } + + pub fn rank_in(&self) -> usize { + self.0.rank_in() + } + + pub fn rank_out(&self) -> usize { + self.0.rank_out() + } +} + +impl<D: DataMut> ReaderFrom for LWEToGLWESwitchingKeyCompressed<D> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + self.0.read_from(reader) + } +} + +impl<D: DataRef> WriterTo for LWEToGLWESwitchingKeyCompressed<D> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + self.0.write_to(writer) + } +} + +impl LWEToGLWESwitchingKeyCompressed<Vec<u8>> { + pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, rank_out: usize) -> Self { + Self(GGLWESwitchingKeyCompressed::alloc( + n, basek, k, rows, 1, 1, rank_out, + )) + } + + pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank_out: usize) -> usize + where + Module<B>: GGLWEEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + { + LWEToGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank_out) + } +} + +impl<D: DataMut, DR: DataRef, B: Backend> Decompress<B, LWEToGLWESwitchingKeyCompressed<DR>> for LWEToGLWESwitchingKey<D> { + fn decompress(&mut self, module: &Module<B>, other: &LWEToGLWESwitchingKeyCompressed<DR>) + where + Module<B>: crate::trait_families::DecompressFamily<B>, + { + self.0.decompress(module, &other.0); + } +}
@@ -0,0 +1,21 @@
+mod gglwe_atk; +mod gglwe_ct; +mod gglwe_ksk; +mod gglwe_tsk; +mod ggsw_ct; +mod glwe_ct; +mod glwe_to_lwe_ksk; +mod lwe_ct; +mod lwe_ksk; +mod lwe_to_glwe_ksk; + +pub use gglwe_atk::*; +pub use gglwe_ct::*; +pub use gglwe_ksk::*; +pub use gglwe_tsk::*; +pub use ggsw_ct::*; +pub use glwe_ct::*; +pub use glwe_to_lwe_ksk::*; +pub use lwe_ct::*; +pub use lwe_ksk::*; +pub use lwe_to_glwe_ksk::*;
@@ -0,0 +1,120 @@
+use backend::hal::{ + api::{FillUniform, Reset}, + layouts::{Data, DataMut, DataRef, MatZnx, ReaderFrom, WriterTo}, +}; + +use crate::layouts::{GLWECiphertext, GGLWESwitchingKey, Infos}; +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; + +use std::fmt; + +#[derive(PartialEq, Eq, Clone)] +pub struct GGLWEAutomorphismKey<D: Data> { + pub(crate) key: GGLWESwitchingKey<D>, + pub(crate) p: i64, +} + +impl<D: DataRef> fmt::Debug for GGLWEAutomorphismKey<D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl<D: DataMut> FillUniform for GGLWEAutomorphismKey<D> { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.key.fill_uniform(source); + } +} + +impl<D: DataMut> Reset for GGLWEAutomorphismKey<D> +where + MatZnx<D>: Reset, +{ + fn reset(&mut self) { + self.key.reset(); + self.p = 0; + } +} + +impl<D: DataRef> fmt::Display for GGLWEAutomorphismKey<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(AutomorphismKey: p={}) {}", self.p, self.key) + } +} + +impl GGLWEAutomorphismKey<Vec<u8>> { + pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self { + GGLWEAutomorphismKey { + key: GGLWESwitchingKey::alloc(n, basek, k, rows, digits, rank, rank), + p: 0, + } + } + + pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize { + GGLWESwitchingKey::bytes_of(n, basek, k, rows, digits, rank, rank) + } +} + +impl<D: Data> Infos for GGLWEAutomorphismKey<D> { + type Inner = MatZnx<D>; + + fn inner(&self) -> &Self::Inner { + &self.key.inner() + } + + fn basek(&self) -> usize { + self.key.basek() + } + + fn k(&self) -> usize { + self.key.k() + } +} + +impl<D: Data> GGLWEAutomorphismKey<D> { + pub fn p(&self) -> i64 { + self.p + } + + pub fn digits(&self) -> usize { + self.key.digits() + } + + pub fn rank(&self) -> usize { + self.key.rank() + } + + pub fn rank_in(&self) -> usize { + self.key.rank_in() + } + + pub fn rank_out(&self) -> usize { + self.key.rank_out() + } +} + +impl<D: DataRef> GGLWEAutomorphismKey<D> { + pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> { + self.key.at(row, col) + } +} + +impl<D: DataMut> GGLWEAutomorphismKey<D> { + pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> { + self.key.at_mut(row, col) + } +} + +impl<D: DataMut> ReaderFrom for GGLWEAutomorphismKey<D> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + self.p = reader.read_u64::<LittleEndian>()? as i64; + self.key.read_from(reader) + } +} + +impl<D: DataRef> WriterTo for GGLWEAutomorphismKey<D> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::<LittleEndian>(self.p as u64)?; + self.key.write_to(writer) + } +}
@@ -0,0 +1,167 @@
+use backend::hal::{ + api::{FillUniform, Reset}, + layouts::{Data, DataMut, DataRef, MatZnx, ReaderFrom, WriterTo}, +}; + +use crate::layouts::{GLWECiphertext, Infos}; +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; + +use std::fmt; + +#[derive(PartialEq, Eq, Clone)] +pub struct GGLWECiphertext<D: Data> { + pub(crate) data: MatZnx<D>, + pub(crate) basek: usize, + pub(crate) k: usize, + pub(crate) digits: usize, +} + +impl<D: DataRef> fmt::Debug for GGLWECiphertext<D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl<D: DataMut> FillUniform for GGLWECiphertext<D> { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.data.fill_uniform(source); + } +} + +impl<D: DataMut> Reset for GGLWECiphertext<D> { + fn reset(&mut self) { + self.data.reset(); + self.basek = 0; + self.k = 0; + self.digits = 0; + } +} + +impl<D: DataRef> fmt::Display for GGLWECiphertext<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "(GGLWECiphertext: basek={} k={} digits={}) {}", + self.basek, self.k, self.digits, self.data + ) + } +} + +impl<D: DataRef> GGLWECiphertext<D> { + pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> { + GLWECiphertext { + data: self.data.at(row, col), + basek: self.basek, + k: self.k, + } + } +} + +impl<D: DataMut> GGLWECiphertext<D> { + pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> { + GLWECiphertext { + data: self.data.at_mut(row, col), + basek: self.basek, + k: self.k, + } + } +} + +impl GGLWECiphertext<Vec<u8>> { + pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self { + let size: usize = k.div_ceil(basek); + debug_assert!( + size > digits, + "invalid gglwe: ceil(k/basek): {} <= digits: {}", + size, + digits + ); + + assert!( + rows * digits <= size, + "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}", + rows, + digits, + size + ); + + Self { + data: MatZnx::alloc(n, rows, rank_in, rank_out + 1, size), + basek: basek, + k, + digits, + } + } + + pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> usize { + let size: usize = k.div_ceil(basek); + debug_assert!( + size > digits, + "invalid gglwe: ceil(k/basek): {} <= digits: {}", + size, + digits + ); + + assert!( + rows * digits <= size, + "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}", + rows, + digits, + size + ); + + MatZnx::alloc_bytes(n, rows, rank_in, rank_out + 1, rows) + } +} + +impl<D: Data> Infos for GGLWECiphertext<D> { + type Inner = MatZnx<D>; + + fn inner(&self) -> &Self::Inner { + &self.data + } + + fn basek(&self) -> usize { + self.basek + } + + fn k(&self) -> usize { + self.k + } +} + +impl<D: Data> GGLWECiphertext<D> { + pub fn rank(&self) -> usize { + self.data.cols_out() - 1 + } + + pub fn digits(&self) -> usize { + self.digits + } + + pub fn rank_in(&self) -> usize { + self.data.cols_in() + } + + pub fn rank_out(&self) -> usize { + self.data.cols_out() - 1 + } +} + +impl<D: DataMut> ReaderFrom for GGLWECiphertext<D> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + self.k = reader.read_u64::<LittleEndian>()? as usize; + self.basek = reader.read_u64::<LittleEndian>()? as usize; + self.digits = reader.read_u64::<LittleEndian>()? as usize; + self.data.read_from(reader) + } +} + +impl<D: DataRef> WriterTo for GGLWECiphertext<D> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::<LittleEndian>(self.k as u64)?; + writer.write_u64::<LittleEndian>(self.basek as u64)?; + writer.write_u64::<LittleEndian>(self.digits as u64)?; + self.data.write_to(writer) + } +}
@@ -0,0 +1,133 @@
+use backend::hal::{ + api::{FillUniform, Reset}, + layouts::{Data, DataMut, DataRef, MatZnx, ReaderFrom, WriterTo}, +}; + +use crate::layouts::{GGLWECiphertext, GLWECiphertext, Infos}; +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; + +use std::fmt; + +#[derive(PartialEq, Eq, Clone)] +pub struct GGLWESwitchingKey<D: Data> { + pub(crate) key: GGLWECiphertext<D>, + pub(crate) sk_in_n: usize, // Degree of sk_in + pub(crate) sk_out_n: usize, // Degree of sk_out +} + +impl<D: DataRef> fmt::Debug for GGLWESwitchingKey<D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl<D: DataRef> fmt::Display for GGLWESwitchingKey<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "(GLWESwitchingKey: sk_in_n={} sk_out_n={}) {}", + self.sk_in_n, self.sk_out_n, self.key.data + ) + } +} + +impl<D: DataMut> FillUniform for GGLWESwitchingKey<D> { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.key.fill_uniform(source); + } +} + +impl<D: DataMut> Reset for GGLWESwitchingKey<D> +where + MatZnx<D>: Reset, +{ + fn reset(&mut self) { + self.key.reset(); + self.sk_in_n = 0; + self.sk_out_n = 0; + } +} + +impl GGLWESwitchingKey<Vec<u8>> { + pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self { + GGLWESwitchingKey { + key: GGLWECiphertext::alloc(n, basek, k, rows, digits, rank_in, rank_out), + sk_in_n: 0, + sk_out_n: 0, + } + } + + pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> usize { + GGLWECiphertext::<Vec<u8>>::bytes_of(n, basek, k, rows, digits, rank_in, rank_out) + } +} + +impl<D: Data> Infos for GGLWESwitchingKey<D> { + type Inner = MatZnx<D>; + + fn inner(&self) -> &Self::Inner { + self.key.inner() + } + + fn basek(&self) -> usize { + self.key.basek() + } + + fn k(&self) -> usize { + self.key.k() + } +} + +impl<D: Data> GGLWESwitchingKey<D> { + pub fn rank(&self) -> usize { + self.key.data.cols_out() - 1 + } + + pub fn rank_in(&self) -> usize { + self.key.data.cols_in() + } + + pub fn rank_out(&self) -> usize { + self.key.data.cols_out() - 1 + } + + pub fn digits(&self) -> usize { + self.key.digits() + } + + pub fn sk_degree_in(&self) -> usize { + self.sk_in_n + } + + pub fn sk_degree_out(&self) -> usize { + self.sk_out_n + } +} + +impl<D: DataRef> GGLWESwitchingKey<D> { + pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> { + self.key.at(row, col) + } +} + +impl<D: DataMut> GGLWESwitchingKey<D> { + pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> { + self.key.at_mut(row, col) + } +} + +impl<D: DataMut> ReaderFrom for GGLWESwitchingKey<D> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + self.sk_in_n = reader.read_u64::<LittleEndian>()? as usize; + self.sk_out_n = reader.read_u64::<LittleEndian>()? as usize; + self.key.read_from(reader) + } +} + +impl<D: DataRef> WriterTo for GGLWESwitchingKey<D> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::<LittleEndian>(self.sk_in_n as u64)?; + writer.write_u64::<LittleEndian>(self.sk_out_n as u64)?; + self.key.write_to(writer) + } +}
@@ -0,0 +1,147 @@
+use backend::hal::{ + api::{FillUniform, Reset}, + layouts::{Data, DataMut, DataRef, MatZnx, ReaderFrom, WriterTo}, +}; + +use crate::layouts::{GGLWESwitchingKey, Infos}; +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; + +use std::fmt; + +#[derive(PartialEq, Eq, Clone)] +pub struct GGLWETensorKey<D: Data> { + pub(crate) keys: Vec<GGLWESwitchingKey<D>>, +} + +impl<D: DataRef> fmt::Debug for GGLWETensorKey<D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl<D: DataMut> FillUniform for GGLWETensorKey<D> { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.keys + .iter_mut() + .for_each(|key: &mut GGLWESwitchingKey<D>| key.fill_uniform(source)) + } +} + +impl<D: DataMut> Reset for GGLWETensorKey<D> +where + MatZnx<D>: Reset, +{ + fn reset(&mut self) { + self.keys + .iter_mut() + .for_each(|key: &mut GGLWESwitchingKey<D>| key.reset()) + } +} + +impl<D: DataRef> fmt::Display for GGLWETensorKey<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "(GLWETensorKey)",)?; + for (i, key) in self.keys.iter().enumerate() { + write!(f, "{}: {}", i, key)?; + } + Ok(()) + } +} + +impl GGLWETensorKey<Vec<u8>> { + pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self { + let mut keys: Vec<GGLWESwitchingKey<Vec<u8>>> = Vec::new(); + let pairs: usize = (((rank + 1) * rank) >> 1).max(1); + (0..pairs).for_each(|_| { + keys.push(GGLWESwitchingKey::alloc(n, basek, k, rows, digits, 1, rank)); + }); + Self { keys: keys } + } + + pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize { + let pairs: usize = (((rank + 1) * rank) >> 1).max(1); + pairs * GGLWESwitchingKey::<Vec<u8>>::bytes_of(n, basek, k, rows, digits, 1, rank) + } +} + +impl<D: Data> Infos for GGLWETensorKey<D> { + type Inner = MatZnx<D>; + + fn inner(&self) -> &Self::Inner { + &self.keys[0].inner() + } + + fn basek(&self) -> usize { + self.keys[0].basek() + } + + fn k(&self) -> usize { + self.keys[0].k() + } +} + +impl<D: Data> GGLWETensorKey<D> { + pub fn rank(&self) -> usize { + self.keys[0].rank() + } + + pub fn rank_in(&self) -> usize { + self.keys[0].rank_in() + } + + pub fn rank_out(&self) -> usize { + self.keys[0].rank_out() + } + + pub fn digits(&self) -> usize { + self.keys[0].digits() + } +} + +impl<D: DataMut> GGLWETensorKey<D> { + // Returns a mutable reference to GLWESwitchingKey_{s}(s[i] * s[j]) + pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWESwitchingKey<D> { + if i > j { + std::mem::swap(&mut i, &mut j); + }; + let rank: usize = self.rank(); + &mut self.keys[i * rank + j - (i * (i + 1) / 2)] + } +} + +impl<D: DataRef> GGLWETensorKey<D> { + // Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j]) + pub fn at(&self, mut i: usize, mut j: usize) -> &GGLWESwitchingKey<D> { + if i > j { + std::mem::swap(&mut i, &mut j); + }; + let rank: usize = self.rank(); + &self.keys[i * rank + j - (i * (i + 1) / 2)] + } +} + +impl<D: DataMut> ReaderFrom for GGLWETensorKey<D> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + let len: usize = reader.read_u64::<LittleEndian>()? as usize; + if self.keys.len() != len { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + format!("self.keys.len()={} != read len={}", self.keys.len(), len), + )); + } + for key in &mut self.keys { + key.read_from(reader)?; + } + Ok(()) + } +} + +impl<D: DataRef> WriterTo for GGLWETensorKey<D> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::<LittleEndian>(self.keys.len() as u64)?; + for key in &self.keys { + key.write_to(writer)?; + } + Ok(()) + } +}
@@ -0,0 +1,151 @@
+use backend::hal::{ + api::{FillUniform, Reset}, + layouts::{Data, DataMut, DataRef, ReaderFrom, VecZnx, VecZnxToMut, VecZnxToRef, WriterTo}, +}; +use sampling::source::Source; + +use crate::layouts::{Infos, SetMetaData}; +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use std::fmt; + +#[derive(PartialEq, Eq, Clone)] +pub struct GLWECiphertext<D: Data> { + pub data: VecZnx<D>, + pub basek: usize, + pub k: usize, +} + +impl<D: DataRef> fmt::Debug for GLWECiphertext<D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl<D: DataRef> fmt::Display for GLWECiphertext<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "GLWECiphertext: basek={} k={}: {}", + self.basek(), + self.k(), + self.data + ) + } +} + +impl<D: DataMut> Reset for GLWECiphertext<D> +where + VecZnx<D>: Reset, +{ + fn reset(&mut self) { + self.data.reset(); + self.basek = 0; + self.k = 0; + } +} + +impl<D: DataMut> FillUniform for GLWECiphertext<D> { + fn fill_uniform(&mut self, source: &mut Source) { + self.data.fill_uniform(source); + } +} + +impl GLWECiphertext<Vec<u8>> { + pub fn alloc(n: usize, basek: usize, k: usize, rank: usize) -> Self { + Self { + data: VecZnx::alloc(n, rank + 1, k.div_ceil(basek)), + basek, + k, + } + } + + pub fn bytes_of(n: usize, basek: usize, k: usize, rank: usize) -> usize { + VecZnx::alloc_bytes(n, rank + 1, k.div_ceil(basek)) + } +} + +impl<D: Data> Infos for GLWECiphertext<D> { + type Inner = VecZnx<D>; + + fn inner(&self) -> &Self::Inner { + &self.data + } + + fn basek(&self) -> usize { + self.basek + } + + fn k(&self) -> usize { + self.k + } +} + +impl<D: Data> GLWECiphertext<D> { + pub fn rank(&self) -> usize { + self.cols() - 1 + } +} + +impl<D: DataRef> GLWECiphertext<D> { + pub fn clone(&self) -> GLWECiphertext<Vec<u8>> { + GLWECiphertext { + data: self.data.clone(), + basek: self.basek(), + k: self.k(), + } + } +} + +impl<D: DataMut> SetMetaData for GLWECiphertext<D> { + fn set_k(&mut self, k: usize) { + self.k = k + } + + fn set_basek(&mut self, basek: usize) { + self.basek = basek + } +} + +pub trait GLWECiphertextToRef: Infos { + fn to_ref(&self) -> GLWECiphertext<&[u8]>; +} + +impl<D: DataRef> GLWECiphertextToRef for GLWECiphertext<D> { + fn to_ref(&self) -> GLWECiphertext<&[u8]> { + GLWECiphertext { + data: self.data.to_ref(), + basek: self.basek, + k: self.k, + } + } +} + +pub trait GLWECiphertextToMut: Infos { + fn to_mut(&mut self) -> GLWECiphertext<&mut [u8]>; +} + +impl<D: DataMut> GLWECiphertextToMut for GLWECiphertext<D> { + fn to_mut(&mut self) -> GLWECiphertext<&mut [u8]> { + GLWECiphertext { + data: self.data.to_mut(), + basek: self.basek, + k: self.k, + } + } +} + +impl<D: DataMut> ReaderFrom for GLWECiphertext<D> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + self.k = reader.read_u64::<LittleEndian>()? as usize; + self.basek = reader.read_u64::<LittleEndian>()? as usize; + self.data.read_from(reader) + } +} + +impl<D: DataRef> WriterTo for GLWECiphertext<D> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::<LittleEndian>(self.k as u64)?; + writer.write_u64::<LittleEndian>(self.basek as u64)?; + self.data.write_to(writer) + } +}
@@ -0,0 +1,73 @@
+use backend::hal::layouts::{Data, DataMut, DataRef, ReaderFrom, VecZnx, WriterTo}; + +use crate::{dist::Distribution, layouts::Infos}; +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; + +#[derive(PartialEq, Eq)] +pub struct GLWEPublicKey<D: Data> { + pub(crate) data: VecZnx<D>, + pub(crate) basek: usize, + pub(crate) k: usize, + pub(crate) dist: Distribution, +} + +impl GLWEPublicKey<Vec<u8>> { + pub fn alloc(n: usize, basek: usize, k: usize, rank: usize) -> Self { + Self { + data: VecZnx::alloc(n, rank + 1, k.div_ceil(basek)), + basek: basek, + k: k, + dist: Distribution::NONE, + } + } + + pub fn bytes_of(n: usize, basek: usize, k: usize, rank: usize) -> usize { + VecZnx::alloc_bytes(n, rank + 1, k.div_ceil(basek)) + } +} + +impl<D: Data> Infos for GLWEPublicKey<D> { + type Inner = VecZnx<D>; + + fn inner(&self) -> &Self::Inner { + &self.data + } + + fn basek(&self) -> usize { + self.basek + } + + fn k(&self) -> usize { + self.k + } +} + +impl<D: Data> GLWEPublicKey<D> { + pub fn rank(&self) -> usize { + self.cols() - 1 + } +} + +impl<D: DataMut> ReaderFrom for GLWEPublicKey<D> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + self.k = reader.read_u64::<LittleEndian>()? as usize; + self.basek = reader.read_u64::<LittleEndian>()? as usize; + match Distribution::read_from(reader) { + Ok(dist) => self.dist = dist, + Err(e) => return Err(e), + } + self.data.read_from(reader) + } +} + +impl<D: DataRef> WriterTo for GLWEPublicKey<D> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::<LittleEndian>(self.k as u64)?; + writer.write_u64::<LittleEndian>(self.basek as u64)?; + match self.dist.write_to(writer) { + Ok(()) => {} + Err(e) => return Err(e), + } + self.data.write_to(writer) + } +}
@@ -0,0 +1,102 @@
+use backend::hal::{ + api::{ZnxInfos, ZnxZero}, + layouts::{Data, DataMut, DataRef, ReaderFrom, ScalarZnx, WriterTo}, +}; +use sampling::source::Source; + +use crate::dist::Distribution; + +#[derive(PartialEq, Eq, Clone)] +pub struct GLWESecret<D: Data> { + pub(crate) data: ScalarZnx<D>, + pub(crate) dist: Distribution, +} + +impl GLWESecret<Vec<u8>> { + pub fn alloc(n: usize, rank: usize) -> Self { + Self { + data: ScalarZnx::alloc(n, rank), + dist: Distribution::NONE, + } + } + + pub fn bytes_of(n: usize, rank: usize) -> usize { + ScalarZnx::alloc_bytes(n, rank) + } +} + +impl<D: Data> GLWESecret<D> { + pub fn n(&self) -> usize { + self.data.n() + } + + pub fn log_n(&self) -> usize { + self.data.log_n() + } + + pub fn rank(&self) -> usize { + self.data.cols() + } +} + +impl<D: DataMut> GLWESecret<D> { + pub fn fill_ternary_prob(&mut self, prob: f64, source: &mut Source) { + (0..self.rank()).for_each(|i| { + self.data.fill_ternary_prob(i, prob, source); + }); + self.dist = Distribution::TernaryProb(prob); + } + + pub fn fill_ternary_hw(&mut self, hw: usize, source: &mut Source) { + (0..self.rank()).for_each(|i| { + self.data.fill_ternary_hw(i, hw, source); + }); + self.dist = Distribution::TernaryFixed(hw); + } + + pub fn fill_binary_prob(&mut self, prob: f64, source: &mut Source) { + (0..self.rank()).for_each(|i| { + self.data.fill_binary_prob(i, prob, source); + }); + self.dist = Distribution::BinaryProb(prob); + } + + pub fn fill_binary_hw(&mut self, hw: usize, source: &mut Source) { + (0..self.rank()).for_each(|i| { + self.data.fill_binary_hw(i, hw, source); + }); + self.dist = Distribution::BinaryFixed(hw); + } + + pub fn fill_binary_block(&mut self, block_size: usize, source: &mut Source) { + (0..self.rank()).for_each(|i| { + self.data.fill_binary_block(i, block_size, source); + }); + self.dist = Distribution::BinaryBlock(block_size); + } + + pub fn fill_zero(&mut self) { + self.data.zero(); + self.dist = Distribution::ZERO; + } +} + +impl<D: DataMut> ReaderFrom for GLWESecret<D> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + match Distribution::read_from(reader) { + Ok(dist) => self.dist = dist, + Err(e) => return Err(e), + } + self.data.read_from(reader) + } +} + +impl<D: DataRef> WriterTo for GLWESecret<D> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + match self.dist.write_to(writer) { + Ok(()) => {} + Err(e) => return Err(e), + } + self.data.write_to(writer) + } +}
@@ -0,0 +1,88 @@
+use backend::hal::{ + api::{FillUniform, Reset}, + layouts::{Data, DataMut, DataRef, MatZnx, ReaderFrom, WriterTo}, +}; + +use crate::layouts::{GGLWESwitchingKey, Infos}; + +use std::fmt; + +/// A special [GLWESwitchingKey] required to for the conversion from [GLWECiphertext] to [LWECiphertext]. +#[derive(PartialEq, Eq, Clone)] +pub struct GLWEToLWESwitchingKey<D: Data>(pub(crate) GGLWESwitchingKey<D>); + +impl<D: DataRef> fmt::Debug for GLWEToLWESwitchingKey<D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl<D: DataMut> FillUniform for GLWEToLWESwitchingKey<D> { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.0.fill_uniform(source); + } +} + +impl<D: DataMut> Reset for GLWEToLWESwitchingKey<D> { + fn reset(&mut self) { + self.0.reset(); + } +} + +impl<D: DataRef> fmt::Display for GLWEToLWESwitchingKey<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(GLWEToLWESwitchingKey) {}", self.0) + } +} + +impl<D: Data> Infos for GLWEToLWESwitchingKey<D> { + type Inner = MatZnx<D>; + + fn inner(&self) -> &Self::Inner { + &self.0.inner() + } + + fn basek(&self) -> usize { + self.0.basek() + } + + fn k(&self) -> usize { + self.0.k() + } +} + +impl<D: Data> GLWEToLWESwitchingKey<D> { + pub fn digits(&self) -> usize { + self.0.digits() + } + + pub fn rank(&self) -> usize { + self.0.rank() + } + + pub fn rank_in(&self) -> usize { + self.0.rank_in() + } + + pub fn rank_out(&self) -> usize { + self.0.rank_out() + } +} + +impl<D: DataMut> ReaderFrom for GLWEToLWESwitchingKey<D> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + self.0.read_from(reader) + } +} + +impl<D: DataRef> WriterTo for GLWEToLWESwitchingKey<D> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + self.0.write_to(writer) + } +} + +impl GLWEToLWESwitchingKey<Vec<u8>> { + pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, rank_in: usize) -> Self { + Self(GGLWESwitchingKey::alloc(n, basek, k, rows, 1, rank_in, 1)) + } +}
@@ -0,0 +1,87 @@
+use std::fmt; + +use backend::hal::{ + api::{FillUniform, Reset}, + layouts::{Data, DataMut, DataRef, MatZnx, ReaderFrom, WriterTo}, +}; + +use crate::layouts::{GGLWESwitchingKey, Infos}; + +#[derive(PartialEq, Eq, Clone)] +pub struct LWESwitchingKey<D: Data>(pub(crate) GGLWESwitchingKey<D>); + +impl LWESwitchingKey<Vec<u8>> { + pub fn alloc(n: usize, basek: usize, k: usize, rows: usize) -> Self { + Self(GGLWESwitchingKey::alloc(n, basek, k, rows, 1, 1, 1)) + } +} + +impl<D: DataRef> fmt::Debug for LWESwitchingKey<D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl<D: DataMut> FillUniform for LWESwitchingKey<D> { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.0.fill_uniform(source); + } +} + +impl<D: DataMut> Reset for LWESwitchingKey<D> { + fn reset(&mut self) { + self.0.reset(); + } +} + +impl<D: DataRef> fmt::Display for LWESwitchingKey<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(LWESwitchingKey) {}", self.0) + } +} + +impl<D: Data> Infos for LWESwitchingKey<D> { + type Inner = MatZnx<D>; + + fn inner(&self) -> &Self::Inner { + &self.0.inner() + } + + fn basek(&self) -> usize { + self.0.basek() + } + + fn k(&self) -> usize { + self.0.k() + } +} + +impl<D: Data> LWESwitchingKey<D> { + pub fn digits(&self) -> usize { + self.0.digits() + } + + pub fn rank(&self) -> usize { + self.0.rank() + } + + pub fn rank_in(&self) -> usize { + self.0.rank_in() + } + + pub fn rank_out(&self) -> usize { + self.0.rank_out() + } +} + +impl<D: DataMut> ReaderFrom for LWESwitchingKey<D> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + self.0.read_from(reader) + } +} + +impl<D: DataRef> WriterTo for LWESwitchingKey<D> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + self.0.write_to(writer) + } +}
@@ -0,0 +1,87 @@
+use std::fmt; + +use backend::hal::{ + api::{FillUniform, Reset}, + layouts::{Data, DataMut, DataRef, MatZnx, ReaderFrom, WriterTo}, +}; + +use crate::layouts::{GGLWESwitchingKey, Infos}; + +#[derive(PartialEq, Eq, Clone)] +pub struct LWEToGLWESwitchingKey<D: Data>(pub(crate) GGLWESwitchingKey<D>); + +impl<D: DataRef> fmt::Debug for LWEToGLWESwitchingKey<D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl<D: DataMut> FillUniform for LWEToGLWESwitchingKey<D> { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.0.fill_uniform(source); + } +} + +impl<D: DataMut> Reset for LWEToGLWESwitchingKey<D> { + fn reset(&mut self) { + self.0.reset(); + } +} + +impl<D: DataRef> fmt::Display for LWEToGLWESwitchingKey<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(LWEToGLWESwitchingKey) {}", self.0) + } +} + +impl<D: Data> Infos for LWEToGLWESwitchingKey<D> { + type Inner = MatZnx<D>; + + fn inner(&self) -> &Self::Inner { + &self.0.inner() + } + + fn basek(&self) -> usize { + self.0.basek() + } + + fn k(&self) -> usize { + self.0.k() + } +} + +impl<D: Data> LWEToGLWESwitchingKey<D> { + pub fn digits(&self) -> usize { + self.0.digits() + } + + pub fn rank(&self) -> usize { + self.0.rank() + } + + pub fn rank_in(&self) -> usize { + self.0.rank_in() + } + + pub fn rank_out(&self) -> usize { + self.0.rank_out() + } +} + +impl<D: DataMut> ReaderFrom for LWEToGLWESwitchingKey<D> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + self.0.read_from(reader) + } +} + +impl<D: DataRef> WriterTo for LWEToGLWESwitchingKey<D> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + self.0.write_to(writer) + } +} + +impl LWEToGLWESwitchingKey<Vec<u8>> { + pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, rank_out: usize) -> Self { + Self(GGLWESwitchingKey::alloc(n, basek, k, rows, 1, 1, rank_out)) + } +}
@@ -0,0 +1,36 @@
+mod gglwe_atk; +mod gglwe_ct; +mod gglwe_ksk; +mod gglwe_tsk; +mod ggsw_ct; +mod glwe_ct; +mod glwe_pk; +mod glwe_pt; +mod glwe_sk; +mod glwe_to_lwe_ksk; +mod infos; +mod lwe_ct; +mod lwe_ksk; +mod lwe_pt; +mod lwe_sk; +mod lwe_to_glwe_ksk; + +pub mod compressed; +pub mod prepared; + +pub use gglwe_atk::*; +pub use gglwe_ct::*; +pub use gglwe_ksk::*; +pub use gglwe_tsk::*; +pub use ggsw_ct::*; +pub use glwe_ct::*; +pub use glwe_pk::*; +pub use glwe_pt::*; +pub use glwe_sk::*; +pub use glwe_to_lwe_ksk::*; +pub use infos::*; +pub use lwe_ct::*; +pub use lwe_ksk::*; +pub use lwe_pt::*; +pub use lwe_sk::*; +pub use lwe_to_glwe_ksk::*;
@@ -0,0 +1,97 @@
+use backend::hal::{ + api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare}, + layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}, +}; + +use crate::layouts::{GGLWEAutomorphismKey, Infos, prepared::GGLWESwitchingKeyExec}; + +#[derive(PartialEq, Eq)] +pub struct GGLWEAutomorphismKeyExec<D: Data, B: Backend> { + pub(crate) key: GGLWESwitchingKeyExec<D, B>, + pub(crate) p: i64, +} + +impl<B: Backend> GGLWEAutomorphismKeyExec<Vec<u8>, B> { + pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self + where + Module<B>: VmpPMatAlloc<B>, + { + GGLWEAutomorphismKeyExec::<Vec<u8>, B> { + key: GGLWESwitchingKeyExec::alloc(module, n, basek, k, rows, digits, rank, rank), + p: 0, + } + } + + pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize + where + Module<B>: VmpPMatAllocBytes, + { + GGLWESwitchingKeyExec::bytes_of(module, n, basek, k, rows, digits, rank, rank) + } + + pub fn from<DataOther: DataRef>(module: &Module<B>, other: &GGLWEAutomorphismKey<DataOther>, scratch: &mut Scratch<B>) -> Self + where + Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, + { + let mut atk_exec: GGLWEAutomorphismKeyExec<Vec<u8>, B> = Self::alloc( + module, + other.n(), + other.basek(), + other.k(), + other.rows(), + other.digits(), + other.rank(), + ); + atk_exec.prepare(module, other, scratch); + atk_exec + } +} + +impl<D: Data, B: Backend> Infos for GGLWEAutomorphismKeyExec<D, B> { + type Inner = VmpPMat<D, B>; + + fn inner(&self) -> &Self::Inner { + &self.key.inner() + } + + fn basek(&self) -> usize { + self.key.basek() + } + + fn k(&self) -> usize { + self.key.k() + } +} + +impl<D: Data, B: Backend> GGLWEAutomorphismKeyExec<D, B> { + pub fn p(&self) -> i64 { + self.p + } + + pub fn digits(&self) -> usize { + self.key.digits() + } + + pub fn rank(&self) -> usize { + self.key.rank() + } + + pub fn rank_in(&self) -> usize { + self.key.rank_in() + } + + pub fn rank_out(&self) -> usize { + self.key.rank_out() + } +} + +impl<D: DataMut, B: Backend> GGLWEAutomorphismKeyExec<D, B> { + pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGLWEAutomorphismKey<DataOther>, scratch: &mut Scratch<B>) + where + DataOther: DataRef, + Module<B>: VmpPMatPrepare<B>, + { + self.key.prepare(module, &other.key, scratch); + self.p = other.p; + } +}
@@ -0,0 +1,132 @@
+use backend::hal::{ + api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare}, + layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}, +}; + +use crate::layouts::{GGLWECiphertext, Infos}; + +#[derive(PartialEq, Eq)] +pub struct GGLWECiphertextExec<D: Data, B: Backend> { + pub(crate) data: VmpPMat<D, B>, + pub(crate) basek: usize, + pub(crate) k: usize, + pub(crate) digits: usize, +} + +impl<B: Backend> GGLWECiphertextExec<Vec<u8>, B> { + pub fn alloc( + module: &Module<B>, + n: usize, + basek: usize, + k: usize, + rows: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + ) -> Self + where + Module<B>: VmpPMatAlloc<B>, + { + let size: usize = k.div_ceil(basek); + debug_assert!( + size > digits, + "invalid gglwe: ceil(k/basek): {} <= digits: {}", + size, + digits + ); + + assert!( + rows * digits <= size, + "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}", + rows, + digits, + size + ); + + Self { + data: module.vmp_pmat_alloc(n, rows, rank_in, rank_out + 1, size), + basek: basek, + k, + digits, + } + } + + pub fn bytes_of( + module: &Module<B>, + n: usize, + basek: usize, + k: usize, + rows: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + ) -> usize + where + Module<B>: VmpPMatAllocBytes, + { + let size: usize = k.div_ceil(basek); + debug_assert!( + size > digits, + "invalid gglwe: ceil(k/basek): {} <= digits: {}", + size, + digits + ); + + assert!( + rows * digits <= size, + "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}", + rows, + digits, + size + ); + + module.vmp_pmat_alloc_bytes(n, rows, rank_in, rank_out + 1, rows) + } +} + +impl<D: Data, B: Backend> Infos for GGLWECiphertextExec<D, B> { + type Inner = VmpPMat<D, B>; + + fn inner(&self) -> &Self::Inner { + &self.data + } + + fn basek(&self) -> usize { + self.basek + } + + fn k(&self) -> usize { + self.k + } +} + +impl<D: Data, B: Backend> GGLWECiphertextExec<D, B> { + pub fn rank(&self) -> usize { + self.data.cols_out() - 1 + } + + pub fn digits(&self) -> usize { + self.digits + } + + pub fn rank_in(&self) -> usize { + self.data.cols_in() + } + + pub fn rank_out(&self) -> usize { + self.data.cols_out() - 1 + } +} + +impl<D: DataMut, B: Backend> GGLWECiphertextExec<D, B> { + pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGLWECiphertext<DataOther>, scratch: &mut Scratch<B>) + where + DataOther: DataRef, + Module<B>: VmpPMatPrepare<B>, + { + module.vmp_prepare(&mut self.data, &other.data, scratch); + self.basek = other.basek; + self.k = other.k; + self.digits = other.digits; + } +}
@@ -0,0 +1,123 @@
+use backend::hal::{ + api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare}, + layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}, +}; + +use crate::layouts::{GGLWESwitchingKey, Infos, prepared::GGLWECiphertextExec}; + +#[derive(PartialEq, Eq)] +pub struct GGLWESwitchingKeyExec<D: Data, B: Backend> { + pub(crate) key: GGLWECiphertextExec<D, B>, + pub(crate) sk_in_n: usize, // Degree of sk_in + pub(crate) sk_out_n: usize, // Degree of sk_out +} + +impl<B: Backend> GGLWESwitchingKeyExec<Vec<u8>, B> { + pub fn alloc( + module: &Module<B>, + n: usize, + basek: usize, + k: usize, + rows: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + ) -> Self + where + Module<B>: VmpPMatAlloc<B>, + { + GGLWESwitchingKeyExec::<Vec<u8>, B> { + key: GGLWECiphertextExec::alloc(module, n, basek, k, rows, digits, rank_in, rank_out), + sk_in_n: 0, + sk_out_n: 0, + } + } + + pub fn bytes_of( + module: &Module<B>, + n: usize, + basek: usize, + k: usize, + rows: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + ) -> usize + where + Module<B>: VmpPMatAllocBytes, + { + GGLWECiphertextExec::bytes_of(module, n, basek, k, rows, digits, rank_in, rank_out) + } + + pub fn from<DataOther: DataRef>(module: &Module<B>, other: &GGLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) -> Self + where + Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, + { + let mut ksk_exec: GGLWESwitchingKeyExec<Vec<u8>, B> = Self::alloc( + module, + other.n(), + other.basek(), + other.k(), + other.rows(), + other.digits(), + other.rank_in(), + other.rank_out(), + ); + ksk_exec.prepare(module, other, scratch); + ksk_exec + } +} + +impl<D: Data, B: Backend> Infos for GGLWESwitchingKeyExec<D, B> { + type Inner = VmpPMat<D, B>; + + fn inner(&self) -> &Self::Inner { + self.key.inner() + } + + fn basek(&self) -> usize { + self.key.basek() + } + + fn k(&self) -> usize { + self.key.k() + } +} + +impl<D: Data, B: Backend> GGLWESwitchingKeyExec<D, B> { + pub fn rank(&self) -> usize { + self.key.data.cols_out() - 1 + } + + pub fn rank_in(&self) -> usize { + self.key.data.cols_in() + } + + pub fn rank_out(&self) -> usize { + self.key.data.cols_out() - 1 + } + + pub fn digits(&self) -> usize { + self.key.digits() + } + + pub fn sk_degree_in(&self) -> usize { + self.sk_in_n + } + + pub fn sk_degree_out(&self) -> usize { + self.sk_out_n + } +} + +impl<D: DataMut, B: Backend> GGLWESwitchingKeyExec<D, B> { + pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) + where + DataOther: DataRef, + Module<B>: VmpPMatPrepare<B>, + { + self.key.prepare(module, &other.key, scratch); + self.sk_in_n = other.sk_in_n; + self.sk_out_n = other.sk_out_n; + } +}
@@ -0,0 +1,131 @@
+use backend::hal::{ + api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare}, + layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}, +}; + +use crate::layouts::{GGLWETensorKey, Infos, prepared::GGLWESwitchingKeyExec}; + +#[derive(PartialEq, Eq)] +pub struct GGLWETensorKeyExec<D: Data, B: Backend> { + pub(crate) keys: Vec<GGLWESwitchingKeyExec<D, B>>, +} + +impl<B: Backend> GGLWETensorKeyExec<Vec<u8>, B> { + pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self + where + Module<B>: VmpPMatAlloc<B>, + { + let mut keys: Vec<GGLWESwitchingKeyExec<Vec<u8>, B>> = Vec::new(); + let pairs: usize = (((rank + 1) * rank) >> 1).max(1); + (0..pairs).for_each(|_| { + keys.push(GGLWESwitchingKeyExec::alloc( + module, n, basek, k, rows, digits, 1, rank, + )); + }); + Self { keys } + } + + pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize + where + Module<B>: VmpPMatAllocBytes, + { + let pairs: usize = (((rank + 1) * rank) >> 1).max(1); + pairs * GGLWESwitchingKeyExec::bytes_of(module, n, basek, k, rows, digits, 1, rank) + } + + pub fn from<D: DataRef>( + module: &Module<B>, + other: &GGLWETensorKey<D>, + scratch: &mut Scratch<B>, + ) -> GGLWETensorKeyExec<Vec<u8>, B> + where + Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, + { + let mut tsk_exec: GGLWETensorKeyExec<Vec<u8>, B> = Self::alloc( + module, + other.n(), + other.basek(), + other.k(), + other.rows(), + other.digits(), + other.rank(), + ); + tsk_exec.prepare(module, other, scratch); + tsk_exec + } +} + +impl<D: Data, B: Backend> Infos for GGLWETensorKeyExec<D, B> { + type Inner = VmpPMat<D, B>; + + fn inner(&self) -> &Self::Inner { + &self.keys[0].inner() + } + + fn basek(&self) -> usize { + self.keys[0].basek() + } + + fn k(&self) -> usize { + self.keys[0].k() + } +} + +impl<D: Data, B: Backend> GGLWETensorKeyExec<D, B> { + pub fn rank(&self) -> usize { + self.keys[0].rank() + } + + pub fn rank_in(&self) -> usize { + self.keys[0].rank_in() + } + + pub fn rank_out(&self) -> usize { + self.keys[0].rank_out() + } + + pub fn digits(&self) -> usize { + self.keys[0].digits() + } +} + +impl<D: DataMut, B: Backend> GGLWETensorKeyExec<D, B> { + // Returns a mutable reference to GLWESwitchingKey_{s}(s[i] * s[j]) + pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWESwitchingKeyExec<D, B> { + if i > j { + std::mem::swap(&mut i, &mut j); + }; + let rank: usize = self.rank(); + &mut self.keys[i * rank + j - (i * (i + 1) / 2)] + } +} + +impl<D: DataRef, B: Backend> GGLWETensorKeyExec<D, B> { + // Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j]) + pub fn at(&self, mut i: usize, mut j: usize) -> &GGLWESwitchingKeyExec<D, B> { + if i > j { + std::mem::swap(&mut i, &mut j); + }; + let rank: usize = self.rank(); + &self.keys[i * rank + j - (i * (i + 1) / 2)] + } +} + +impl<D: DataMut, B: Backend> GGLWETensorKeyExec<D, B> { + pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGLWETensorKey<DataOther>, scratch: &mut Scratch<B>) + where + DataOther: DataRef, + Module<B>: VmpPMatPrepare<B>, + { + #[cfg(debug_assertions)] + { + assert_eq!(self.keys.len(), other.keys.len()); + } + self.keys + .iter_mut() + .zip(other.keys.iter()) + .for_each(|(a, b)| { + a.prepare(module, b, scratch); + }); + } +}
@@ -0,0 +1,92 @@
+use backend::hal::{ + api::{VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftFromVecZnx}, + layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VecZnxDft}, +}; + +use crate::{ + dist::Distribution, + layouts::{GLWEPublicKey, Infos}, +}; + +#[derive(PartialEq, Eq)] +pub struct GLWEPublicKeyExec<D: Data, B: Backend> { + pub(crate) data: VecZnxDft<D, B>, + pub(crate) basek: usize, + pub(crate) k: usize, + pub(crate) dist: Distribution, +} + +impl<D: Data, B: Backend> Infos for GLWEPublicKeyExec<D, B> { + type Inner = VecZnxDft<D, B>; + + fn inner(&self) -> &Self::Inner { + &self.data + } + + fn basek(&self) -> usize { + self.basek + } + + fn k(&self) -> usize { + self.k + } +} + +impl<D: Data, B: Backend> GLWEPublicKeyExec<D, B> { + pub fn rank(&self) -> usize { + self.cols() - 1 + } +} + +impl<B: Backend> GLWEPublicKeyExec<Vec<u8>, B> { + pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> Self + where + Module<B>: VecZnxDftAlloc<B>, + { + Self { + data: module.vec_znx_dft_alloc(n, rank + 1, k.div_ceil(basek)), + basek: basek, + k: k, + dist: Distribution::NONE, + } + } + + pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize + where + Module<B>: VecZnxDftAllocBytes, + { + module.vec_znx_dft_alloc_bytes(n, rank + 1, k.div_ceil(basek)) + } + + pub fn from<DataOther>(module: &Module<B>, other: &GLWEPublicKey<DataOther>, scratch: &mut Scratch<B>) -> Self + where + DataOther: DataRef, + Module<B>: VecZnxDftAlloc<B> + VecZnxDftFromVecZnx<B>, + { + let mut pk_exec: GLWEPublicKeyExec<Vec<u8>, B> = + GLWEPublicKeyExec::alloc(module, other.n(), other.basek(), other.k(), other.rank()); + pk_exec.prepare(module, other, scratch); + pk_exec + } +} + +impl<D: DataMut, B: Backend> GLWEPublicKeyExec<D, B> { + pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GLWEPublicKey<DataOther>, _scratch: &mut Scratch<B>) + where + DataOther: DataRef, + Module<B>: VecZnxDftFromVecZnx<B>, + { + #[cfg(debug_assertions)] + { + assert_eq!(self.n(), other.n()); + assert_eq!(self.size(), other.size()); + } + + (0..self.cols()).for_each(|i| { + module.vec_znx_dft_from_vec_znx(1, 0, &mut self.data, i, &other.data, i); + }); + self.k = other.k; + self.basek = other.basek; + self.dist = other.dist; + } +}
@@ -0,0 +1,69 @@
+use backend::hal::{ + api::{SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, ZnxInfos}, + layouts::{Backend, Data, DataMut, DataRef, Module, SvpPPol}, +}; + +use crate::{dist::Distribution, layouts::GLWESecret, trait_families::GLWESecretExecModuleFamily}; + +pub struct GLWESecretExec<D: Data, B: Backend> { + pub(crate) data: SvpPPol<D, B>, + pub(crate) dist: Distribution, +} + +impl<B: Backend> GLWESecretExec<Vec<u8>, B> { + pub fn alloc(module: &Module<B>, n: usize, rank: usize) -> Self + where + Module<B>: GLWESecretExecModuleFamily<B>, + { + Self { + data: module.svp_ppol_alloc(n, rank), + dist: Distribution::NONE, + } + } + + pub fn bytes_of(module: &Module<B>, n: usize, rank: usize) -> usize + where + Module<B>: GLWESecretExecModuleFamily<B>, + { + module.svp_ppol_alloc_bytes(n, rank) + } +} + +impl<B: Backend> GLWESecretExec<Vec<u8>, B> { + pub fn from<D>(module: &Module<B>, sk: &GLWESecret<D>) -> Self + where + D: DataRef, + Module<B>: GLWESecretExecModuleFamily<B>, + { + let mut sk_dft: GLWESecretExec<Vec<u8>, B> = Self::alloc(module, sk.n(), sk.rank()); + sk_dft.prepare(module, sk); + sk_dft + } +} + +impl<D: Data, B: Backend> GLWESecretExec<D, B> { + pub fn n(&self) -> usize { + self.data.n() + } + + pub fn log_n(&self) -> usize { + self.data.log_n() + } + + pub fn rank(&self) -> usize { + self.data.cols() + } +} + +impl<D: DataMut, B: Backend> GLWESecretExec<D, B> { + pub(crate) fn prepare<O>(&mut self, module: &Module<B>, sk: &GLWESecret<O>) + where + O: DataRef, + Module<B>: GLWESecretExecModuleFamily<B>, + { + (0..self.rank()).for_each(|i| { + module.svp_prepare(&mut self.data, i, &sk.data, i); + }); + self.dist = sk.dist + } +}
@@ -0,0 +1,91 @@
+use backend::hal::{ + api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare}, + layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}, +}; + +use crate::layouts::{GLWEToLWESwitchingKey, Infos, prepared::GGLWESwitchingKeyExec}; + +#[derive(PartialEq, Eq)] +pub struct GLWEToLWESwitchingKeyExec<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyExec<D, B>); + +impl<D: Data, B: Backend> Infos for GLWEToLWESwitchingKeyExec<D, B> { + type Inner = VmpPMat<D, B>; + + fn inner(&self) -> &Self::Inner { + &self.0.inner() + } + + fn basek(&self) -> usize { + self.0.basek() + } + + fn k(&self) -> usize { + self.0.k() + } +} + +impl<D: Data, B: Backend> GLWEToLWESwitchingKeyExec<D, B> { + pub fn digits(&self) -> usize { + self.0.digits() + } + + pub fn rank(&self) -> usize { + self.0.rank() + } + + pub fn rank_in(&self) -> usize { + self.0.rank_in() + } + + pub fn rank_out(&self) -> usize { + self.0.rank_out() + } +} + +impl<B: Backend> GLWEToLWESwitchingKeyExec<Vec<u8>, B> { + pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, rank_in: usize) -> Self + where + Module<B>: VmpPMatAlloc<B>, + { + Self(GGLWESwitchingKeyExec::alloc( + module, n, basek, k, rows, 1, rank_in, 1, + )) + } + + pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize) -> usize + where + Module<B>: VmpPMatAllocBytes, + { + GGLWESwitchingKeyExec::<Vec<u8>, B>::bytes_of(module, n, basek, k, rows, digits, rank_in, 1) + } + + pub fn from<DataOther: DataRef>( + module: &Module<B>, + other: &GLWEToLWESwitchingKey<DataOther>, + scratch: &mut Scratch<B>, + ) -> Self + where + Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, + { + let mut ksk_exec: GLWEToLWESwitchingKeyExec<Vec<u8>, B> = Self::alloc( + module, + other.0.n(), + other.0.basek(), + other.0.k(), + other.0.rows(), + other.0.rank_in(), + ); + ksk_exec.prepare(module, other, scratch); + ksk_exec + } +} + +impl<D: DataMut, B: Backend> GLWEToLWESwitchingKeyExec<D, B> { + pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GLWEToLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) + where + DataOther: DataRef, + Module<B>: VmpPMatPrepare<B>, + { + self.0.prepare(module, &other.0, scratch); + } +}
@@ -0,0 +1,86 @@
+use backend::hal::{ + api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare}, + layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}, +}; + +use crate::layouts::{Infos, LWESwitchingKey, prepared::GGLWESwitchingKeyExec}; + +#[derive(PartialEq, Eq)] +pub struct LWESwitchingKeyExec<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyExec<D, B>); + +impl<D: Data, B: Backend> Infos for LWESwitchingKeyExec<D, B> { + type Inner = VmpPMat<D, B>; + + fn inner(&self) -> &Self::Inner { + &self.0.inner() + } + + fn basek(&self) -> usize { + self.0.basek() + } + + fn k(&self) -> usize { + self.0.k() + } +} + +impl<D: Data, B: Backend> LWESwitchingKeyExec<D, B> { + pub fn digits(&self) -> usize { + self.0.digits() + } + + pub fn rank(&self) -> usize { + self.0.rank() + } + + pub fn rank_in(&self) -> usize { + self.0.rank_in() + } + + pub fn rank_out(&self) -> usize { + self.0.rank_out() + } +} + +impl<B: Backend> LWESwitchingKeyExec<Vec<u8>, B> { + pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize) -> Self + where + Module<B>: VmpPMatAlloc<B>, + { + Self(GGLWESwitchingKeyExec::alloc( + module, n, basek, k, rows, 1, 1, 1, + )) + } + + pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize) -> usize + where + Module<B>: VmpPMatAllocBytes, + { + GGLWESwitchingKeyExec::<Vec<u8>, B>::bytes_of(module, n, basek, k, rows, digits, 1, 1) + } + + pub fn from<DataOther: DataRef>(module: &Module<B>, other: &LWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) -> Self + where + Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, + { + let mut ksk_exec: LWESwitchingKeyExec<Vec<u8>, B> = Self::alloc( + module, + other.0.n(), + other.0.basek(), + other.0.k(), + other.0.rows(), + ); + ksk_exec.prepare(module, other, scratch); + ksk_exec + } +} + +impl<D: DataMut, B: Backend> LWESwitchingKeyExec<D, B> { + pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &LWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) + where + DataOther: DataRef, + Module<B>: VmpPMatPrepare<B>, + { + self.0.prepare(module, &other.0, scratch); + } +}
@@ -0,0 +1,92 @@
+use backend::hal::{ + api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare}, + layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}, +}; + +use crate::layouts::{Infos, LWEToGLWESwitchingKey, prepared::GGLWESwitchingKeyExec}; + +/// A special [GLWESwitchingKey] required to for the conversion from [LWECiphertext] to [GLWECiphertext]. +#[derive(PartialEq, Eq)] +pub struct LWEToGLWESwitchingKeyExec<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyExec<D, B>); + +impl<D: Data, B: Backend> Infos for LWEToGLWESwitchingKeyExec<D, B> { + type Inner = VmpPMat<D, B>; + + fn inner(&self) -> &Self::Inner { + &self.0.inner() + } + + fn basek(&self) -> usize { + self.0.basek() + } + + fn k(&self) -> usize { + self.0.k() + } +} + +impl<D: Data, B: Backend> LWEToGLWESwitchingKeyExec<D, B> { + pub fn digits(&self) -> usize { + self.0.digits() + } + + pub fn rank(&self) -> usize { + self.0.rank() + } + + pub fn rank_in(&self) -> usize { + self.0.rank_in() + } + + pub fn rank_out(&self) -> usize { + self.0.rank_out() + } +} + +impl<B: Backend> LWEToGLWESwitchingKeyExec<Vec<u8>, B> { + pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, rank_out: usize) -> Self + where + Module<B>: VmpPMatAlloc<B>, + { + Self(GGLWESwitchingKeyExec::alloc( + module, n, basek, k, rows, 1, 1, rank_out, + )) + } + + pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_out: usize) -> usize + where + Module<B>: VmpPMatAllocBytes, + { + GGLWESwitchingKeyExec::<Vec<u8>, B>::bytes_of(module, n, basek, k, rows, digits, 1, rank_out) + } + + pub fn from<DataOther: DataRef>( + module: &Module<B>, + other: &LWEToGLWESwitchingKey<DataOther>, + scratch: &mut Scratch<B>, + ) -> Self + where + Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, + { + let mut ksk_exec: LWEToGLWESwitchingKeyExec<Vec<u8>, B> = Self::alloc( + module, + other.0.n(), + other.0.basek(), + other.0.k(), + other.0.rows(), + other.0.rank(), + ); + ksk_exec.prepare(module, other, scratch); + ksk_exec + } +} + +impl<D: DataMut, B: Backend> LWEToGLWESwitchingKeyExec<D, B> { + pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &LWEToGLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) + where + DataOther: DataRef, + Module<B>: VmpPMatPrepare<B>, + { + self.0.prepare(module, &other.0, scratch); + } +}
@@ -0,0 +1,21 @@
+mod gglwe_atk; +mod gglwe_ct; +mod gglwe_ksk; +mod gglwe_tsk; +mod ggsw_ct; +mod glwe_pk; +mod glwe_sk; +mod glwe_to_lwe_ksk; +mod lwe_ksk; +mod lwe_to_glwe_ksk; + +pub use gglwe_atk::*; +pub use gglwe_ct::*; +pub use gglwe_ksk::*; +pub use gglwe_tsk::*; +pub use ggsw_ct::*; +pub use glwe_pk::*; +pub use glwe_sk::*; +pub use glwe_to_lwe_ksk::*; +pub use lwe_ksk::*; +pub use lwe_to_glwe_ksk::*;
@@ -1,24 +1,24 @@
#![feature(trait_alias)] -mod blind_rotation; -mod circuit_bootstrapping; +mod automorphism; +mod conversion; +mod decryption; mod dist; -mod elem; -mod gglwe; -mod ggsw; -mod glwe; -mod lwe; +mod encryption; +mod external_product; +mod glwe_packing; +mod glwe_trace; +mod keyswitching; mod noise; +mod operations; mod scratch; -use crate::dist::Distribution; +pub use operations::*; +pub mod layouts; +pub mod trait_families; +pub use glwe_packing::*; -pub use blind_rotation::*; -pub use circuit_bootstrapping::*; -pub use elem::*; -pub use gglwe::*; -pub use ggsw::*; -pub use glwe::*; -pub use lwe::*; pub use scratch::*; pub(crate) const SIX_SIGMA: f64 = 6.0; + +pub mod tests;
@@ -1,173 +0,0 @@
-use backend::hal::{ - api::{ScratchAvailable, TakeVecZnx, TakeVecZnxDft, ZnxView, ZnxViewMut, ZnxZero}, - layouts::{Backend, DataMut, DataRef, Module, Scratch}, -}; - -use crate::{ - GLWECiphertext, GLWEKeyswitchFamily, GLWEToLWESwitchingKeyExec, Infos, LWECiphertext, LWESwitchingKeyExec, - LWEToGLWESwitchingKeyExec, TakeGLWECt, -}; - -impl LWECiphertext<Vec<u8>> { - pub fn from_glwe_scratch_space<B: Backend>( - module: &Module<B>, - n: usize, - basek: usize, - k_lwe: usize, - k_glwe: usize, - k_ksk: usize, - rank: usize, - ) -> usize - where - Module<B>: GLWEKeyswitchFamily<B>, - { - GLWECiphertext::bytes_of(n, basek, k_lwe, 1) - + GLWECiphertext::keyswitch_scratch_space(module, n, basek, k_lwe, k_glwe, k_ksk, 1, rank, 1) - } - - pub fn keyswitch_scratch_space<B: Backend>( - module: &Module<B>, - n: usize, - basek: usize, - k_lwe_out: usize, - k_lwe_in: usize, - k_ksk: usize, - ) -> usize - where - Module<B>: GLWEKeyswitchFamily<B>, - { - GLWECiphertext::bytes_of(n, basek, k_lwe_out.max(k_lwe_in), 1) - + GLWECiphertext::keyswitch_inplace_scratch_space(module, n, basek, k_lwe_out, k_ksk, 1, 1) - } -} - -impl<DLwe: DataMut> LWECiphertext<DLwe> { - pub fn sample_extract<DGlwe: DataRef>(&mut self, a: &GLWECiphertext<DGlwe>) { - #[cfg(debug_assertions)] - { - assert!(self.n() <= a.n()); - } - - let min_size: usize = self.size().min(a.size()); - let n: usize = self.n(); - - self.data.zero(); - (0..min_size).for_each(|i| { - let data_lwe: &mut [i64] = self.data.at_mut(0, i); - data_lwe[0] = a.data.at(0, i)[0]; - data_lwe[1..].copy_from_slice(&a.data.at(1, i)[..n]); - }); - } - - pub fn from_glwe<DGlwe, DKs, B: Backend>( - &mut self, - module: &Module<B>, - a: &GLWECiphertext<DGlwe>, - ks: &GLWEToLWESwitchingKeyExec<DKs, B>, - scratch: &mut Scratch<B>, - ) where - DGlwe: DataRef, - DKs: DataRef, - Module<B>: GLWEKeyswitchFamily<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - assert_eq!(self.basek(), a.basek()); - assert_eq!(a.n(), ks.n()); - } - let (mut tmp_glwe, scratch1) = scratch.take_glwe_ct(a.n(), a.basek(), self.k(), 1); - tmp_glwe.keyswitch(module, a, &ks.0, scratch1); - self.sample_extract(&tmp_glwe); - } - - pub fn keyswitch<A, DKs, B: Backend>( - &mut self, - module: &Module<B>, - a: &LWECiphertext<A>, - ksk: &LWESwitchingKeyExec<DKs, B>, - scratch: &mut Scratch<B>, - ) where - A: DataRef, - DKs: DataRef, - Module<B>: GLWEKeyswitchFamily<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - assert!(self.n() <= module.n()); - assert!(a.n() <= module.n()); - assert_eq!(self.basek(), a.basek()); - } - - let max_k: usize = self.k().max(a.k()); - let basek: usize = self.basek(); - - let (mut glwe, scratch1) = scratch.take_glwe_ct(ksk.n(), basek, max_k, 1); - glwe.data.zero(); - - let n_lwe: usize = a.n(); - - (0..a.size()).for_each(|i| { - let data_lwe: &[i64] = a.data.at(0, i); - glwe.data.at_mut(0, i)[0] = data_lwe[0]; - glwe.data.at_mut(1, i)[..n_lwe].copy_from_slice(&data_lwe[1..]); - }); - - glwe.keyswitch_inplace(module, &ksk.0, scratch1); - - self.sample_extract(&glwe); - } -} - -impl GLWECiphertext<Vec<u8>> { - pub fn from_lwe_scratch_space<B: Backend>( - module: &Module<B>, - n: usize, - basek: usize, - k_lwe: usize, - k_glwe: usize, - k_ksk: usize, - rank: usize, - ) -> usize - where - Module<B>: GLWEKeyswitchFamily<B>, - { - GLWECiphertext::keyswitch_scratch_space(module, n, basek, k_glwe, k_lwe, k_ksk, 1, 1, rank) - + GLWECiphertext::bytes_of(n, basek, k_lwe, 1) - } -} - -impl<D: DataMut> GLWECiphertext<D> { - pub fn from_lwe<DLwe, DKsk, B: Backend>( - &mut self, - module: &Module<B>, - lwe: &LWECiphertext<DLwe>, - ksk: &LWEToGLWESwitchingKeyExec<DKsk, B>, - scratch: &mut Scratch<B>, - ) where - DLwe: DataRef, - DKsk: DataRef, - Module<B>: GLWEKeyswitchFamily<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - assert!(lwe.n() <= self.n()); - assert_eq!(self.basek(), self.basek()); - } - - let (mut glwe, scratch1) = scratch.take_glwe_ct(ksk.n(), lwe.basek(), lwe.k(), 1); - glwe.data.zero(); - - let n_lwe: usize = lwe.n(); - - (0..lwe.size()).for_each(|i| { - let data_lwe: &[i64] = lwe.data.at(0, i); - glwe.data.at_mut(0, i)[0] = data_lwe[0]; - glwe.data.at_mut(1, i)[..n_lwe].copy_from_slice(&data_lwe[1..]); - }); - - self.keyswitch(module, &glwe, &ksk.0, scratch1); - } -}
@@ -4,7 +4,7 @@ layouts::{Backend, DataMut, DataRef, Module, ScratchOwned},
oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl}, }; -use crate::{Infos, LWECiphertext, LWESecret, SetMetaData, lwe::LWEPlaintext}; +use crate::layouts::{Infos, LWECiphertext, LWEPlaintext, LWESecret, SetMetaData}; impl<DataSelf> LWECiphertext<DataSelf> where
@@ -1,206 +0,0 @@
-use backend::hal::{ - api::{ - ScratchAvailable, ScratchOwnedAlloc, ScratchOwnedBorrow, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft, VecZnxAddNormal, - VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxFillUniform, VecZnxNormalizeInplace, VecZnxSwithcDegree, - ZnxView, ZnxViewMut, ZnxZero, - }, - layouts::{Backend, DataMut, DataRef, Module, Scratch, ScratchOwned, VecZnx}, - oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl}, -}; -use sampling::source::Source; - -use crate::{ - GGLWEEncryptSkFamily, GLWESecret, GLWEToLWESwitchingKey, Infos, LWECiphertext, LWESecret, LWESwitchingKey, - LWEToGLWESwitchingKey, SIX_SIGMA, TakeGLWESecret, TakeGLWESecretExec, lwe::LWEPlaintext, -}; - -impl<DataSelf: DataMut> LWECiphertext<DataSelf> { - pub fn encrypt_sk<DataPt, DataSk, B: Backend>( - &mut self, - module: &Module<B>, - pt: &LWEPlaintext<DataPt>, - sk: &LWESecret<DataSk>, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - ) where - DataPt: DataRef, - DataSk: DataRef, - Module<B>: VecZnxFillUniform + VecZnxAddNormal + VecZnxNormalizeInplace<B>, - B: ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, - { - #[cfg(debug_assertions)] - { - assert_eq!(self.n(), sk.n()) - } - - let basek: usize = self.basek(); - let k: usize = self.k(); - - module.vec_znx_fill_uniform(basek, &mut self.data, 0, k, source_xa); - - let mut tmp_znx: VecZnx<Vec<u8>> = VecZnx::alloc(1, 1, self.size()); - - let min_size = self.size().min(pt.size()); - - (0..min_size).for_each(|i| { - tmp_znx.at_mut(0, i)[0] = pt.data.at(0, i)[0] - - self.data.at(0, i)[1..] - .iter() - .zip(sk.data.at(0, 0)) - .map(|(x, y)| x * y) - .sum::<i64>(); - }); - - (min_size..self.size()).for_each(|i| { - tmp_znx.at_mut(0, i)[0] -= self.data.at(0, i)[1..] - .iter() - .zip(sk.data.at(0, 0)) - .map(|(x, y)| x * y) - .sum::<i64>(); - }); - - module.vec_znx_add_normal( - basek, - &mut self.data, - 0, - k, - source_xe, - sigma, - sigma * SIX_SIGMA, - ); - - module.vec_znx_normalize_inplace( - basek, - &mut tmp_znx, - 0, - ScratchOwned::alloc(size_of::<i64>()).borrow(), - ); - - (0..self.size()).for_each(|i| { - self.data.at_mut(0, i)[0] = tmp_znx.at(0, i)[0]; - }); - } -} - -impl<D: DataMut> GLWEToLWESwitchingKey<D> { - pub fn encrypt_sk<DLwe, DGlwe, B: Backend>( - &mut self, - module: &Module<B>, - sk_lwe: &LWESecret<DLwe>, - sk_glwe: &GLWESecret<DGlwe>, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, - ) where - DLwe: DataRef, - DGlwe: DataRef, - Module<B>: GGLWEEncryptSkFamily<B> + VecZnxAutomorphismInplace + VecZnxSwithcDegree + VecZnxAddScalarInplace, - Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - assert!(sk_lwe.n() <= module.n()); - } - - let (mut sk_lwe_as_glwe, scratch1) = scratch.take_glwe_secret(sk_glwe.n(), 1); - sk_lwe_as_glwe.data.zero(); - sk_lwe_as_glwe.data.at_mut(0, 0)[..sk_lwe.n()].copy_from_slice(sk_lwe.data.at(0, 0)); - module.vec_znx_automorphism_inplace(-1, &mut sk_lwe_as_glwe.data.as_vec_znx_mut(), 0); - - self.0.encrypt_sk( - module, - sk_glwe, - &sk_lwe_as_glwe, - source_xa, - source_xe, - sigma, - scratch1, - ); - } -} - -impl<D: DataMut> LWEToGLWESwitchingKey<D> { - pub fn encrypt_sk<DLwe, DGlwe, B: Backend>( - &mut self, - module: &Module<B>, - sk_lwe: &LWESecret<DLwe>, - sk_glwe: &GLWESecret<DGlwe>, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, - ) where - DLwe: DataRef, - DGlwe: DataRef, - Module<B>: GGLWEEncryptSkFamily<B> + VecZnxAutomorphismInplace + VecZnxSwithcDegree + VecZnxAddScalarInplace, - Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - assert!(sk_lwe.n() <= module.n()); - } - - let (mut sk_lwe_as_glwe, scratch1) = scratch.take_glwe_secret(sk_glwe.n(), 1); - sk_lwe_as_glwe.data.at_mut(0, 0)[..sk_lwe.n()].copy_from_slice(sk_lwe.data.at(0, 0)); - sk_lwe_as_glwe.data.at_mut(0, 0)[sk_lwe.n()..].fill(0); - module.vec_znx_automorphism_inplace(-1, &mut sk_lwe_as_glwe.data.as_vec_znx_mut(), 0); - - self.0.encrypt_sk( - module, - &sk_lwe_as_glwe, - &sk_glwe, - source_xa, - source_xe, - sigma, - scratch1, - ); - } -} - -impl<D: DataMut> LWESwitchingKey<D> { - pub fn encrypt_sk<DIn, DOut, B: Backend>( - &mut self, - module: &Module<B>, - sk_lwe_in: &LWESecret<DIn>, - sk_lwe_out: &LWESecret<DOut>, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, - ) where - DIn: DataRef, - DOut: DataRef, - Module<B>: GGLWEEncryptSkFamily<B> + VecZnxAutomorphismInplace + VecZnxSwithcDegree + VecZnxAddScalarInplace, - Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - assert!(sk_lwe_in.n() <= self.n()); - assert!(sk_lwe_out.n() <= self.n()); - assert!(self.n() <= module.n()); - } - - let (mut sk_in_glwe, scratch1) = scratch.take_glwe_secret(self.n(), 1); - let (mut sk_out_glwe, scratch2) = scratch1.take_glwe_secret(self.n(), 1); - - sk_out_glwe.data.at_mut(0, 0)[..sk_lwe_out.n()].copy_from_slice(sk_lwe_out.data.at(0, 0)); - sk_out_glwe.data.at_mut(0, 0)[sk_lwe_out.n()..].fill(0); - module.vec_znx_automorphism_inplace(-1, &mut sk_out_glwe.data.as_vec_znx_mut(), 0); - - sk_in_glwe.data.at_mut(0, 0)[..sk_lwe_in.n()].copy_from_slice(sk_lwe_in.data.at(0, 0)); - sk_in_glwe.data.at_mut(0, 0)[sk_lwe_in.n()..].fill(0); - module.vec_znx_automorphism_inplace(-1, &mut sk_in_glwe.data.as_vec_znx_mut(), 0); - - self.0.encrypt_sk( - module, - &sk_in_glwe, - &sk_out_glwe, - source_xa, - source_xe, - sigma, - scratch2, - ); - } -}
@@ -1,257 +0,0 @@
-use backend::hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}; - -use crate::{ - GGLWEExecLayoutFamily, GLWESwitchingKeyExec, Infos, - lwe::keyswtich_layouts::{GLWEToLWESwitchingKey, LWESwitchingKey, LWEToGLWESwitchingKey}, -}; - -#[derive(PartialEq, Eq)] -pub struct GLWEToLWESwitchingKeyExec<D: Data, B: Backend>(pub(crate) GLWESwitchingKeyExec<D, B>); - -impl<D: Data, B: Backend> Infos for GLWEToLWESwitchingKeyExec<D, B> { - type Inner = VmpPMat<D, B>; - - fn inner(&self) -> &Self::Inner { - &self.0.inner() - } - - fn basek(&self) -> usize { - self.0.basek() - } - - fn k(&self) -> usize { - self.0.k() - } -} - -impl<D: Data, B: Backend> GLWEToLWESwitchingKeyExec<D, B> { - pub fn digits(&self) -> usize { - self.0.digits() - } - - pub fn rank(&self) -> usize { - self.0.rank() - } - - pub fn rank_in(&self) -> usize { - self.0.rank_in() - } - - pub fn rank_out(&self) -> usize { - self.0.rank_out() - } -} - -impl<B: Backend> GLWEToLWESwitchingKeyExec<Vec<u8>, B> { - pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, rank_in: usize) -> Self - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - Self(GLWESwitchingKeyExec::alloc( - module, n, basek, k, rows, 1, rank_in, 1, - )) - } - - pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize) -> usize - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - GLWESwitchingKeyExec::<Vec<u8>, B>::bytes_of(module, n, basek, k, rows, digits, rank_in, 1) - } - - pub fn from<DataOther: DataRef>( - module: &Module<B>, - other: &GLWEToLWESwitchingKey<DataOther>, - scratch: &mut Scratch<B>, - ) -> Self - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - let mut ksk_exec: GLWEToLWESwitchingKeyExec<Vec<u8>, B> = Self::alloc( - module, - other.0.n(), - other.0.basek(), - other.0.k(), - other.0.rows(), - other.0.rank_in(), - ); - ksk_exec.prepare(module, other, scratch); - ksk_exec - } -} - -impl<D: DataMut, B: Backend> GLWEToLWESwitchingKeyExec<D, B> { - pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GLWEToLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) - where - DataOther: DataRef, - Module<B>: GGLWEExecLayoutFamily<B>, - { - self.0.prepare(module, &other.0, scratch); - } -} - -/// A special [GLWESwitchingKey] required to for the conversion from [LWECiphertext] to [GLWECiphertext]. -#[derive(PartialEq, Eq)] -pub struct LWEToGLWESwitchingKeyExec<D: Data, B: Backend>(pub(crate) GLWESwitchingKeyExec<D, B>); - -impl<D: Data, B: Backend> Infos for LWEToGLWESwitchingKeyExec<D, B> { - type Inner = VmpPMat<D, B>; - - fn inner(&self) -> &Self::Inner { - &self.0.inner() - } - - fn basek(&self) -> usize { - self.0.basek() - } - - fn k(&self) -> usize { - self.0.k() - } -} - -impl<D: Data, B: Backend> LWEToGLWESwitchingKeyExec<D, B> { - pub fn digits(&self) -> usize { - self.0.digits() - } - - pub fn rank(&self) -> usize { - self.0.rank() - } - - pub fn rank_in(&self) -> usize { - self.0.rank_in() - } - - pub fn rank_out(&self) -> usize { - self.0.rank_out() - } -} - -impl<B: Backend> LWEToGLWESwitchingKeyExec<Vec<u8>, B> { - pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, rank_out: usize) -> Self - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - Self(GLWESwitchingKeyExec::alloc( - module, n, basek, k, rows, 1, 1, rank_out, - )) - } - - pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_out: usize) -> usize - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - GLWESwitchingKeyExec::<Vec<u8>, B>::bytes_of(module, n, basek, k, rows, digits, 1, rank_out) - } - - pub fn from<DataOther: DataRef>( - module: &Module<B>, - other: &LWEToGLWESwitchingKey<DataOther>, - scratch: &mut Scratch<B>, - ) -> Self - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - let mut ksk_exec: LWEToGLWESwitchingKeyExec<Vec<u8>, B> = Self::alloc( - module, - other.0.n(), - other.0.basek(), - other.0.k(), - other.0.rows(), - other.0.rank(), - ); - ksk_exec.prepare(module, other, scratch); - ksk_exec - } -} - -impl<D: DataMut, B: Backend> LWEToGLWESwitchingKeyExec<D, B> { - pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &LWEToGLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) - where - DataOther: DataRef, - Module<B>: GGLWEExecLayoutFamily<B>, - { - self.0.prepare(module, &other.0, scratch); - } -} - -#[derive(PartialEq, Eq)] -pub struct LWESwitchingKeyExec<D: Data, B: Backend>(pub(crate) GLWESwitchingKeyExec<D, B>); - -impl<D: Data, B: Backend> Infos for LWESwitchingKeyExec<D, B> { - type Inner = VmpPMat<D, B>; - - fn inner(&self) -> &Self::Inner { - &self.0.inner() - } - - fn basek(&self) -> usize { - self.0.basek() - } - - fn k(&self) -> usize { - self.0.k() - } -} - -impl<D: Data, B: Backend> LWESwitchingKeyExec<D, B> { - pub fn digits(&self) -> usize { - self.0.digits() - } - - pub fn rank(&self) -> usize { - self.0.rank() - } - - pub fn rank_in(&self) -> usize { - self.0.rank_in() - } - - pub fn rank_out(&self) -> usize { - self.0.rank_out() - } -} - -impl<B: Backend> LWESwitchingKeyExec<Vec<u8>, B> { - pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize) -> Self - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - Self(GLWESwitchingKeyExec::alloc( - module, n, basek, k, rows, 1, 1, 1, - )) - } - - pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize) -> usize - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - GLWESwitchingKeyExec::<Vec<u8>, B>::bytes_of(module, n, basek, k, rows, digits, 1, 1) - } - - pub fn from<DataOther: DataRef>(module: &Module<B>, other: &LWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) -> Self - where - Module<B>: GGLWEExecLayoutFamily<B>, - { - let mut ksk_exec: LWESwitchingKeyExec<Vec<u8>, B> = Self::alloc( - module, - other.0.n(), - other.0.basek(), - other.0.k(), - other.0.rows(), - ); - ksk_exec.prepare(module, other, scratch); - ksk_exec - } -} - -impl<D: DataMut, B: Backend> LWESwitchingKeyExec<D, B> { - pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &LWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) - where - DataOther: DataRef, - Module<B>: GGLWEExecLayoutFamily<B>, - { - self.0.prepare(module, &other.0, scratch); - } -}
@@ -1,270 +0,0 @@
-use backend::hal::{ - api::{FillUniform, Reset}, - layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, WriterTo}, -}; - -use crate::{GGLWEEncryptSkFamily, GLWESecret, GLWESecretExec, GLWESwitchingKey, Infos}; - -use std::fmt; - -/// A special [GLWESwitchingKey] required to for the conversion from [GLWECiphertext] to [LWECiphertext]. -#[derive(PartialEq, Eq, Clone)] -pub struct GLWEToLWESwitchingKey<D: Data>(pub(crate) GLWESwitchingKey<D>); - -impl<D: DataRef> fmt::Debug for GLWEToLWESwitchingKey<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl<D: DataMut> FillUniform for GLWEToLWESwitchingKey<D> { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.0.fill_uniform(source); - } -} - -impl<D: DataMut> Reset for GLWEToLWESwitchingKey<D> { - fn reset(&mut self) { - self.0.reset(); - } -} - -impl<D: DataRef> fmt::Display for GLWEToLWESwitchingKey<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "(GLWEToLWESwitchingKey) {}", self.0) - } -} - -impl<D: Data> Infos for GLWEToLWESwitchingKey<D> { - type Inner = MatZnx<D>; - - fn inner(&self) -> &Self::Inner { - &self.0.inner() - } - - fn basek(&self) -> usize { - self.0.basek() - } - - fn k(&self) -> usize { - self.0.k() - } -} - -impl<D: Data> GLWEToLWESwitchingKey<D> { - pub fn digits(&self) -> usize { - self.0.digits() - } - - pub fn rank(&self) -> usize { - self.0.rank() - } - - pub fn rank_in(&self) -> usize { - self.0.rank_in() - } - - pub fn rank_out(&self) -> usize { - self.0.rank_out() - } -} - -impl<D: DataMut> ReaderFrom for GLWEToLWESwitchingKey<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - self.0.read_from(reader) - } -} - -impl<D: DataRef> WriterTo for GLWEToLWESwitchingKey<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - self.0.write_to(writer) - } -} - -impl GLWEToLWESwitchingKey<Vec<u8>> { - pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, rank_in: usize) -> Self { - Self(GLWESwitchingKey::alloc(n, basek, k, rows, 1, rank_in, 1)) - } - - pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank_in: usize) -> usize - where - Module<B>: GGLWEEncryptSkFamily<B>, - { - GLWESecretExec::bytes_of(module, n, rank_in) - + (GLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank_in, 1) | GLWESecret::bytes_of(n, rank_in)) - } -} - -#[derive(PartialEq, Eq, Clone)] -pub struct LWEToGLWESwitchingKey<D: Data>(pub(crate) GLWESwitchingKey<D>); - -impl<D: DataRef> fmt::Debug for LWEToGLWESwitchingKey<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl<D: DataMut> FillUniform for LWEToGLWESwitchingKey<D> { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.0.fill_uniform(source); - } -} - -impl<D: DataMut> Reset for LWEToGLWESwitchingKey<D> { - fn reset(&mut self) { - self.0.reset(); - } -} - -impl<D: DataRef> fmt::Display for LWEToGLWESwitchingKey<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "(LWEToGLWESwitchingKey) {}", self.0) - } -} - -impl<D: Data> Infos for LWEToGLWESwitchingKey<D> { - type Inner = MatZnx<D>; - - fn inner(&self) -> &Self::Inner { - &self.0.inner() - } - - fn basek(&self) -> usize { - self.0.basek() - } - - fn k(&self) -> usize { - self.0.k() - } -} - -impl<D: Data> LWEToGLWESwitchingKey<D> { - pub fn digits(&self) -> usize { - self.0.digits() - } - - pub fn rank(&self) -> usize { - self.0.rank() - } - - pub fn rank_in(&self) -> usize { - self.0.rank_in() - } - - pub fn rank_out(&self) -> usize { - self.0.rank_out() - } -} - -impl<D: DataMut> ReaderFrom for LWEToGLWESwitchingKey<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - self.0.read_from(reader) - } -} - -impl<D: DataRef> WriterTo for LWEToGLWESwitchingKey<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - self.0.write_to(writer) - } -} - -impl LWEToGLWESwitchingKey<Vec<u8>> { - pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, rank_out: usize) -> Self { - Self(GLWESwitchingKey::alloc(n, basek, k, rows, 1, 1, rank_out)) - } - - pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank_out: usize) -> usize - where - Module<B>: GGLWEEncryptSkFamily<B>, - { - GLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, 1, rank_out) + GLWESecret::bytes_of(n, 1) - } -} - -#[derive(PartialEq, Eq, Clone)] -pub struct LWESwitchingKey<D: Data>(pub(crate) GLWESwitchingKey<D>); - -impl<D: DataRef> fmt::Debug for LWESwitchingKey<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl<D: DataMut> FillUniform for LWESwitchingKey<D> { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.0.fill_uniform(source); - } -} - -impl<D: DataMut> Reset for LWESwitchingKey<D> { - fn reset(&mut self) { - self.0.reset(); - } -} - -impl<D: DataRef> fmt::Display for LWESwitchingKey<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "(LWESwitchingKey) {}", self.0) - } -} - -impl<D: Data> Infos for LWESwitchingKey<D> { - type Inner = MatZnx<D>; - - fn inner(&self) -> &Self::Inner { - &self.0.inner() - } - - fn basek(&self) -> usize { - self.0.basek() - } - - fn k(&self) -> usize { - self.0.k() - } -} - -impl<D: Data> LWESwitchingKey<D> { - pub fn digits(&self) -> usize { - self.0.digits() - } - - pub fn rank(&self) -> usize { - self.0.rank() - } - - pub fn rank_in(&self) -> usize { - self.0.rank_in() - } - - pub fn rank_out(&self) -> usize { - self.0.rank_out() - } -} - -impl<D: DataMut> ReaderFrom for LWESwitchingKey<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - self.0.read_from(reader) - } -} - -impl<D: DataRef> WriterTo for LWESwitchingKey<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - self.0.write_to(writer) - } -} - -impl LWESwitchingKey<Vec<u8>> { - pub fn alloc(n: usize, basek: usize, k: usize, rows: usize) -> Self { - Self(GLWESwitchingKey::alloc(n, basek, k, rows, 1, 1, 1)) - } - - pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize) -> usize - where - Module<B>: GGLWEEncryptSkFamily<B>, - { - GLWESecret::bytes_of(n, 1) - + GLWESecretExec::bytes_of(module, n, 1) - + GLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, 1, 1) - } -}
@@ -6,8 +6,6 @@ layouts::{Data, DataMut, DataRef, ReaderFrom, VecZnx, VecZnxToMut, VecZnxToRef, WriterTo},
}; use sampling::source::Source; -use crate::{Infos, SetMetaData}; - #[derive(PartialEq, Eq, Clone)] pub struct LWECiphertext<D: Data> { pub(crate) data: VecZnx<D>,@@ -126,6 +124,8 @@ }
} use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; + +use crate::layouts::{Infos, SetMetaData}; impl<D: DataMut> ReaderFrom for LWECiphertext<D> { fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
@@ -1,398 +0,0 @@
-use std::fmt; - -use backend::hal::{ - api::{FillUniform, Reset, VecZnxFillUniform, ZnxInfos, ZnxView, ZnxViewMut}, - layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, VecZnx, WriterTo}, -}; -use sampling::source::Source; - -use crate::{ - Decompress, GGLWEEncryptSkFamily, GLWESwitchingKeyCompressed, GLWEToLWESwitchingKey, Infos, LWECiphertext, LWESwitchingKey, - LWEToGLWESwitchingKey, SetMetaData, -}; - -#[derive(PartialEq, Eq, Clone)] -pub struct LWECiphertextCompressed<D: Data> { - pub(crate) data: VecZnx<D>, - pub(crate) k: usize, - pub(crate) basek: usize, - pub(crate) seed: [u8; 32], -} - -impl<D: DataRef> fmt::Debug for LWECiphertextCompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl<D: DataRef> fmt::Display for LWECiphertextCompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "LWECiphertextCompressed: basek={} k={} seed={:?}: {}", - self.basek(), - self.k(), - self.seed, - self.data - ) - } -} - -impl<D: DataMut> Reset for LWECiphertextCompressed<D> -where - VecZnx<D>: Reset, -{ - fn reset(&mut self) { - self.data.reset(); - self.basek = 0; - self.k = 0; - self.seed = [0u8; 32]; - } -} - -impl<D: DataMut> FillUniform for LWECiphertextCompressed<D> { - fn fill_uniform(&mut self, source: &mut Source) { - self.data.fill_uniform(source); - } -} - -impl LWECiphertextCompressed<Vec<u8>> { - pub fn alloc(basek: usize, k: usize) -> Self { - Self { - data: VecZnx::alloc(1, 1, k.div_ceil(basek)), - k: k, - basek: basek, - seed: [0u8; 32], - } - } -} - -impl<D: Data> Infos for LWECiphertextCompressed<D> -where - VecZnx<D>: ZnxInfos, -{ - type Inner = VecZnx<D>; - - fn n(&self) -> usize { - &self.inner().n() - 1 - } - - fn inner(&self) -> &Self::Inner { - &self.data - } - - fn basek(&self) -> usize { - self.basek - } - - fn k(&self) -> usize { - self.k - } -} - -impl<DataSelf: DataMut> SetMetaData for LWECiphertextCompressed<DataSelf> { - fn set_k(&mut self, k: usize) { - self.k = k - } - - fn set_basek(&mut self, basek: usize) { - self.basek = basek - } -} - -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; - -impl<D: DataMut> ReaderFrom for LWECiphertextCompressed<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - self.k = reader.read_u64::<LittleEndian>()? as usize; - self.basek = reader.read_u64::<LittleEndian>()? as usize; - reader.read(&mut self.seed)?; - self.data.read_from(reader) - } -} - -impl<D: DataRef> WriterTo for LWECiphertextCompressed<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::<LittleEndian>(self.k as u64)?; - writer.write_u64::<LittleEndian>(self.basek as u64)?; - writer.write_all(&self.seed)?; - self.data.write_to(writer) - } -} - -impl<D: DataMut, B: Backend, DR: DataRef> Decompress<B, LWECiphertextCompressed<DR>> for LWECiphertext<D> { - fn decompress(&mut self, module: &Module<B>, other: &LWECiphertextCompressed<DR>) - where - Module<B>: VecZnxFillUniform, - { - let mut source = Source::new(other.seed); - module.vec_znx_fill_uniform(other.basek(), &mut self.data, 0, other.k(), &mut source); - (0..self.size()).for_each(|i| { - self.data.at_mut(0, i)[0] = other.data.at(0, i)[0]; - }); - } -} - -#[derive(PartialEq, Eq, Clone)] -pub struct GLWEToLWESwitchingKeyCompressed<D: Data>(pub(crate) GLWESwitchingKeyCompressed<D>); - -impl<D: DataRef> fmt::Debug for GLWEToLWESwitchingKeyCompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl<D: DataMut> FillUniform for GLWEToLWESwitchingKeyCompressed<D> { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.0.fill_uniform(source); - } -} - -impl<D: DataMut> Reset for GLWEToLWESwitchingKeyCompressed<D> { - fn reset(&mut self) { - self.0.reset(); - } -} - -impl<D: DataRef> fmt::Display for GLWEToLWESwitchingKeyCompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "(GLWEToLWESwitchingKeyCompressed) {}", self.0) - } -} - -impl<D: Data> Infos for GLWEToLWESwitchingKeyCompressed<D> { - type Inner = MatZnx<D>; - - fn inner(&self) -> &Self::Inner { - &self.0.inner() - } - - fn basek(&self) -> usize { - self.0.basek() - } - - fn k(&self) -> usize { - self.0.k() - } -} - -impl<D: Data> GLWEToLWESwitchingKeyCompressed<D> { - pub fn digits(&self) -> usize { - self.0.digits() - } - - pub fn rank(&self) -> usize { - self.0.rank() - } - - pub fn rank_in(&self) -> usize { - self.0.rank_in() - } - - pub fn rank_out(&self) -> usize { - self.0.rank_out() - } -} - -impl<D: DataMut> ReaderFrom for GLWEToLWESwitchingKeyCompressed<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - self.0.read_from(reader) - } -} - -impl<D: DataRef> WriterTo for GLWEToLWESwitchingKeyCompressed<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - self.0.write_to(writer) - } -} - -impl GLWEToLWESwitchingKeyCompressed<Vec<u8>> { - pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, rank_in: usize) -> Self { - Self(GLWESwitchingKeyCompressed::alloc( - n, basek, k, rows, 1, rank_in, 1, - )) - } - - pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank_in: usize) -> usize - where - Module<B>: GGLWEEncryptSkFamily<B>, - { - GLWEToLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank_in) - } -} - -#[derive(PartialEq, Eq, Clone)] -pub struct LWEToGLWESwitchingKeyCompressed<D: Data>(pub(crate) GLWESwitchingKeyCompressed<D>); - -impl<D: DataRef> fmt::Debug for LWEToGLWESwitchingKeyCompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl<D: DataMut> FillUniform for LWEToGLWESwitchingKeyCompressed<D> { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.0.fill_uniform(source); - } -} - -impl<D: DataMut> Reset for LWEToGLWESwitchingKeyCompressed<D> { - fn reset(&mut self) { - self.0.reset(); - } -} - -impl<D: DataRef> fmt::Display for LWEToGLWESwitchingKeyCompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "(LWEToGLWESwitchingKeyCompressed) {}", self.0) - } -} - -impl<D: Data> Infos for LWEToGLWESwitchingKeyCompressed<D> { - type Inner = MatZnx<D>; - - fn inner(&self) -> &Self::Inner { - &self.0.inner() - } - - fn basek(&self) -> usize { - self.0.basek() - } - - fn k(&self) -> usize { - self.0.k() - } -} - -impl<D: Data> LWEToGLWESwitchingKeyCompressed<D> { - pub fn digits(&self) -> usize { - self.0.digits() - } - - pub fn rank(&self) -> usize { - self.0.rank() - } - - pub fn rank_in(&self) -> usize { - self.0.rank_in() - } - - pub fn rank_out(&self) -> usize { - self.0.rank_out() - } -} - -impl<D: DataMut> ReaderFrom for LWEToGLWESwitchingKeyCompressed<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - self.0.read_from(reader) - } -} - -impl<D: DataRef> WriterTo for LWEToGLWESwitchingKeyCompressed<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - self.0.write_to(writer) - } -} - -impl LWEToGLWESwitchingKeyCompressed<Vec<u8>> { - pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, rank_out: usize) -> Self { - Self(GLWESwitchingKeyCompressed::alloc( - n, basek, k, rows, 1, 1, rank_out, - )) - } - - pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank_out: usize) -> usize - where - Module<B>: GGLWEEncryptSkFamily<B>, - { - LWEToGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank_out) - } -} - -#[derive(PartialEq, Eq, Clone)] -pub struct LWESwitchingKeyCompressed<D: Data>(pub(crate) GLWESwitchingKeyCompressed<D>); - -impl<D: DataRef> fmt::Debug for LWESwitchingKeyCompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl<D: DataMut> FillUniform for LWESwitchingKeyCompressed<D> { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.0.fill_uniform(source); - } -} - -impl<D: DataMut> Reset for LWESwitchingKeyCompressed<D> { - fn reset(&mut self) { - self.0.reset(); - } -} - -impl<D: DataRef> fmt::Display for LWESwitchingKeyCompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "(LWESwitchingKeyCompressed) {}", self.0) - } -} - -impl<D: Data> Infos for LWESwitchingKeyCompressed<D> { - type Inner = MatZnx<D>; - - fn inner(&self) -> &Self::Inner { - &self.0.inner() - } - - fn basek(&self) -> usize { - self.0.basek() - } - - fn k(&self) -> usize { - self.0.k() - } -} - -impl<D: Data> LWESwitchingKeyCompressed<D> { - pub fn digits(&self) -> usize { - self.0.digits() - } - - pub fn rank(&self) -> usize { - self.0.rank() - } - - pub fn rank_in(&self) -> usize { - self.0.rank_in() - } - - pub fn rank_out(&self) -> usize { - self.0.rank_out() - } -} - -impl<D: DataMut> ReaderFrom for LWESwitchingKeyCompressed<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - self.0.read_from(reader) - } -} - -impl<D: DataRef> WriterTo for LWESwitchingKeyCompressed<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - self.0.write_to(writer) - } -} - -impl LWESwitchingKeyCompressed<Vec<u8>> { - pub fn alloc(n: usize, basek: usize, k: usize, rows: usize) -> Self { - Self(GLWESwitchingKeyCompressed::alloc( - n, basek, k, rows, 1, 1, 1, - )) - } - - pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize) -> usize - where - Module<B>: GGLWEEncryptSkFamily<B>, - { - LWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k) - } -}
@@ -1,19 +0,0 @@
-mod conversion; -mod decryption; -mod encryption; -mod keyswitch_layouts_exec; -mod keyswtich_layouts; -mod layouts; -mod layouts_compressed; -mod plaintext; -mod secret; - -pub use keyswitch_layouts_exec::*; -pub use keyswtich_layouts::*; -pub use layouts::*; -pub use layouts_compressed::*; -pub use plaintext::*; -pub use secret::*; - -#[cfg(test)] -pub mod tests;
@@ -1,6 +1,6 @@
use backend::hal::layouts::{Data, DataMut, DataRef, VecZnx, VecZnxToMut, VecZnxToRef}; -use crate::{Infos, SetMetaData}; +use crate::layouts::{Infos, SetMetaData}; pub struct LWEPlaintext<D: Data> { pub(crate) data: VecZnx<D>,
@@ -4,7 +4,7 @@ layouts::{Data, DataMut, ScalarZnx},
}; use sampling::source::Source; -use crate::Distribution; +use crate::dist::Distribution; pub struct LWESecret<D: Data> { pub(crate) data: ScalarZnx<D>,
@@ -3,7 +3,7 @@ hal::{api::ModuleNew, layouts::Module},
implementation::cpu_spqlios::FFT64, }; -use crate::tests::generic_conversion::{test_glwe_to_lwe, test_keyswitch, test_lwe_to_glwe}; +use crate::tests::generics::{keyswitch::test_lwe_keyswitch, test_glwe_to_lwe, test_lwe_to_glwe}; #[test] fn lwe_to_glwe() {@@ -20,8 +20,8 @@ test_glwe_to_lwe(&module)
} #[test] -fn keyswitch() { +fn lwe_keyswitch() { let log_n: usize = 5; let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); - test_keyswitch(&module) + test_lwe_keyswitch(&module) }
@@ -1,258 +0,0 @@
-use backend::hal::{ - api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxEncodeCoeffsi64, - VecZnxSwithcDegree, ZnxView, - }, - layouts::{Backend, Module, ScratchOwned}, - oep::{ - ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, - TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, - }, -}; -use sampling::source::Source; - -use crate::{ - GGLWEEncryptSkFamily, GGLWEExecLayoutFamily, GLWECiphertext, GLWEDecryptFamily, GLWEKeyswitchFamily, GLWEPlaintext, - GLWESecret, GLWESecretExec, GLWEToLWESwitchingKey, GLWEToLWESwitchingKeyExec, Infos, LWECiphertext, LWEPlaintext, LWESecret, - LWESwitchingKey, LWESwitchingKeyExec, LWEToGLWESwitchingKey, LWEToGLWESwitchingKeyExec, -}; - -pub(crate) trait LWETestModuleFamily<B: Backend> = GGLWEEncryptSkFamily<B> - + GLWEDecryptFamily<B> - + VecZnxSwithcDegree - + VecZnxAddScalarInplace - + GGLWEExecLayoutFamily<B> - + GLWEKeyswitchFamily<B> - + VecZnxEncodeCoeffsi64 - + VecZnxAutomorphismInplace; - -pub(crate) trait LWETestScratchFamily<B: Backend> = TakeScalarZnxImpl<B> - + TakeVecZnxDftImpl<B> - + ScratchAvailableImpl<B> - + TakeVecZnxImpl<B> - + TakeVecZnxBigImpl<B> - + TakeSvpPPolImpl<B> - + ScratchOwnedAllocImpl<B> - + ScratchOwnedBorrowImpl<B>; - -pub(crate) fn test_lwe_to_glwe<B: Backend>(module: &Module<B>) -where - Module<B>: LWETestModuleFamily<B>, - B: LWETestScratchFamily<B>, -{ - let n: usize = module.n(); - let basek: usize = 17; - let sigma: f64 = 3.2; - - let rank: usize = 2; - - let n_lwe: usize = 22; - let k_lwe_ct: usize = 2 * basek; - let k_lwe_pt: usize = 8; - - let k_glwe_ct: usize = 3 * basek; - - let k_ksk: usize = k_lwe_ct + basek; - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - LWEToGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank) - | GLWECiphertext::from_lwe_scratch_space(module, n, basek, k_lwe_ct, k_glwe_ct, k_ksk, rank) - | GLWECiphertext::decrypt_scratch_space(module, n, basek, k_glwe_ct), - ); - - let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk_glwe.fill_ternary_prob(0.5, &mut source_xs); - - let sk_glwe_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_glwe); - - let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe); - sk_lwe.fill_ternary_prob(0.5, &mut source_xs); - - let data: i64 = 17; - - let mut lwe_pt: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_pt); - module.encode_coeff_i64(basek, &mut lwe_pt.data, 0, k_lwe_pt, 0, data, k_lwe_pt); - - let mut lwe_ct: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe, basek, k_lwe_ct); - lwe_ct.encrypt_sk( - module, - &lwe_pt, - &sk_lwe, - &mut source_xa, - &mut source_xe, - sigma, - ); - - let mut ksk: LWEToGLWESwitchingKey<Vec<u8>> = LWEToGLWESwitchingKey::alloc(n, basek, k_ksk, lwe_ct.size(), rank); - - ksk.encrypt_sk( - module, - &sk_lwe, - &sk_glwe, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut glwe_ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_glwe_ct, rank); - - let ksk_exec: LWEToGLWESwitchingKeyExec<Vec<u8>, B> = LWEToGLWESwitchingKeyExec::from(module, &ksk, scratch.borrow()); - - glwe_ct.from_lwe(module, &lwe_ct, &ksk_exec, scratch.borrow()); - - let mut glwe_pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_glwe_ct); - glwe_ct.decrypt(module, &mut glwe_pt, &sk_glwe_exec, scratch.borrow()); - - assert_eq!(glwe_pt.data.at(0, 0)[0], lwe_pt.data.at(0, 0)[0]); -} - -pub(crate) fn test_glwe_to_lwe<B: Backend>(module: &Module<B>) -where - Module<B>: LWETestModuleFamily<B>, - B: LWETestScratchFamily<B>, -{ - let n: usize = module.n(); - let basek: usize = 17; - let sigma: f64 = 3.2; - - let rank: usize = 2; - - let n_lwe: usize = 22; - let k_lwe_ct: usize = 2 * basek; - let k_lwe_pt: usize = 8; - - let k_glwe_ct: usize = 3 * basek; - - let k_ksk: usize = k_lwe_ct + basek; - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - LWEToGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank) - | LWECiphertext::from_glwe_scratch_space(module, n, basek, k_lwe_ct, k_glwe_ct, k_ksk, rank) - | GLWECiphertext::decrypt_scratch_space(module, n, basek, k_glwe_ct), - ); - - let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk_glwe.fill_ternary_prob(0.5, &mut source_xs); - - let sk_glwe_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_glwe); - - let mut sk_lwe = LWESecret::alloc(n_lwe); - sk_lwe.fill_ternary_prob(0.5, &mut source_xs); - - let data: i64 = 17; - let mut glwe_pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_glwe_ct); - module.encode_coeff_i64(basek, &mut glwe_pt.data, 0, k_lwe_pt, 0, data, k_lwe_pt); - - let mut glwe_ct = GLWECiphertext::alloc(n, basek, k_glwe_ct, rank); - glwe_ct.encrypt_sk( - module, - &glwe_pt, - &sk_glwe_exec, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut ksk: GLWEToLWESwitchingKey<Vec<u8>> = GLWEToLWESwitchingKey::alloc(n, basek, k_ksk, glwe_ct.size(), rank); - - ksk.encrypt_sk( - module, - &sk_lwe, - &sk_glwe, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut lwe_ct: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe, basek, k_lwe_ct); - - let ksk_exec: GLWEToLWESwitchingKeyExec<Vec<u8>, B> = GLWEToLWESwitchingKeyExec::from(module, &ksk, scratch.borrow()); - - lwe_ct.from_glwe(module, &glwe_ct, &ksk_exec, scratch.borrow()); - - let mut lwe_pt: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_ct); - lwe_ct.decrypt(module, &mut lwe_pt, &sk_lwe); - - assert_eq!(glwe_pt.data.at(0, 0)[0], lwe_pt.data.at(0, 0)[0]); -} - -pub(crate) fn test_keyswitch<B: Backend>(module: &Module<B>) -where - Module<B>: LWETestModuleFamily<B>, - B: LWETestScratchFamily<B>, -{ - let n: usize = module.n(); - let basek: usize = 17; - let sigma: f64 = 3.2; - - let n_lwe_in: usize = 22; - let n_lwe_out: usize = 30; - let k_lwe_ct: usize = 2 * basek; - let k_lwe_pt: usize = 8; - - let k_ksk: usize = k_lwe_ct + basek; - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - LWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk) - | LWECiphertext::keyswitch_scratch_space(module, n, basek, k_lwe_ct, k_lwe_ct, k_ksk), - ); - - let mut sk_lwe_in: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe_in); - sk_lwe_in.fill_ternary_prob(0.5, &mut source_xs); - - let mut sk_lwe_out: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe_out); - sk_lwe_out.fill_ternary_prob(0.5, &mut source_xs); - - let data: i64 = 17; - - let mut lwe_pt_in: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_pt); - module.encode_coeff_i64(basek, &mut lwe_pt_in.data, 0, k_lwe_pt, 0, data, k_lwe_pt); - - let mut lwe_ct_in: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe_in, basek, k_lwe_ct); - lwe_ct_in.encrypt_sk( - module, - &lwe_pt_in, - &sk_lwe_in, - &mut source_xa, - &mut source_xe, - sigma, - ); - - let mut ksk: LWESwitchingKey<Vec<u8>> = LWESwitchingKey::alloc(n, basek, k_ksk, lwe_ct_in.size()); - - ksk.encrypt_sk( - module, - &sk_lwe_in, - &sk_lwe_out, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut lwe_ct_out: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe_out, basek, k_lwe_ct); - - let ksk_exec: LWESwitchingKeyExec<Vec<u8>, B> = LWESwitchingKeyExec::from(module, &ksk, scratch.borrow()); - - lwe_ct_out.keyswitch(module, &lwe_ct_in, &ksk_exec, scratch.borrow()); - - let mut lwe_pt_out: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_ct); - lwe_ct_out.decrypt(module, &mut lwe_pt_out, &sk_lwe_out); - - assert_eq!(lwe_pt_in.data.at(0, 0)[0], lwe_pt_out.data.at(0, 0)[0]); -}
@@ -1,54 +0,0 @@
-use backend::hal::tests::serialization::test_reader_writer_interface; - -use crate::{ - GLWEToLWESwitchingKey, GLWEToLWESwitchingKeyCompressed, LWECiphertext, LWECiphertextCompressed, LWESwitchingKey, - LWESwitchingKeyCompressed, LWEToGLWESwitchingKey, LWEToGLWESwitchingKeyCompressed, -}; - -#[test] -fn lwe_serialization() { - let original: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(771, 12, 54); - test_reader_writer_interface(original); -} - -#[test] -fn lwe_compressed_serialization() { - let original: LWECiphertextCompressed<Vec<u8>> = LWECiphertextCompressed::alloc(12, 54); - test_reader_writer_interface(original); -} - -#[test] -fn glwe_to_lwe_switching_key_serialization() { - let original: GLWEToLWESwitchingKey<Vec<u8>> = GLWEToLWESwitchingKey::alloc(1024, 12, 54, 2, 2); - test_reader_writer_interface(original); -} - -#[test] -fn glwe_to_lwe_switching_key_compressed_serialization() { - let original: GLWEToLWESwitchingKeyCompressed<Vec<u8>> = GLWEToLWESwitchingKeyCompressed::alloc(1024, 12, 54, 2, 2); - test_reader_writer_interface(original); -} - -#[test] -fn lwe_to_glwe_switching_key_serialization() { - let original: LWEToGLWESwitchingKey<Vec<u8>> = LWEToGLWESwitchingKey::alloc(1024, 12, 54, 2, 2); - test_reader_writer_interface(original); -} - -#[test] -fn lwe_to_glwe_switching_key_compressed_serialization() { - let original: LWEToGLWESwitchingKeyCompressed<Vec<u8>> = LWEToGLWESwitchingKeyCompressed::alloc(1024, 12, 54, 2, 2); - test_reader_writer_interface(original); -} - -#[test] -fn lwe_switching_key_serialization() { - let original: LWESwitchingKey<Vec<u8>> = LWESwitchingKey::alloc(1024, 12, 54, 2); - test_reader_writer_interface(original); -} - -#[test] -fn lwe_switching_key_compressed_serialization() { - let original: LWESwitchingKeyCompressed<Vec<u8>> = LWESwitchingKeyCompressed::alloc(1024, 12, 54, 2); - test_reader_writer_interface(original); -}
@@ -1,4 +0,0 @@
-mod generic_conversion; -mod generic_serialization; - -mod cpu_spqlios;
@@ -1,3 +1,7 @@
+mod gglwe_ct; +mod ggsw_ct; +mod glwe_ct; + #[allow(dead_code)] pub(crate) fn var_noise_gglwe_product( n: f64,
@@ -5,9 +5,15 @@ oep::{TakeMatZnxImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, TakeVmpPMatImpl},
}; use crate::{ - AutomorphismKey, AutomorphismKeyExec, GGLWECiphertext, GGLWECiphertextExec, GGSWCiphertext, GGSWCiphertextExec, - GLWECiphertext, GLWEPlaintext, GLWEPublicKey, GLWEPublicKeyExec, GLWESecret, GLWESecretExec, GLWESwitchingKey, - GLWESwitchingKeyExec, GLWETensorKey, GLWETensorKeyExec, Infos, dist::Distribution, + dist::Distribution, + layouts::{ + GGLWEAutomorphismKey, GGLWECiphertext, GGLWETensorKey, GGSWCiphertext, GLWECiphertext, GLWEPlaintext, GLWEPublicKey, + GLWESecret, GGLWESwitchingKey, Infos, + prepared::{ + GGLWEAutomorphismKeyExec, GGLWECiphertextExec, GGSWCiphertextExec, GLWEPublicKeyExec, GLWESecretExec, + GGLWESwitchingKeyExec, GGLWETensorKeyExec, + }, + }, }; pub trait TakeLike<'a, B: Backend, T> {@@ -116,7 +122,7 @@ rows: usize,
digits: usize, rank_in: usize, rank_out: usize, - ) -> (GLWESwitchingKey<&mut [u8]>, &mut Self); + ) -> (GGLWESwitchingKey<&mut [u8]>, &mut Self); } pub trait TakeGLWESwitchingKeyExec<B: Backend> {@@ -129,7 +135,7 @@ rows: usize,
digits: usize, rank_in: usize, rank_out: usize, - ) -> (GLWESwitchingKeyExec<&mut [u8], B>, &mut Self); + ) -> (GGLWESwitchingKeyExec<&mut [u8], B>, &mut Self); } pub trait TakeTensorKey<B: Backend> {@@ -141,7 +147,7 @@ k: usize,
rows: usize, digits: usize, rank: usize, - ) -> (GLWETensorKey<&mut [u8]>, &mut Self); + ) -> (GGLWETensorKey<&mut [u8]>, &mut Self); } pub trait TakeTensorKeyExec<B: Backend> {@@ -153,7 +159,7 @@ k: usize,
rows: usize, digits: usize, rank: usize, - ) -> (GLWETensorKeyExec<&mut [u8], B>, &mut Self); + ) -> (GGLWETensorKeyExec<&mut [u8], B>, &mut Self); } pub trait TakeAutomorphismKey<B: Backend> {@@ -165,7 +171,7 @@ k: usize,
rows: usize, digits: usize, rank: usize, - ) -> (AutomorphismKey<&mut [u8]>, &mut Self); + ) -> (GGLWEAutomorphismKey<&mut [u8]>, &mut Self); } pub trait TakeAutomorphismKeyExec<B: Backend> {@@ -177,7 +183,7 @@ k: usize,
rows: usize, digits: usize, rank: usize, - ) -> (AutomorphismKeyExec<&mut [u8], B>, &mut Self); + ) -> (GGLWEAutomorphismKeyExec<&mut [u8], B>, &mut Self); } impl<B: Backend> TakeGLWECt<B> for Scratch<B>@@ -672,10 +678,10 @@ rows: usize,
digits: usize, rank_in: usize, rank_out: usize, - ) -> (GLWESwitchingKey<&mut [u8]>, &mut Self) { + ) -> (GGLWESwitchingKey<&mut [u8]>, &mut Self) { let (data, scratch) = self.take_gglwe(n, basek, k, rows, digits, rank_in, rank_out); ( - GLWESwitchingKey { + GGLWESwitchingKey { key: data, sk_in_n: 0, sk_out_n: 0,@@ -685,18 +691,18 @@ )
} } -impl<'a, B, D> TakeLike<'a, B, GLWESwitchingKey<D>> for Scratch<B> +impl<'a, B, D> TakeLike<'a, B, GGLWESwitchingKey<D>> for Scratch<B> where Scratch<B>: TakeLike<'a, B, GGLWECiphertext<D>, Output = GGLWECiphertext<&'a mut [u8]>>, B: Backend + TakeMatZnxImpl<B>, D: DataRef, { - type Output = GLWESwitchingKey<&'a mut [u8]>; + type Output = GGLWESwitchingKey<&'a mut [u8]>; - fn take_like(&'a mut self, template: &GLWESwitchingKey<D>) -> (Self::Output, &'a mut Self) { + fn take_like(&'a mut self, template: &GGLWESwitchingKey<D>) -> (Self::Output, &'a mut Self) { let (key, scratch) = self.take_like(&template.key); ( - GLWESwitchingKey { + GGLWESwitchingKey { key, sk_in_n: template.sk_in_n, sk_out_n: template.sk_out_n,@@ -719,10 +725,10 @@ rows: usize,
digits: usize, rank_in: usize, rank_out: usize, - ) -> (GLWESwitchingKeyExec<&mut [u8], B>, &mut Self) { + ) -> (GGLWESwitchingKeyExec<&mut [u8], B>, &mut Self) { let (data, scratch) = self.take_gglwe_exec(n, basek, k, rows, digits, rank_in, rank_out); ( - GLWESwitchingKeyExec { + GGLWESwitchingKeyExec { key: data, sk_in_n: 0, sk_out_n: 0,@@ -732,18 +738,18 @@ )
} } -impl<'a, B, D> TakeLike<'a, B, GLWESwitchingKeyExec<D, B>> for Scratch<B> +impl<'a, B, D> TakeLike<'a, B, GGLWESwitchingKeyExec<D, B>> for Scratch<B> where Scratch<B>: TakeLike<'a, B, GGLWECiphertextExec<D, B>, Output = GGLWECiphertextExec<&'a mut [u8], B>>, B: Backend + TakeMatZnxImpl<B>, D: DataRef, { - type Output = GLWESwitchingKeyExec<&'a mut [u8], B>; + type Output = GGLWESwitchingKeyExec<&'a mut [u8], B>; - fn take_like(&'a mut self, template: &GLWESwitchingKeyExec<D, B>) -> (Self::Output, &'a mut Self) { + fn take_like(&'a mut self, template: &GGLWESwitchingKeyExec<D, B>) -> (Self::Output, &'a mut Self) { let (key, scratch) = self.take_like(&template.key); ( - GLWESwitchingKeyExec { + GGLWESwitchingKeyExec { key, sk_in_n: template.sk_in_n, sk_out_n: template.sk_out_n,@@ -765,23 +771,23 @@ k: usize,
rows: usize, digits: usize, rank: usize, - ) -> (AutomorphismKey<&mut [u8]>, &mut Self) { + ) -> (GGLWEAutomorphismKey<&mut [u8]>, &mut Self) { let (data, scratch) = self.take_glwe_switching_key(n, basek, k, rows, digits, rank, rank); - (AutomorphismKey { key: data, p: 0 }, scratch) + (GGLWEAutomorphismKey { key: data, p: 0 }, scratch) } } -impl<'a, B, D> TakeLike<'a, B, AutomorphismKey<D>> for Scratch<B> +impl<'a, B, D> TakeLike<'a, B, GGLWEAutomorphismKey<D>> for Scratch<B> where - Scratch<B>: TakeLike<'a, B, GLWESwitchingKey<D>, Output = GLWESwitchingKey<&'a mut [u8]>>, + Scratch<B>: TakeLike<'a, B, GGLWESwitchingKey<D>, Output = GGLWESwitchingKey<&'a mut [u8]>>, B: Backend + TakeMatZnxImpl<B>, D: DataRef, { - type Output = AutomorphismKey<&'a mut [u8]>; + type Output = GGLWEAutomorphismKey<&'a mut [u8]>; - fn take_like(&'a mut self, template: &AutomorphismKey<D>) -> (Self::Output, &'a mut Self) { + fn take_like(&'a mut self, template: &GGLWEAutomorphismKey<D>) -> (Self::Output, &'a mut Self) { let (key, scratch) = self.take_like(&template.key); - (AutomorphismKey { key, p: template.p }, scratch) + (GGLWEAutomorphismKey { key, p: template.p }, scratch) } }@@ -797,23 +803,23 @@ k: usize,
rows: usize, digits: usize, rank: usize, - ) -> (AutomorphismKeyExec<&mut [u8], B>, &mut Self) { + ) -> (GGLWEAutomorphismKeyExec<&mut [u8], B>, &mut Self) { let (data, scratch) = self.take_glwe_switching_key_exec(n, basek, k, rows, digits, rank, rank); - (AutomorphismKeyExec { key: data, p: 0 }, scratch) + (GGLWEAutomorphismKeyExec { key: data, p: 0 }, scratch) } } -impl<'a, B, D> TakeLike<'a, B, AutomorphismKeyExec<D, B>> for Scratch<B> +impl<'a, B, D> TakeLike<'a, B, GGLWEAutomorphismKeyExec<D, B>> for Scratch<B> where - Scratch<B>: TakeLike<'a, B, GLWESwitchingKeyExec<D, B>, Output = GLWESwitchingKeyExec<&'a mut [u8], B>>, + Scratch<B>: TakeLike<'a, B, GGLWESwitchingKeyExec<D, B>, Output = GGLWESwitchingKeyExec<&'a mut [u8], B>>, B: Backend + TakeMatZnxImpl<B>, D: DataRef, { - type Output = AutomorphismKeyExec<&'a mut [u8], B>; + type Output = GGLWEAutomorphismKeyExec<&'a mut [u8], B>; - fn take_like(&'a mut self, template: &AutomorphismKeyExec<D, B>) -> (Self::Output, &'a mut Self) { + fn take_like(&'a mut self, template: &GGLWEAutomorphismKeyExec<D, B>) -> (Self::Output, &'a mut Self) { let (key, scratch) = self.take_like(&template.key); - (AutomorphismKeyExec { key, p: template.p }, scratch) + (GGLWEAutomorphismKeyExec { key, p: template.p }, scratch) } }@@ -829,8 +835,8 @@ k: usize,
rows: usize, digits: usize, rank: usize, - ) -> (GLWETensorKey<&mut [u8]>, &mut Self) { - let mut keys: Vec<GLWESwitchingKey<&mut [u8]>> = Vec::new(); + ) -> (GGLWETensorKey<&mut [u8]>, &mut Self) { + let mut keys: Vec<GGLWESwitchingKey<&mut [u8]>> = Vec::new(); let pairs: usize = (((rank + 1) * rank) >> 1).max(1); let mut scratch: &mut Scratch<B> = self;@@ -845,20 +851,20 @@ let (gglwe, s) = scratch.take_glwe_switching_key(n, basek, k, rows, digits, 1, rank);
scratch = s; keys.push(gglwe); } - (GLWETensorKey { keys }, scratch) + (GGLWETensorKey { keys }, scratch) } } -impl<'a, B, D> TakeLike<'a, B, GLWETensorKey<D>> for Scratch<B> +impl<'a, B, D> TakeLike<'a, B, GGLWETensorKey<D>> for Scratch<B> where - Scratch<B>: TakeLike<'a, B, GLWESwitchingKey<D>, Output = GLWESwitchingKey<&'a mut [u8]>>, + Scratch<B>: TakeLike<'a, B, GGLWESwitchingKey<D>, Output = GGLWESwitchingKey<&'a mut [u8]>>, B: Backend + TakeMatZnxImpl<B>, D: DataRef, { - type Output = GLWETensorKey<&'a mut [u8]>; + type Output = GGLWETensorKey<&'a mut [u8]>; - fn take_like(&'a mut self, template: &GLWETensorKey<D>) -> (Self::Output, &'a mut Self) { - let mut keys: Vec<GLWESwitchingKey<&mut [u8]>> = Vec::new(); + fn take_like(&'a mut self, template: &GGLWETensorKey<D>) -> (Self::Output, &'a mut Self) { + let mut keys: Vec<GGLWESwitchingKey<&mut [u8]>> = Vec::new(); let pairs: usize = template.keys.len(); let mut scratch: &mut Scratch<B> = self;@@ -874,7 +880,7 @@ scratch = s;
keys.push(gglwe); } - (GLWETensorKey { keys }, scratch) + (GGLWETensorKey { keys }, scratch) } }@@ -890,8 +896,8 @@ k: usize,
rows: usize, digits: usize, rank: usize, - ) -> (GLWETensorKeyExec<&mut [u8], B>, &mut Self) { - let mut keys: Vec<GLWESwitchingKeyExec<&mut [u8], B>> = Vec::new(); + ) -> (GGLWETensorKeyExec<&mut [u8], B>, &mut Self) { + let mut keys: Vec<GGLWESwitchingKeyExec<&mut [u8], B>> = Vec::new(); let pairs: usize = (((rank + 1) * rank) >> 1).max(1); let mut scratch: &mut Scratch<B> = self;@@ -906,20 +912,20 @@ let (gglwe, s) = scratch.take_glwe_switching_key_exec(n, basek, k, rows, digits, 1, rank);
scratch = s; keys.push(gglwe); } - (GLWETensorKeyExec { keys }, scratch) + (GGLWETensorKeyExec { keys }, scratch) } } -impl<'a, B, D> TakeLike<'a, B, GLWETensorKeyExec<D, B>> for Scratch<B> +impl<'a, B, D> TakeLike<'a, B, GGLWETensorKeyExec<D, B>> for Scratch<B> where - Scratch<B>: TakeLike<'a, B, GLWESwitchingKeyExec<D, B>, Output = GLWESwitchingKeyExec<&'a mut [u8], B>>, + Scratch<B>: TakeLike<'a, B, GGLWESwitchingKeyExec<D, B>, Output = GGLWESwitchingKeyExec<&'a mut [u8], B>>, B: Backend + TakeMatZnxImpl<B>, D: DataRef, { - type Output = GLWETensorKeyExec<&'a mut [u8], B>; + type Output = GGLWETensorKeyExec<&'a mut [u8], B>; - fn take_like(&'a mut self, template: &GLWETensorKeyExec<D, B>) -> (Self::Output, &'a mut Self) { - let mut keys: Vec<GLWESwitchingKeyExec<&mut [u8], B>> = Vec::new(); + fn take_like(&'a mut self, template: &GGLWETensorKeyExec<D, B>) -> (Self::Output, &'a mut Self) { + let mut keys: Vec<GGLWESwitchingKeyExec<&mut [u8], B>> = Vec::new(); let pairs: usize = template.keys.len(); let mut scratch: &mut Scratch<B> = self;@@ -935,6 +941,6 @@ scratch = s;
keys.push(gglwe); } - (GLWETensorKeyExec { keys }, scratch) + (GGLWETensorKeyExec { keys }, scratch) } }
@@ -0,0 +1,305 @@
+use backend::hal::{ + api::{ + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxCopy, + VecZnxStd, VecZnxSubScalarInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, + }, + layouts::{Backend, Module, ScratchOwned}, + oep::{ + ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, + TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, + }, +}; +use sampling::source::Source; + +use crate::{ + layouts::{ + GGLWEAutomorphismKey, GLWEPlaintext, GLWESecret, Infos, + prepared::{GGLWEAutomorphismKeyExec, GLWESecretExec}, + }, + noise::log2_std_noise_gglwe_product, + trait_families::{GLWEDecryptFamily, GLWEKeyswitchFamily}, +}; + +use crate::trait_families::{GGLWEAutomorphismKeyEncryptSkFamily, GLWESecretExecModuleFamily}; + +pub fn test_gglwe_automorphism_key_automorphism<B: Backend>( + module: &Module<B>, + p0: i64, + p1: i64, + basek: usize, + digits: usize, + k_in: usize, + k_out: usize, + k_apply: usize, + sigma: f64, + rank: usize, +) where + Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + + GLWEKeyswitchFamily<B> + + VecZnxAutomorphism + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxAutomorphism + + VecZnxAutomorphismInplace + + GLWEDecryptFamily<B> + + VecZnxSubScalarInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>, + B: ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxDftImpl<B> + + TakeVecZnxImpl<B> + + TakeSvpPPolImpl<B> + + TakeVecZnxBigImpl<B>, +{ + let n: usize = module.n(); + let digits_in: usize = 1; + + let rows_in: usize = k_in / (basek * digits); + let rows_apply: usize = k_in.div_ceil(basek * digits); + + let mut auto_key_in: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_in, rows_in, digits_in, rank); + let mut auto_key_out: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_out, rows_in, digits_in, rank); + let mut auto_key_apply: GGLWEAutomorphismKey<Vec<u8>> = + GGLWEAutomorphismKey::alloc(n, basek, k_apply, rows_apply, digits, rank); + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + let mut source_xa: Source = Source::new([0u8; 32]); + + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( + GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_apply, rank) + | GGLWEAutomorphismKey::automorphism_scratch_space(module, n, basek, k_out, k_in, k_apply, digits, rank), + ); + + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk.fill_ternary_prob(0.5, &mut source_xs); + + // gglwe_{s1}(s0) = s0 -> s1 + auto_key_in.encrypt_sk( + module, + p0, + &sk, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + // gglwe_{s2}(s1) -> s1 -> s2 + auto_key_apply.encrypt_sk( + module, + p1, + &sk, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + let mut auto_key_apply_exec: GGLWEAutomorphismKeyExec<Vec<u8>, B> = + GGLWEAutomorphismKeyExec::alloc(module, n, basek, k_apply, rows_apply, digits, rank); + + auto_key_apply_exec.prepare(module, &auto_key_apply, scratch.borrow()); + + // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0) + auto_key_out.automorphism(module, &auto_key_in, &auto_key_apply_exec, scratch.borrow()); + + let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_out); + + let mut sk_auto: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk_auto.fill_zero(); // Necessary to avoid panic of unfilled sk + (0..rank).for_each(|i| { + module.vec_znx_automorphism( + module.galois_element_inv(p0 * p1), + &mut sk_auto.data.as_vec_znx_mut(), + i, + &sk.data.as_vec_znx(), + i, + ); + }); + + let sk_auto_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_auto); + + (0..auto_key_out.rank_in()).for_each(|col_i| { + (0..auto_key_out.rows()).for_each(|row_i| { + auto_key_out + .at(row_i, col_i) + .decrypt(module, &mut pt, &sk_auto_dft, scratch.borrow()); + + module.vec_znx_sub_scalar_inplace( + &mut pt.data, + 0, + (digits_in - 1) + row_i * digits_in, + &sk.data, + col_i, + ); + + let noise_have: f64 = module.vec_znx_std(basek, &pt.data, 0).log2(); + let noise_want: f64 = log2_std_noise_gglwe_product( + n as f64, + basek * digits, + 0.5, + 0.5, + 0f64, + sigma * sigma, + 0f64, + rank as f64, + k_out, + k_apply, + ); + + assert!( + noise_have < noise_want + 0.5, + "{} {}", + noise_have, + noise_want + ); + }); + }); +} + +pub fn test_gglwe_automorphism_key_automorphism_inplace<B: Backend>( + module: &Module<B>, + p0: i64, + p1: i64, + basek: usize, + digits: usize, + k_in: usize, + k_apply: usize, + sigma: f64, + rank: usize, +) where + Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + + GLWEKeyswitchFamily<B> + + VecZnxAutomorphism + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxAutomorphism + + VecZnxAutomorphismInplace + + GLWEDecryptFamily<B> + + VecZnxSubScalarInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>, + B: ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxDftImpl<B> + + TakeVecZnxImpl<B> + + TakeSvpPPolImpl<B> + + TakeVecZnxBigImpl<B>, +{ + let n: usize = module.n(); + let digits_in: usize = 1; + + let rows_in: usize = k_in / (basek * digits); + let rows_apply: usize = k_in.div_ceil(basek * digits); + + let mut auto_key: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_in, rows_in, digits_in, rank); + let mut auto_key_apply: GGLWEAutomorphismKey<Vec<u8>> = + GGLWEAutomorphismKey::alloc(n, basek, k_apply, rows_apply, digits, rank); + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + let mut source_xa: Source = Source::new([0u8; 32]); + + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( + GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_apply, rank) + | GGLWEAutomorphismKey::automorphism_inplace_scratch_space(module, n, basek, k_in, k_apply, digits, rank), + ); + + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk.fill_ternary_prob(0.5, &mut source_xs); + + // gglwe_{s1}(s0) = s0 -> s1 + auto_key.encrypt_sk( + module, + p0, + &sk, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + // gglwe_{s2}(s1) -> s1 -> s2 + auto_key_apply.encrypt_sk( + module, + p1, + &sk, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + let mut auto_key_apply_exec: GGLWEAutomorphismKeyExec<Vec<u8>, B> = + GGLWEAutomorphismKeyExec::alloc(module, n, basek, k_apply, rows_apply, digits, rank); + + auto_key_apply_exec.prepare(module, &auto_key_apply, scratch.borrow()); + + // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0) + auto_key.automorphism_inplace(module, &auto_key_apply_exec, scratch.borrow()); + + let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_in); + + let mut sk_auto: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk_auto.fill_zero(); // Necessary to avoid panic of unfilled sk + + (0..rank).for_each(|i| { + module.vec_znx_automorphism( + module.galois_element_inv(p0 * p1), + &mut sk_auto.data.as_vec_znx_mut(), + i, + &sk.data.as_vec_znx(), + i, + ); + }); + + let sk_auto_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_auto); + + (0..auto_key.rank_in()).for_each(|col_i| { + (0..auto_key.rows()).for_each(|row_i| { + auto_key + .at(row_i, col_i) + .decrypt(module, &mut pt, &sk_auto_dft, scratch.borrow()); + module.vec_znx_sub_scalar_inplace( + &mut pt.data, + 0, + (digits_in - 1) + row_i * digits_in, + &sk.data, + col_i, + ); + + let noise_have: f64 = module.vec_znx_std(basek, &pt.data, 0).log2(); + let noise_want: f64 = log2_std_noise_gglwe_product( + n as f64, + basek * digits, + 0.5, + 0.5, + 0f64, + sigma * sigma, + 0f64, + rank as f64, + k_in, + k_apply, + ); + + assert!( + noise_have < noise_want + 0.5, + "{} {}", + noise_have, + noise_want + ); + }); + }); +}
@@ -0,0 +1,280 @@
+use backend::hal::{ + api::{ + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxCopy, + VecZnxStd, VecZnxSubABInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, + }, + layouts::{Backend, Module, ScalarZnx, ScratchOwned}, + oep::{ + ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, + TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl, + }, +}; +use sampling::source::Source; + +use crate::{ + layouts::{ + GGLWEAutomorphismKey, GGLWETensorKey, GGSWCiphertext, GLWESecret, + prepared::{GGLWEAutomorphismKeyExec, GLWESecretExec, GGLWETensorKeyExec}, + }, + noise::noise_ggsw_keyswitch, + trait_families::GGSWAssertNoiseFamily, +}; + +use crate::trait_families::{ + GGLWESwitchingKeyEncryptSkFamily, GGLWETensorKeyEncryptSkFamily, GGSWKeySwitchFamily, GLWESecretExecModuleFamily, +}; + +pub fn test_ggsw_automorphism<B: Backend>( + p: i64, + module: &Module<B>, + basek: usize, + k_out: usize, + k_in: usize, + k_ksk: usize, + k_tsk: usize, + digits: usize, + rank: usize, + sigma: f64, +) where + Module<B>: GGSWAssertNoiseFamily<B> + + GLWESecretExecModuleFamily<B> + + VecZnxAddScalarInplace + + VecZnxCopy + + VecZnxStd + + VecZnxSubABInplace + + VmpPMatAlloc<B> + + VmpPMatPrepare<B> + + GGSWKeySwitchFamily<B> + + GGLWESwitchingKeyEncryptSkFamily<B> + + GGLWETensorKeyEncryptSkFamily<B> + + VecZnxSwithcDegree + + VecZnxAutomorphismInplace + + VecZnxAutomorphismInplace + + VecZnxAutomorphism, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B> + + VecZnxDftAllocBytesImpl<B> + + VecZnxBigAllocBytesImpl<B> + + TakeSvpPPolImpl<B>, +{ + let n: usize = module.n(); + let rows: usize = k_in.div_ceil(basek * digits); + let rows_in: usize = k_in.div_euclid(basek * digits); + + let digits_in: usize = 1; + + let mut ct_in: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_in, rows_in, digits_in, rank); + let mut ct_out: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_out, rows_in, digits_in, rank); + let mut tensor_key: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(n, basek, k_tsk, rows, digits, rank); + let mut auto_key: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); + let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + let mut source_xa: Source = Source::new([0u8; 32]); + + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( + GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_in, rank) + | GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank) + | GGLWETensorKey::encrypt_sk_scratch_space(module, n, basek, k_tsk, rank) + | GGSWCiphertext::automorphism_scratch_space( + module, n, basek, k_out, k_in, k_ksk, digits, k_tsk, digits, rank, + ), + ); + + let var_xs: f64 = 0.5; + + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk.fill_ternary_prob(var_xs, &mut source_xs); + let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); + + auto_key.encrypt_sk( + module, + p, + &sk, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + tensor_key.encrypt_sk( + module, + &sk, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + pt_scalar.fill_ternary_hw(0, n, &mut source_xs); + + ct_in.encrypt_sk( + module, + &pt_scalar, + &sk_exec, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + let mut auto_key_exec: GGLWEAutomorphismKeyExec<Vec<u8>, B> = + GGLWEAutomorphismKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); + auto_key_exec.prepare(module, &auto_key, scratch.borrow()); + + let mut tsk_exec: GGLWETensorKeyExec<Vec<u8>, B> = GGLWETensorKeyExec::alloc(module, n, basek, k_tsk, rows, digits, rank); + tsk_exec.prepare(module, &tensor_key, scratch.borrow()); + + ct_out.automorphism(module, &ct_in, &auto_key_exec, &tsk_exec, scratch.borrow()); + + module.vec_znx_automorphism_inplace(p, &mut pt_scalar.as_vec_znx_mut(), 0); + + let max_noise = |col_j: usize| -> f64 { + noise_ggsw_keyswitch( + n as f64, + basek * digits, + col_j, + var_xs, + 0f64, + sigma * sigma, + 0f64, + rank as f64, + k_in, + k_ksk, + k_tsk, + ) + 0.5 + }; + + ct_out.assert_noise(module, &sk_exec, &pt_scalar, &max_noise); +} + +pub fn test_ggsw_automorphism_inplace<B: Backend>( + p: i64, + module: &Module<B>, + basek: usize, + k_ct: usize, + k_ksk: usize, + k_tsk: usize, + digits: usize, + rank: usize, + sigma: f64, +) where + Module<B>: GGSWAssertNoiseFamily<B> + + GLWESecretExecModuleFamily<B> + + VecZnxAddScalarInplace + + VecZnxCopy + + VecZnxStd + + VecZnxSubABInplace + + VmpPMatAlloc<B> + + VmpPMatPrepare<B> + + GGSWKeySwitchFamily<B> + + GGLWESwitchingKeyEncryptSkFamily<B> + + GGLWETensorKeyEncryptSkFamily<B> + + VecZnxSwithcDegree + + VecZnxAutomorphismInplace + + VecZnxAutomorphismInplace + + VecZnxAutomorphism, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B> + + VecZnxDftAllocBytesImpl<B> + + VecZnxBigAllocBytesImpl<B> + + TakeSvpPPolImpl<B>, +{ + let n: usize = module.n(); + let rows: usize = k_ct.div_ceil(digits * basek); + let rows_in: usize = k_ct.div_euclid(basek * digits); + let digits_in: usize = 1; + + let mut ct: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ct, rows_in, digits_in, rank); + let mut tensor_key: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(n, basek, k_tsk, rows, digits, rank); + let mut auto_key: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); + let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + let mut source_xa: Source = Source::new([0u8; 32]); + + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( + GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ct, rank) + | GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank) + | GGLWETensorKey::encrypt_sk_scratch_space(module, n, basek, k_tsk, rank) + | GGSWCiphertext::automorphism_inplace_scratch_space(module, n, basek, k_ct, k_ksk, digits, k_tsk, digits, rank), + ); + + let var_xs: f64 = 0.5; + + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk.fill_ternary_prob(var_xs, &mut source_xs); + let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); + + auto_key.encrypt_sk( + module, + p, + &sk, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + tensor_key.encrypt_sk( + module, + &sk, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + pt_scalar.fill_ternary_hw(0, n, &mut source_xs); + + ct.encrypt_sk( + module, + &pt_scalar, + &sk_exec, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + let mut auto_key_exec: GGLWEAutomorphismKeyExec<Vec<u8>, B> = + GGLWEAutomorphismKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); + auto_key_exec.prepare(module, &auto_key, scratch.borrow()); + + let mut tsk_exec: GGLWETensorKeyExec<Vec<u8>, B> = GGLWETensorKeyExec::alloc(module, n, basek, k_tsk, rows, digits, rank); + tsk_exec.prepare(module, &tensor_key, scratch.borrow()); + + ct.automorphism_inplace(module, &auto_key_exec, &tsk_exec, scratch.borrow()); + + module.vec_znx_automorphism_inplace(p, &mut pt_scalar.as_vec_znx_mut(), 0); + + let max_noise = |col_j: usize| -> f64 { + noise_ggsw_keyswitch( + n as f64, + basek * digits, + col_j, + var_xs, + 0f64, + sigma * sigma, + 0f64, + rank as f64, + k_ct, + k_ksk, + k_tsk, + ) + 0.5 + }; + + ct.assert_noise(module, &sk_exec, &pt_scalar, &max_noise); +}
@@ -0,0 +1,7 @@
+mod gglwe_atk; +mod ggsw_ct; +mod glwe_ct; + +pub use gglwe_atk::*; +pub use ggsw_ct::*; +pub use glwe_ct::*;
@@ -0,0 +1,204 @@
+use backend::hal::{ + api::{ + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxEncodeCoeffsi64, + VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, ZnxView, + }, + layouts::{Backend, Module, ScratchOwned}, + oep::{ + ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, + TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, + }, +}; +use sampling::source::Source; + +use crate::layouts::{ + GLWECiphertext, GLWEPlaintext, GLWESecret, GLWEToLWESwitchingKey, Infos, LWECiphertext, LWEPlaintext, LWESecret, + LWEToGLWESwitchingKey, + prepared::{GLWESecretExec, GLWEToLWESwitchingKeyExec, LWEToGLWESwitchingKeyExec}, +}; + +use crate::trait_families::{GGLWEEncryptSkFamily, GLWEDecryptFamily, GLWEKeyswitchFamily, GLWESecretExecModuleFamily}; + +pub fn test_lwe_to_glwe<B: Backend>(module: &Module<B>) +where + Module<B>: GGLWEEncryptSkFamily<B> + + GLWEDecryptFamily<B> + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + GLWEKeyswitchFamily<B> + + VecZnxEncodeCoeffsi64 + + VecZnxAutomorphismInplace + + VmpPMatAlloc<B> + + VmpPMatPrepare<B> + + GLWESecretExecModuleFamily<B>, + B: TakeScalarZnxImpl<B> + + TakeVecZnxDftImpl<B> + + ScratchAvailableImpl<B> + + TakeVecZnxImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B>, +{ + let n: usize = module.n(); + let basek: usize = 17; + let sigma: f64 = 3.2; + + let rank: usize = 2; + + let n_lwe: usize = 22; + let k_lwe_ct: usize = 2 * basek; + let k_lwe_pt: usize = 8; + + let k_glwe_ct: usize = 3 * basek; + + let k_ksk: usize = k_lwe_ct + basek; + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xa: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( + LWEToGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank) + | GLWECiphertext::from_lwe_scratch_space(module, n, basek, k_lwe_ct, k_glwe_ct, k_ksk, rank) + | GLWECiphertext::decrypt_scratch_space(module, n, basek, k_glwe_ct), + ); + + let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk_glwe.fill_ternary_prob(0.5, &mut source_xs); + + let sk_glwe_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_glwe); + + let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe); + sk_lwe.fill_ternary_prob(0.5, &mut source_xs); + + let data: i64 = 17; + + let mut lwe_pt: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_pt); + module.encode_coeff_i64(basek, &mut lwe_pt.data, 0, k_lwe_pt, 0, data, k_lwe_pt); + + let mut lwe_ct: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe, basek, k_lwe_ct); + lwe_ct.encrypt_sk( + module, + &lwe_pt, + &sk_lwe, + &mut source_xa, + &mut source_xe, + sigma, + ); + + let mut ksk: LWEToGLWESwitchingKey<Vec<u8>> = LWEToGLWESwitchingKey::alloc(n, basek, k_ksk, lwe_ct.size(), rank); + + ksk.encrypt_sk( + module, + &sk_lwe, + &sk_glwe, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + let mut glwe_ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_glwe_ct, rank); + + let ksk_exec: LWEToGLWESwitchingKeyExec<Vec<u8>, B> = LWEToGLWESwitchingKeyExec::from(module, &ksk, scratch.borrow()); + + glwe_ct.from_lwe(module, &lwe_ct, &ksk_exec, scratch.borrow()); + + let mut glwe_pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_glwe_ct); + glwe_ct.decrypt(module, &mut glwe_pt, &sk_glwe_exec, scratch.borrow()); + + assert_eq!(glwe_pt.data.at(0, 0)[0], lwe_pt.data.at(0, 0)[0]); +} + +pub fn test_glwe_to_lwe<B: Backend>(module: &Module<B>) +where + Module<B>: GGLWEEncryptSkFamily<B> + + GLWEDecryptFamily<B> + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + GLWEKeyswitchFamily<B> + + VecZnxEncodeCoeffsi64 + + VecZnxAutomorphismInplace + + VmpPMatAlloc<B> + + VmpPMatPrepare<B> + + GLWESecretExecModuleFamily<B>, + B: TakeScalarZnxImpl<B> + + TakeVecZnxDftImpl<B> + + ScratchAvailableImpl<B> + + TakeVecZnxImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B>, +{ + let n: usize = module.n(); + let basek: usize = 17; + let sigma: f64 = 3.2; + + let rank: usize = 2; + + let n_lwe: usize = 22; + let k_lwe_ct: usize = 2 * basek; + let k_lwe_pt: usize = 8; + + let k_glwe_ct: usize = 3 * basek; + + let k_ksk: usize = k_lwe_ct + basek; + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xa: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( + LWEToGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank) + | LWECiphertext::from_glwe_scratch_space(module, n, basek, k_lwe_ct, k_glwe_ct, k_ksk, rank) + | GLWECiphertext::decrypt_scratch_space(module, n, basek, k_glwe_ct), + ); + + let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk_glwe.fill_ternary_prob(0.5, &mut source_xs); + + let sk_glwe_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_glwe); + + let mut sk_lwe = LWESecret::alloc(n_lwe); + sk_lwe.fill_ternary_prob(0.5, &mut source_xs); + + let data: i64 = 17; + let mut glwe_pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_glwe_ct); + module.encode_coeff_i64(basek, &mut glwe_pt.data, 0, k_lwe_pt, 0, data, k_lwe_pt); + + let mut glwe_ct = GLWECiphertext::alloc(n, basek, k_glwe_ct, rank); + glwe_ct.encrypt_sk( + module, + &glwe_pt, + &sk_glwe_exec, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + let mut ksk: GLWEToLWESwitchingKey<Vec<u8>> = GLWEToLWESwitchingKey::alloc(n, basek, k_ksk, glwe_ct.size(), rank); + + ksk.encrypt_sk( + module, + &sk_lwe, + &sk_glwe, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + let mut lwe_ct: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe, basek, k_lwe_ct); + + let ksk_exec: GLWEToLWESwitchingKeyExec<Vec<u8>, B> = GLWEToLWESwitchingKeyExec::from(module, &ksk, scratch.borrow()); + + lwe_ct.from_glwe(module, &glwe_ct, &ksk_exec, scratch.borrow()); + + let mut lwe_pt: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_ct); + lwe_ct.decrypt(module, &mut lwe_pt, &sk_lwe); + + assert_eq!(glwe_pt.data.at(0, 0)[0], lwe_pt.data.at(0, 0)[0]); +}
@@ -0,0 +1,176 @@
+use backend::hal::{ + api::{ + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxCopy, + VecZnxStd, VecZnxSubScalarInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, + }, + layouts::{Backend, Module, ScratchOwned}, + oep::{ + ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, + TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, + }, +}; +use sampling::source::Source; + +use crate::{ + layouts::{GGLWEAutomorphismKey, GLWESecret, compressed::GGLWEAutomorphismKeyCompressed, prepared::GLWESecretExec}, + trait_families::{Decompress, GLWEDecryptFamily, GLWEKeyswitchFamily}, +}; + +use crate::trait_families::{GGLWEAutomorphismKeyEncryptSkFamily, GLWESecretExecModuleFamily}; + +pub fn test_gglwe_automorphisk_key_encrypt_sk<B: Backend>( + module: &Module<B>, + basek: usize, + k_ksk: usize, + digits: usize, + rank: usize, + sigma: f64, +) where + Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + + GLWEKeyswitchFamily<B> + + VecZnxAutomorphism + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxAutomorphism + + VecZnxAutomorphismInplace + + GLWEDecryptFamily<B> + + VecZnxSubScalarInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>, + B: ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxDftImpl<B> + + TakeVecZnxImpl<B> + + TakeSvpPPolImpl<B> + + TakeVecZnxBigImpl<B>, +{ + let n: usize = module.n(); + let rows: usize = (k_ksk - digits * basek) / (digits * basek); + + let mut atk: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + let mut source_xa: Source = Source::new([0u8; 32]); + + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWEAutomorphismKey::encrypt_sk_scratch_space( + module, n, basek, k_ksk, rank, + )); + + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk.fill_ternary_prob(0.5, &mut source_xs); + + let p = -5; + + atk.encrypt_sk( + module, + p, + &sk, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + let mut sk_out: GLWESecret<Vec<u8>> = sk.clone(); + (0..atk.rank()).for_each(|i| { + module.vec_znx_automorphism( + module.galois_element_inv(p), + &mut sk_out.data.as_vec_znx_mut(), + i, + &sk.data.as_vec_znx(), + i, + ); + }); + let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); + + atk.key + .key + .assert_noise(module, &sk_out_exec, &sk.data, sigma); +} + +pub fn test_gglwe_automorphisk_key_compressed_encrypt_sk<B: Backend>( + module: &Module<B>, + basek: usize, + k_ksk: usize, + digits: usize, + rank: usize, + sigma: f64, +) where + Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + + GLWEKeyswitchFamily<B> + + VecZnxAutomorphism + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxAutomorphism + + VecZnxAutomorphismInplace + + GLWEDecryptFamily<B> + + VecZnxSubScalarInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>, + B: ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxDftImpl<B> + + TakeVecZnxImpl<B> + + TakeSvpPPolImpl<B> + + TakeVecZnxBigImpl<B>, +{ + let n: usize = module.n(); + let rows: usize = (k_ksk - digits * basek) / (digits * basek); + + let mut atk_compressed: GGLWEAutomorphismKeyCompressed<Vec<u8>> = + GGLWEAutomorphismKeyCompressed::alloc(n, basek, k_ksk, rows, digits, rank); + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWEAutomorphismKey::encrypt_sk_scratch_space( + module, n, basek, k_ksk, rank, + )); + + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk.fill_ternary_prob(0.5, &mut source_xs); + + let p = -5; + + let seed_xa: [u8; 32] = [1u8; 32]; + + atk_compressed.encrypt_sk( + module, + p, + &sk, + seed_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + let mut sk_out: GLWESecret<Vec<u8>> = sk.clone(); + (0..atk_compressed.rank()).for_each(|i| { + module.vec_znx_automorphism( + module.galois_element_inv(p), + &mut sk_out.data.as_vec_znx_mut(), + i, + &sk.data.as_vec_znx(), + i, + ); + }); + let sk_out_exec = GLWESecretExec::from(module, &sk_out); + + let mut atk: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); + atk.decompress(module, &atk_compressed); + + atk.key + .key + .assert_noise(module, &sk_out_exec, &sk.data, sigma); +}
@@ -0,0 +1,154 @@
+use backend::hal::{ + api::{ + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxStd, VecZnxSubScalarInplace, + VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, + }, + layouts::{Backend, Module, ScratchOwned}, + oep::{ + ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, + TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl, + }, +}; +use sampling::source::Source; + +use crate::{ + layouts::{GLWESecret, GGLWESwitchingKey, compressed::GGLWESwitchingKeyCompressed, prepared::GLWESecretExec}, + trait_families::{Decompress, GLWEDecryptFamily}, +}; + +use crate::trait_families::{GGLWEEncryptSkFamily, GLWESecretExecModuleFamily}; + +pub fn test_gglwe_switching_key_encrypt_sk<B: Backend>( + module: &Module<B>, + basek: usize, + k_ksk: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + sigma: f64, +) where + Module<B>: GGLWEEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + + GLWEDecryptFamily<B> + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxStd + + VecZnxSubScalarInplace + + VecZnxCopy + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B> + + VecZnxDftAllocBytesImpl<B> + + VecZnxBigAllocBytesImpl<B> + + TakeSvpPPolImpl<B>, +{ + let n: usize = module.n(); + let rows: usize = (k_ksk - digits * basek) / (digits * basek); + + let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_in, rank_out); + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + let mut source_xa: Source = Source::new([0u8; 32]); + + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWESwitchingKey::encrypt_sk_scratch_space( + module, n, basek, k_ksk, rank_in, rank_out, + )); + + let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in); + sk_in.fill_ternary_prob(0.5, &mut source_xs); + + let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out); + sk_out.fill_ternary_prob(0.5, &mut source_xs); + let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); + + ksk.encrypt_sk( + module, + &sk_in, + &sk_out, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + ksk.key + .assert_noise(module, &sk_out_exec, &sk_in.data, sigma); +} + +pub fn test_gglwe_switching_key_compressed_encrypt_sk<B: Backend>( + module: &Module<B>, + basek: usize, + k_ksk: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + sigma: f64, +) where + Module<B>: GGLWEEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + + GLWEDecryptFamily<B> + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxStd + + VecZnxSubScalarInplace + + VecZnxCopy + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B> + + VecZnxDftAllocBytesImpl<B> + + VecZnxBigAllocBytesImpl<B> + + TakeSvpPPolImpl<B>, +{ + let n: usize = module.n(); + let rows: usize = (k_ksk - digits * basek) / (digits * basek); + + let mut ksk_compressed: GGLWESwitchingKeyCompressed<Vec<u8>> = + GGLWESwitchingKeyCompressed::alloc(n, basek, k_ksk, rows, digits, rank_in, rank_out); + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWESwitchingKeyCompressed::encrypt_sk_scratch_space( + module, n, basek, k_ksk, rank_in, rank_out, + )); + + let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in); + sk_in.fill_ternary_prob(0.5, &mut source_xs); + + let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out); + sk_out.fill_ternary_prob(0.5, &mut source_xs); + let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); + + let seed_xa = [1u8; 32]; + + ksk_compressed.encrypt_sk( + module, + &sk_in, + &sk_out, + seed_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_in, rank_out); + ksk.decompress(module, &ksk_compressed); + + ksk.key + .assert_noise(module, &sk_out_exec, &sk_in.data, sigma); +}
@@ -0,0 +1,149 @@
+use backend::hal::{ + api::{ + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxStd, VecZnxSubABInplace, VmpPMatAlloc, + VmpPMatPrepare, + }, + layouts::{Backend, Module, ScalarZnx, ScratchOwned}, + oep::{ + ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, + TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl, + }, +}; +use sampling::source::Source; + +use crate::{ + layouts::{GGSWCiphertext, GLWESecret, compressed::GGSWCiphertextCompressed, prepared::GLWESecretExec}, + trait_families::{Decompress, GGSWAssertNoiseFamily}, +}; + +use crate::trait_families::{GGSWEncryptSkFamily, GLWESecretExecModuleFamily}; + +pub fn test_ggsw_encrypt_sk<B: Backend>(module: &Module<B>, basek: usize, k: usize, digits: usize, rank: usize, sigma: f64) +where + Module<B>: GLWESecretExecModuleFamily<B> + + GGSWEncryptSkFamily<B> + + GGSWAssertNoiseFamily<B> + + VecZnxAddScalarInplace + + VecZnxSubABInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B> + + VecZnxDftAllocBytesImpl<B> + + VecZnxBigAllocBytesImpl<B> + + TakeSvpPPolImpl<B>, +{ + let n: usize = module.n(); + let rows: usize = (k - digits * basek) / (digits * basek); + + let mut ct: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k, rows, digits, rank); + + let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + let mut source_xa: Source = Source::new([0u8; 32]); + + pt_scalar.fill_ternary_hw(0, n, &mut source_xs); + + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGSWCiphertext::encrypt_sk_scratch_space( + module, n, basek, k, rank, + )); + + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk.fill_ternary_prob(0.5, &mut source_xs); + let mut sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); + sk_exec.prepare(module, &sk); + + ct.encrypt_sk( + module, + &pt_scalar, + &sk_exec, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + let noise_f = |_col_i: usize| -(k as f64) + sigma.log2() + 0.5; + + ct.assert_noise(module, &sk_exec, &pt_scalar, &noise_f); +} + +pub fn test_ggsw_compressed_encrypt_sk<B: Backend>( + module: &Module<B>, + basek: usize, + k: usize, + digits: usize, + rank: usize, + sigma: f64, +) where + Module<B>: GLWESecretExecModuleFamily<B> + + GGSWEncryptSkFamily<B> + + GGSWAssertNoiseFamily<B> + + VecZnxAddScalarInplace + + VecZnxSubABInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B> + + VecZnxDftAllocBytesImpl<B> + + VecZnxBigAllocBytesImpl<B> + + TakeSvpPPolImpl<B>, +{ + let n: usize = module.n(); + let rows: usize = (k - digits * basek) / (digits * basek); + + let mut ct_compressed: GGSWCiphertextCompressed<Vec<u8>> = GGSWCiphertextCompressed::alloc(n, basek, k, rows, digits, rank); + + let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + + pt_scalar.fill_ternary_hw(0, n, &mut source_xs); + + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGSWCiphertextCompressed::encrypt_sk_scratch_space( + module, n, basek, k, rank, + )); + + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk.fill_ternary_prob(0.5, &mut source_xs); + let mut sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); + sk_exec.prepare(module, &sk); + + let seed_xa: [u8; 32] = [1u8; 32]; + + ct_compressed.encrypt_sk( + module, + &pt_scalar, + &sk_exec, + seed_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + let noise_f = |_col_i: usize| -(k as f64) + sigma.log2() + 0.5; + + let mut ct: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k, rows, digits, rank); + ct.decompress(module, &ct_compressed); + + ct.assert_noise(module, &sk_exec, &pt_scalar, &noise_f); +}
@@ -0,0 +1,11 @@
+mod gglwe_atk; +mod gglwe_ct; +mod ggsw_ct; +mod glwe_ct; +mod glwe_tsk; + +pub use gglwe_atk::*; +pub use gglwe_ct::*; +pub use ggsw_ct::*; +pub use glwe_ct::*; +pub use glwe_tsk::*;
@@ -0,0 +1,281 @@
+use backend::hal::{ + api::{ + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxRotateInplace, VecZnxStd, + VecZnxSubScalarInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, ZnxViewMut, + }, + layouts::{Backend, Module, ScalarZnx, ScalarZnxToMut, ScratchOwned}, + oep::{ + ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, + TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl, + }, +}; +use sampling::source::Source; + +use crate::{ + layouts::{ + GGSWCiphertext, GLWESecret, GGLWESwitchingKey, + prepared::{GGSWCiphertextExec, GLWESecretExec}, + }, + noise::noise_ggsw_product, + trait_families::{GLWEDecryptFamily, GLWEExternalProductFamily}, +}; + +use crate::trait_families::{GGLWEEncryptSkFamily, GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; + +pub fn test_gglwe_switching_key_external_product<B: Backend>( + module: &Module<B>, + basek: usize, + k_out: usize, + k_in: usize, + k_ggsw: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + sigma: f64, +) where + Module<B>: GGLWEEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + + GLWEDecryptFamily<B> + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxStd + + VecZnxSubScalarInplace + + VecZnxCopy + + VmpPMatAlloc<B> + + VmpPMatPrepare<B> + + GGLWESwitchingKeyEncryptSkFamily<B> + + GLWEExternalProductFamily<B> + + GLWEDecryptFamily<B> + + VecZnxRotateInplace, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B> + + VecZnxDftAllocBytesImpl<B> + + VecZnxBigAllocBytesImpl<B> + + TakeSvpPPolImpl<B>, +{ + let n: usize = module.n(); + let rows: usize = k_in.div_ceil(basek * digits); + let digits_in: usize = 1; + + let mut ct_gglwe_in: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_in, rows, digits_in, rank_in, rank_out); + let mut ct_gglwe_out: GGLWESwitchingKey<Vec<u8>> = + GGLWESwitchingKey::alloc(n, basek, k_out, rows, digits_in, rank_in, rank_out); + let mut ct_rgsw: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank_out); + + let mut pt_rgsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + let mut source_xa: Source = Source::new([0u8; 32]); + + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( + GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_in, rank_in, rank_out) + | GGLWESwitchingKey::external_product_scratch_space(module, n, basek, k_out, k_in, k_ggsw, digits, rank_out) + | GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ggsw, rank_out), + ); + + let r: usize = 1; + + pt_rgsw.to_mut().raw_mut()[r] = 1; // X^{r} + + let var_xs: f64 = 0.5; + + let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in); + sk_in.fill_ternary_prob(var_xs, &mut source_xs); + + let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out); + sk_out.fill_ternary_prob(var_xs, &mut source_xs); + let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); + + // gglwe_{s1}(s0) = s0 -> s1 + ct_gglwe_in.encrypt_sk( + module, + &sk_in, + &sk_out, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + ct_rgsw.encrypt_sk( + module, + &pt_rgsw, + &sk_out_exec, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + let mut ct_rgsw_exec: GGSWCiphertextExec<Vec<u8>, B> = + GGSWCiphertextExec::alloc(module, n, basek, k_ggsw, rows, digits, rank_out); + + ct_rgsw_exec.prepare(module, &ct_rgsw, scratch.borrow()); + + // gglwe_(m) (x) RGSW_(X^k) = gglwe_(m * X^k) + ct_gglwe_out.external_product(module, &ct_gglwe_in, &ct_rgsw_exec, scratch.borrow()); + + (0..rank_in).for_each(|i| { + module.vec_znx_rotate_inplace(r as i64, &mut sk_in.data.as_vec_znx_mut(), i); // * X^{r} + }); + + let var_gct_err_lhs: f64 = sigma * sigma; + let var_gct_err_rhs: f64 = 0f64; + + let var_msg: f64 = 1f64 / n as f64; // X^{k} + let var_a0_err: f64 = sigma * sigma; + let var_a1_err: f64 = 1f64 / 12f64; + + let max_noise: f64 = noise_ggsw_product( + n as f64, + basek * digits, + var_xs, + var_msg, + var_a0_err, + var_a1_err, + var_gct_err_lhs, + var_gct_err_rhs, + rank_out as f64, + k_in, + k_ggsw, + ); + + ct_gglwe_out + .key + .assert_noise(module, &sk_out_exec, &sk_in.data, max_noise + 0.5); +} + +pub fn test_gglwe_switching_key_external_product_inplace<B: Backend>( + module: &Module<B>, + basek: usize, + k_ct: usize, + k_ggsw: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + sigma: f64, +) where + Module<B>: GGLWEEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + + GLWEDecryptFamily<B> + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxStd + + VecZnxSubScalarInplace + + VecZnxCopy + + VmpPMatAlloc<B> + + VmpPMatPrepare<B> + + GGLWESwitchingKeyEncryptSkFamily<B> + + GLWEExternalProductFamily<B> + + GLWEDecryptFamily<B> + + VecZnxRotateInplace, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B> + + VecZnxDftAllocBytesImpl<B> + + VecZnxBigAllocBytesImpl<B> + + TakeSvpPPolImpl<B>, +{ + let n: usize = module.n(); + let rows: usize = k_ct.div_ceil(basek * digits); + + let digits_in: usize = 1; + + let mut ct_gglwe: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_ct, rows, digits_in, rank_in, rank_out); + let mut ct_rgsw: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank_out); + + let mut pt_rgsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + let mut source_xa: Source = Source::new([0u8; 32]); + + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( + GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ct, rank_in, rank_out) + | GGLWESwitchingKey::external_product_inplace_scratch_space(module, n, basek, k_ct, k_ggsw, digits, rank_out) + | GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ggsw, rank_out), + ); + + let r: usize = 1; + + pt_rgsw.to_mut().raw_mut()[r] = 1; // X^{r} + + let var_xs: f64 = 0.5; + + let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in); + sk_in.fill_ternary_prob(var_xs, &mut source_xs); + + let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out); + sk_out.fill_ternary_prob(var_xs, &mut source_xs); + let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); + + // gglwe_{s1}(s0) = s0 -> s1 + ct_gglwe.encrypt_sk( + module, + &sk_in, + &sk_out, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + ct_rgsw.encrypt_sk( + module, + &pt_rgsw, + &sk_out_exec, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + let mut ct_rgsw_exec: GGSWCiphertextExec<Vec<u8>, B> = + GGSWCiphertextExec::alloc(module, n, basek, k_ggsw, rows, digits, rank_out); + + ct_rgsw_exec.prepare(module, &ct_rgsw, scratch.borrow()); + + // gglwe_(m) (x) RGSW_(X^k) = gglwe_(m * X^k) + ct_gglwe.external_product_inplace(module, &ct_rgsw_exec, scratch.borrow()); + + (0..rank_in).for_each(|i| { + module.vec_znx_rotate_inplace(r as i64, &mut sk_in.data.as_vec_znx_mut(), i); // * X^{r} + }); + + let var_gct_err_lhs: f64 = sigma * sigma; + let var_gct_err_rhs: f64 = 0f64; + + let var_msg: f64 = 1f64 / n as f64; // X^{k} + let var_a0_err: f64 = sigma * sigma; + let var_a1_err: f64 = 1f64 / 12f64; + + let max_noise: f64 = noise_ggsw_product( + n as f64, + basek * digits, + var_xs, + var_msg, + var_a0_err, + var_a1_err, + var_gct_err_lhs, + var_gct_err_rhs, + rank_out as f64, + k_ct, + k_ggsw, + ); + + ct_gglwe + .key + .assert_noise(module, &sk_out_exec, &sk_in.data, max_noise + 0.5); +}
@@ -0,0 +1,263 @@
+use backend::hal::{ + api::{ + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxRotateInplace, VecZnxStd, + VecZnxSubABInplace, VmpPMatAlloc, VmpPMatPrepare, ZnxViewMut, + }, + layouts::{Backend, Module, ScalarZnx, ScalarZnxToMut, ScratchOwned}, + oep::{ + ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, + TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl, + }, +}; +use sampling::source::Source; + +use crate::{ + layouts::{ + GGSWCiphertext, GLWESecret, + prepared::{GGSWCiphertextExec, GLWESecretExec}, + }, + noise::noise_ggsw_product, + trait_families::GGSWAssertNoiseFamily, +}; + +use crate::trait_families::{ + GGLWESwitchingKeyEncryptSkFamily, GGLWETensorKeyEncryptSkFamily, GGSWEncryptSkFamily, GGSWKeySwitchFamily, + GLWESecretExecModuleFamily, +}; + +pub fn test_ggsw_external_product<B: Backend>( + module: &Module<B>, + basek: usize, + k_in: usize, + k_out: usize, + k_ggsw: usize, + digits: usize, + rank: usize, + sigma: f64, +) where + Module<B>: GLWESecretExecModuleFamily<B> + + GGSWEncryptSkFamily<B> + + GGSWAssertNoiseFamily<B> + + VecZnxAddScalarInplace + + VecZnxSubABInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc<B> + + VmpPMatPrepare<B> + + GGSWAssertNoiseFamily<B> + + GGSWKeySwitchFamily<B> + + GGLWESwitchingKeyEncryptSkFamily<B> + + GGLWETensorKeyEncryptSkFamily<B> + + VecZnxRotateInplace, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B> + + VecZnxDftAllocBytesImpl<B> + + VecZnxBigAllocBytesImpl<B> + + TakeSvpPPolImpl<B>, +{ + let n: usize = module.n(); + let rows: usize = k_in.div_ceil(basek * digits); + let rows_in: usize = k_in.div_euclid(basek * digits); + let digits_in: usize = 1; + + let mut ct_ggsw_lhs_in: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_in, rows_in, digits_in, rank); + let mut ct_ggsw_lhs_out: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_out, rows_in, digits_in, rank); + let mut ct_ggsw_rhs: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank); + let mut pt_ggsw_lhs: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); + let mut pt_ggsw_rhs: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + let mut source_xa: Source = Source::new([0u8; 32]); + + pt_ggsw_lhs.fill_ternary_prob(0, 0.5, &mut source_xs); + + let k: usize = 1; + + pt_ggsw_rhs.to_mut().raw_mut()[k] = 1; //X^{k} + + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( + GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ggsw, rank) + | GGSWCiphertext::external_product_scratch_space(module, n, basek, k_out, k_in, k_ggsw, digits, rank), + ); + + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk.fill_ternary_prob(0.5, &mut source_xs); + let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); + + ct_ggsw_rhs.encrypt_sk( + module, + &pt_ggsw_rhs, + &sk_exec, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + ct_ggsw_lhs_in.encrypt_sk( + module, + &pt_ggsw_lhs, + &sk_exec, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + let mut ct_rhs_exec: GGSWCiphertextExec<Vec<u8>, B> = GGSWCiphertextExec::alloc(module, n, basek, k_ggsw, rows, digits, rank); + ct_rhs_exec.prepare(module, &ct_ggsw_rhs, scratch.borrow()); + + ct_ggsw_lhs_out.external_product(module, &ct_ggsw_lhs_in, &ct_rhs_exec, scratch.borrow()); + + module.vec_znx_rotate_inplace(k as i64, &mut pt_ggsw_lhs.as_vec_znx_mut(), 0); + + let var_gct_err_lhs: f64 = sigma * sigma; + let var_gct_err_rhs: f64 = 0f64; + + let var_msg: f64 = 1f64 / n as f64; // X^{k} + let var_a0_err: f64 = sigma * sigma; + let var_a1_err: f64 = 1f64 / 12f64; + + let max_noise = |_col_j: usize| -> f64 { + noise_ggsw_product( + n as f64, + basek * digits, + 0.5, + var_msg, + var_a0_err, + var_a1_err, + var_gct_err_lhs, + var_gct_err_rhs, + rank as f64, + k_in, + k_ggsw, + ) + 0.5 + }; + + ct_ggsw_lhs_out.assert_noise(module, &sk_exec, &pt_ggsw_lhs, &max_noise); +} + +pub fn test_ggsw_external_product_inplace<B: Backend>( + module: &Module<B>, + basek: usize, + k_ct: usize, + k_ggsw: usize, + digits: usize, + rank: usize, + sigma: f64, +) where + Module<B>: GLWESecretExecModuleFamily<B> + + GGSWEncryptSkFamily<B> + + GGSWAssertNoiseFamily<B> + + VecZnxAddScalarInplace + + VecZnxSubABInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc<B> + + VmpPMatPrepare<B> + + GGSWAssertNoiseFamily<B> + + GGSWKeySwitchFamily<B> + + GGLWESwitchingKeyEncryptSkFamily<B> + + GGLWETensorKeyEncryptSkFamily<B> + + VecZnxRotateInplace, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B> + + VecZnxDftAllocBytesImpl<B> + + VecZnxBigAllocBytesImpl<B> + + TakeSvpPPolImpl<B>, +{ + let n: usize = module.n(); + let rows: usize = k_ct.div_ceil(digits * basek); + let rows_in: usize = k_ct.div_euclid(basek * digits); + let digits_in: usize = 1; + + let mut ct_ggsw_lhs: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ct, rows_in, digits_in, rank); + let mut ct_ggsw_rhs: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank); + + let mut pt_ggsw_lhs: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); + let mut pt_ggsw_rhs: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + let mut source_xa: Source = Source::new([0u8; 32]); + + pt_ggsw_lhs.fill_ternary_prob(0, 0.5, &mut source_xs); + + let k: usize = 1; + + pt_ggsw_rhs.to_mut().raw_mut()[k] = 1; //X^{k} + + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( + GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ggsw, rank) + | GGSWCiphertext::external_product_inplace_scratch_space(module, n, basek, k_ct, k_ggsw, digits, rank), + ); + + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk.fill_ternary_prob(0.5, &mut source_xs); + let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); + + ct_ggsw_rhs.encrypt_sk( + module, + &pt_ggsw_rhs, + &sk_exec, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + ct_ggsw_lhs.encrypt_sk( + module, + &pt_ggsw_lhs, + &sk_exec, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + let mut ct_rhs_exec: GGSWCiphertextExec<Vec<u8>, B> = GGSWCiphertextExec::alloc(module, n, basek, k_ggsw, rows, digits, rank); + ct_rhs_exec.prepare(module, &ct_ggsw_rhs, scratch.borrow()); + + ct_ggsw_lhs.external_product_inplace(module, &ct_rhs_exec, scratch.borrow()); + + module.vec_znx_rotate_inplace(k as i64, &mut pt_ggsw_lhs.as_vec_znx_mut(), 0); + + let var_gct_err_lhs: f64 = sigma * sigma; + let var_gct_err_rhs: f64 = 0f64; + + let var_msg: f64 = 1f64 / n as f64; // X^{k} + let var_a0_err: f64 = sigma * sigma; + let var_a1_err: f64 = 1f64 / 12f64; + + let max_noise = |_col_j: usize| -> f64 { + noise_ggsw_product( + n as f64, + basek * digits, + 0.5, + var_msg, + var_a0_err, + var_a1_err, + var_gct_err_lhs, + var_gct_err_rhs, + rank as f64, + k_ct, + k_ggsw, + ) + 0.5 + }; + + ct_ggsw_lhs.assert_noise(module, &sk_exec, &pt_ggsw_lhs, &max_noise); +}
@@ -0,0 +1,7 @@
+mod gglwe_ksk; +mod ggsw_ct; +mod glwe_ct; + +pub use gglwe_ksk::*; +pub use ggsw_ct::*; +pub use glwe_ct::*;
@@ -0,0 +1,282 @@
+use backend::hal::{ + api::{ + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxStd, VecZnxSubScalarInplace, + VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, + }, + layouts::{Backend, Module, ScratchOwned}, + oep::{ + ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, + TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl, + }, +}; +use sampling::source::Source; + +use crate::{ + layouts::{ + GLWESecret, GGLWESwitchingKey, + prepared::{GLWESecretExec, GGLWESwitchingKeyExec}, + }, + noise::log2_std_noise_gglwe_product, + trait_families::{GLWEDecryptFamily, GLWEKeyswitchFamily}, +}; + +use crate::trait_families::{GGLWEEncryptSkFamily, GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; + +pub fn test_gglwe_switching_key_keyswitch<B: Backend>( + module: &Module<B>, + basek: usize, + k_out: usize, + k_in: usize, + k_ksk: usize, + digits: usize, + rank_in_s0s1: usize, + rank_out_s0s1: usize, + rank_out_s1s2: usize, + sigma: f64, +) where + Module<B>: GGLWEEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + + GLWEDecryptFamily<B> + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxStd + + VecZnxSubScalarInplace + + VecZnxCopy + + VmpPMatAlloc<B> + + VmpPMatPrepare<B> + + GGLWEEncryptSkFamily<B> + + GLWEDecryptFamily<B> + + GLWEKeyswitchFamily<B>, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B> + + VecZnxDftAllocBytesImpl<B> + + VecZnxBigAllocBytesImpl<B> + + TakeSvpPPolImpl<B>, +{ + let n: usize = module.n(); + let rows: usize = k_in.div_ceil(basek * digits); + let digits_in: usize = 1; + + let mut ct_gglwe_s0s1: GGLWESwitchingKey<Vec<u8>> = + GGLWESwitchingKey::alloc(n, basek, k_in, rows, digits_in, rank_in_s0s1, rank_out_s0s1); + let mut ct_gglwe_s1s2: GGLWESwitchingKey<Vec<u8>> = + GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_out_s0s1, rank_out_s1s2); + let mut ct_gglwe_s0s2: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc( + n, + basek, + k_out, + rows, + digits_in, + rank_in_s0s1, + rank_out_s1s2, + ); + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + let mut source_xa: Source = Source::new([0u8; 32]); + + let mut scratch_enc: ScratchOwned<B> = ScratchOwned::alloc(GGLWESwitchingKey::encrypt_sk_scratch_space( + module, + n, + basek, + k_ksk, + rank_in_s0s1 | rank_out_s0s1, + rank_out_s0s1 | rank_out_s1s2, + )); + let mut scratch_apply: ScratchOwned<B> = ScratchOwned::alloc(GGLWESwitchingKey::keyswitch_scratch_space( + module, + n, + basek, + k_out, + k_in, + k_ksk, + digits, + ct_gglwe_s1s2.rank_in(), + ct_gglwe_s1s2.rank_out(), + )); + + let mut sk0: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in_s0s1); + sk0.fill_ternary_prob(0.5, &mut source_xs); + + let mut sk1: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out_s0s1); + sk1.fill_ternary_prob(0.5, &mut source_xs); + + let mut sk2: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out_s1s2); + sk2.fill_ternary_prob(0.5, &mut source_xs); + let sk2_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk2); + + // gglwe_{s1}(s0) = s0 -> s1 + ct_gglwe_s0s1.encrypt_sk( + module, + &sk0, + &sk1, + &mut source_xa, + &mut source_xe, + sigma, + scratch_enc.borrow(), + ); + + // gglwe_{s2}(s1) -> s1 -> s2 + ct_gglwe_s1s2.encrypt_sk( + module, + &sk1, + &sk2, + &mut source_xa, + &mut source_xe, + sigma, + scratch_enc.borrow(), + ); + + let ct_gglwe_s1s2_exec: GGLWESwitchingKeyExec<Vec<u8>, B> = + GGLWESwitchingKeyExec::from(module, &ct_gglwe_s1s2, scratch_apply.borrow()); + + // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0) + ct_gglwe_s0s2.keyswitch( + module, + &ct_gglwe_s0s1, + &ct_gglwe_s1s2_exec, + scratch_apply.borrow(), + ); + + let max_noise: f64 = log2_std_noise_gglwe_product( + n as f64, + basek * digits, + 0.5, + 0.5, + 0f64, + sigma * sigma, + 0f64, + rank_out_s0s1 as f64, + k_in, + k_ksk, + ); + + ct_gglwe_s0s2 + .key + .assert_noise(module, &sk2_exec, &sk0.data, max_noise + 0.5); +} + +pub fn test_gglwe_switching_key_keyswitch_inplace<B: Backend>( + module: &Module<B>, + basek: usize, + k_ct: usize, + k_ksk: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + sigma: f64, +) where + Module<B>: GGLWEEncryptSkFamily<B> + + GLWESecretExecModuleFamily<B> + + GLWEDecryptFamily<B> + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxStd + + VecZnxSubScalarInplace + + VecZnxCopy + + VmpPMatAlloc<B> + + VmpPMatPrepare<B> + + GGLWESwitchingKeyEncryptSkFamily<B> + + GLWEKeyswitchFamily<B> + + GLWEDecryptFamily<B>, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B> + + VecZnxDftAllocBytesImpl<B> + + VecZnxBigAllocBytesImpl<B> + + TakeSvpPPolImpl<B>, +{ + let n: usize = module.n(); + let rows: usize = k_ct.div_ceil(basek * digits); + let digits_in: usize = 1; + + let mut ct_gglwe_s0s1: GGLWESwitchingKey<Vec<u8>> = + GGLWESwitchingKey::alloc(n, basek, k_ct, rows, digits_in, rank_in, rank_out); + let mut ct_gglwe_s1s2: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_out, rank_out); + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + let mut source_xa: Source = Source::new([0u8; 32]); + + let mut scratch_enc: ScratchOwned<B> = ScratchOwned::alloc(GGLWESwitchingKey::encrypt_sk_scratch_space( + module, + n, + basek, + k_ksk, + rank_in | rank_out, + rank_out, + )); + let mut scratch_apply: ScratchOwned<B> = ScratchOwned::alloc(GGLWESwitchingKey::keyswitch_inplace_scratch_space( + module, n, basek, k_ct, k_ksk, digits, rank_out, + )); + + let var_xs: f64 = 0.5; + + let mut sk0: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in); + sk0.fill_ternary_prob(var_xs, &mut source_xs); + + let mut sk1: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out); + sk1.fill_ternary_prob(var_xs, &mut source_xs); + + let mut sk2: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out); + sk2.fill_ternary_prob(var_xs, &mut source_xs); + let sk2_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk2); + + // gglwe_{s1}(s0) = s0 -> s1 + ct_gglwe_s0s1.encrypt_sk( + module, + &sk0, + &sk1, + &mut source_xa, + &mut source_xe, + sigma, + scratch_enc.borrow(), + ); + + // gglwe_{s2}(s1) -> s1 -> s2 + ct_gglwe_s1s2.encrypt_sk( + module, + &sk1, + &sk2, + &mut source_xa, + &mut source_xe, + sigma, + scratch_enc.borrow(), + ); + + let ct_gglwe_s1s2_exec: GGLWESwitchingKeyExec<Vec<u8>, B> = + GGLWESwitchingKeyExec::from(module, &ct_gglwe_s1s2, scratch_apply.borrow()); + + // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0) + ct_gglwe_s0s1.keyswitch_inplace(module, &ct_gglwe_s1s2_exec, scratch_apply.borrow()); + + let ct_gglwe_s0s2: GGLWESwitchingKey<Vec<u8>> = ct_gglwe_s0s1; + + let max_noise: f64 = log2_std_noise_gglwe_product( + n as f64, + basek * digits, + var_xs, + var_xs, + 0f64, + sigma * sigma, + 0f64, + rank_out as f64, + k_ct, + k_ksk, + ); + + ct_gglwe_s0s2 + .key + .assert_noise(module, &sk2_exec, &sk0.data, max_noise + 0.5); +}
@@ -0,0 +1,283 @@
+use backend::hal::{ + api::{ + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxStd, VecZnxSubABInplace, + VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, + }, + layouts::{Backend, Module, ScalarZnx, ScratchOwned}, + oep::{ + ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, + TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl, + }, +}; +use sampling::source::Source; + +use crate::{ + layouts::{ + GGLWETensorKey, GGSWCiphertext, GLWESecret, GGLWESwitchingKey, + prepared::{GLWESecretExec, GGLWESwitchingKeyExec, GGLWETensorKeyExec}, + }, + noise::noise_ggsw_keyswitch, + trait_families::GGSWAssertNoiseFamily, +}; + +use crate::trait_families::{ + GGLWESwitchingKeyEncryptSkFamily, GGLWETensorKeyEncryptSkFamily, GGSWEncryptSkFamily, GGSWKeySwitchFamily, + GLWESecretExecModuleFamily, +}; + +pub fn test_ggsw_keyswitch<B: Backend>( + module: &Module<B>, + basek: usize, + k_out: usize, + k_in: usize, + k_ksk: usize, + k_tsk: usize, + digits: usize, + rank: usize, + sigma: f64, +) where + Module<B>: GLWESecretExecModuleFamily<B> + + GGSWEncryptSkFamily<B> + + GGSWAssertNoiseFamily<B> + + VecZnxAddScalarInplace + + VecZnxSubABInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc<B> + + VmpPMatPrepare<B> + + GGSWAssertNoiseFamily<B> + + GGSWKeySwitchFamily<B> + + GGLWESwitchingKeyEncryptSkFamily<B> + + GGLWETensorKeyEncryptSkFamily<B> + + VecZnxSwithcDegree, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B> + + VecZnxDftAllocBytesImpl<B> + + VecZnxBigAllocBytesImpl<B> + + TakeSvpPPolImpl<B> + + VecZnxDftAllocBytesImpl<B> + + VecZnxBigAllocBytesImpl<B> + + TakeSvpPPolImpl<B>, +{ + let n: usize = module.n(); + let rows: usize = k_in.div_ceil(digits * basek); + + let digits_in: usize = 1; + + let mut ct_in: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_in, rows, digits_in, rank); + let mut ct_out: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_out, rows, digits_in, rank); + let mut tsk: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(n, basek, k_ksk, rows, digits, rank); + let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank, rank); + let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + let mut source_xa: Source = Source::new([0u8; 32]); + + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( + GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_in, rank) + | GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank, rank) + | GGLWETensorKey::encrypt_sk_scratch_space(module, n, basek, k_tsk, rank) + | GGSWCiphertext::keyswitch_scratch_space( + module, n, basek, k_out, k_in, k_ksk, digits, k_tsk, digits, rank, + ), + ); + + let var_xs: f64 = 0.5; + + let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk_in.fill_ternary_prob(var_xs, &mut source_xs); + let sk_in_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_in); + + let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk_out.fill_ternary_prob(var_xs, &mut source_xs); + let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); + + ksk.encrypt_sk( + module, + &sk_in, + &sk_out, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + tsk.encrypt_sk( + module, + &sk_out, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + pt_scalar.fill_ternary_hw(0, n, &mut source_xs); + + ct_in.encrypt_sk( + module, + &pt_scalar, + &sk_in_dft, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + let mut ksk_exec: GGLWESwitchingKeyExec<Vec<u8>, B> = + GGLWESwitchingKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank, rank); + let mut tsk_exec: GGLWETensorKeyExec<Vec<u8>, B> = GGLWETensorKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); + + ksk_exec.prepare(module, &ksk, scratch.borrow()); + tsk_exec.prepare(module, &tsk, scratch.borrow()); + + ct_out.keyswitch(module, &ct_in, &ksk_exec, &tsk_exec, scratch.borrow()); + + let max_noise = |col_j: usize| -> f64 { + noise_ggsw_keyswitch( + n as f64, + basek * digits, + col_j, + var_xs, + 0f64, + sigma * sigma, + 0f64, + rank as f64, + k_in, + k_ksk, + k_tsk, + ) + 0.5 + }; + + ct_out.assert_noise(module, &sk_out_exec, &pt_scalar, &max_noise); +} + +pub fn test_ggsw_keyswitch_inplace<B: Backend>( + module: &Module<B>, + basek: usize, + k_ct: usize, + k_ksk: usize, + k_tsk: usize, + digits: usize, + rank: usize, + sigma: f64, +) where + Module<B>: GLWESecretExecModuleFamily<B> + + GGSWEncryptSkFamily<B> + + GGSWAssertNoiseFamily<B> + + VecZnxAddScalarInplace + + VecZnxSubABInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc<B> + + VmpPMatPrepare<B> + + GGSWAssertNoiseFamily<B> + + GGSWKeySwitchFamily<B> + + GGLWESwitchingKeyEncryptSkFamily<B> + + GGLWETensorKeyEncryptSkFamily<B> + + VecZnxSwithcDegree, + B: TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + ScratchAvailableImpl<B> + + TakeScalarZnxImpl<B> + + TakeVecZnxImpl<B> + + VecZnxDftAllocBytesImpl<B> + + VecZnxBigAllocBytesImpl<B> + + TakeSvpPPolImpl<B>, +{ + let n: usize = module.n(); + let rows: usize = k_ct.div_ceil(digits * basek); + + let digits_in: usize = 1; + + let mut ct: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ct, rows, digits_in, rank); + let mut tsk: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(n, basek, k_tsk, rows, digits, rank); + let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank, rank); + let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + let mut source_xa: Source = Source::new([0u8; 32]); + + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( + GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ct, rank) + | GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk, rank, rank) + | GGLWETensorKey::encrypt_sk_scratch_space(module, n, basek, k_tsk, rank) + | GGSWCiphertext::keyswitch_inplace_scratch_space(module, n, basek, k_ct, k_ksk, digits, k_tsk, digits, rank), + ); + + let var_xs: f64 = 0.5; + + let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk_in.fill_ternary_prob(var_xs, &mut source_xs); + let sk_in_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_in); + + let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk_out.fill_ternary_prob(var_xs, &mut source_xs); + let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); + + ksk.encrypt_sk( + module, + &sk_in, + &sk_out, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + tsk.encrypt_sk( + module, + &sk_out, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + pt_scalar.fill_ternary_hw(0, n, &mut source_xs); + + ct.encrypt_sk( + module, + &pt_scalar, + &sk_in_dft, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + let mut ksk_exec: GGLWESwitchingKeyExec<Vec<u8>, B> = + GGLWESwitchingKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank, rank); + let mut tsk_exec: GGLWETensorKeyExec<Vec<u8>, B> = GGLWETensorKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); + + ksk_exec.prepare(module, &ksk, scratch.borrow()); + tsk_exec.prepare(module, &tsk, scratch.borrow()); + + ct.keyswitch_inplace(module, &ksk_exec, &tsk_exec, scratch.borrow()); + + let max_noise = |col_j: usize| -> f64 { + noise_ggsw_keyswitch( + n as f64, + basek * digits, + col_j, + var_xs, + 0f64, + sigma * sigma, + 0f64, + rank as f64, + k_ct, + k_ksk, + k_tsk, + ) + 0.5 + }; + + ct.assert_noise(module, &sk_out_exec, &pt_scalar, &max_noise); +}
@@ -0,0 +1,102 @@
+use backend::hal::{ + api::{ + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxEncodeCoeffsi64, + VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, ZnxView, + }, + layouts::{Backend, Module, ScratchOwned}, + oep::{ + ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, + TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, + }, +}; +use sampling::source::Source; + +use crate::layouts::{Infos, LWECiphertext, LWEPlaintext, LWESecret, LWESwitchingKey, prepared::LWESwitchingKeyExec}; + +use crate::trait_families::{GGLWEEncryptSkFamily, GLWEDecryptFamily, GLWEKeyswitchFamily, GLWESecretExecModuleFamily}; + +pub fn test_lwe_keyswitch<B: Backend>(module: &Module<B>) +where + Module<B>: GGLWEEncryptSkFamily<B> + + GLWEDecryptFamily<B> + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + GLWEKeyswitchFamily<B> + + VecZnxEncodeCoeffsi64 + + VecZnxAutomorphismInplace + + VmpPMatAlloc<B> + + VmpPMatPrepare<B> + + GLWESecretExecModuleFamily<B>, + B: TakeScalarZnxImpl<B> + + TakeVecZnxDftImpl<B> + + ScratchAvailableImpl<B> + + TakeVecZnxImpl<B> + + TakeVecZnxBigImpl<B> + + TakeSvpPPolImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B>, +{ + let n: usize = module.n(); + let basek: usize = 17; + let sigma: f64 = 3.2; + + let n_lwe_in: usize = 22; + let n_lwe_out: usize = 30; + let k_lwe_ct: usize = 2 * basek; + let k_lwe_pt: usize = 8; + + let k_ksk: usize = k_lwe_ct + basek; + + let mut source_xs: Source = Source::new([0u8; 32]); + let mut source_xa: Source = Source::new([0u8; 32]); + let mut source_xe: Source = Source::new([0u8; 32]); + + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( + LWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk) + | LWECiphertext::keyswitch_scratch_space(module, n, basek, k_lwe_ct, k_lwe_ct, k_ksk), + ); + + let mut sk_lwe_in: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe_in); + sk_lwe_in.fill_ternary_prob(0.5, &mut source_xs); + + let mut sk_lwe_out: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe_out); + sk_lwe_out.fill_ternary_prob(0.5, &mut source_xs); + + let data: i64 = 17; + + let mut lwe_pt_in: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_pt); + module.encode_coeff_i64(basek, &mut lwe_pt_in.data, 0, k_lwe_pt, 0, data, k_lwe_pt); + + let mut lwe_ct_in: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe_in, basek, k_lwe_ct); + lwe_ct_in.encrypt_sk( + module, + &lwe_pt_in, + &sk_lwe_in, + &mut source_xa, + &mut source_xe, + sigma, + ); + + let mut ksk: LWESwitchingKey<Vec<u8>> = LWESwitchingKey::alloc(n, basek, k_ksk, lwe_ct_in.size()); + + ksk.encrypt_sk( + module, + &sk_lwe_in, + &sk_lwe_out, + &mut source_xa, + &mut source_xe, + sigma, + scratch.borrow(), + ); + + let mut lwe_ct_out: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe_out, basek, k_lwe_ct); + + let ksk_exec: LWESwitchingKeyExec<Vec<u8>, B> = LWESwitchingKeyExec::from(module, &ksk, scratch.borrow()); + + lwe_ct_out.keyswitch(module, &lwe_ct_in, &ksk_exec, scratch.borrow()); + + let mut lwe_pt_out: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_ct); + lwe_ct_out.decrypt(module, &mut lwe_pt_out, &sk_lwe_out); + + assert_eq!(lwe_pt_in.data.at(0, 0)[0], lwe_pt_out.data.at(0, 0)[0]); +}
@@ -0,0 +1,9 @@
+mod gglwe_ct; +mod ggsw_ct; +mod glwe_ct; +mod lwe_ct; + +pub use gglwe_ct::*; +pub use ggsw_ct::*; +pub use glwe_ct::*; +pub use lwe_ct::*;
@@ -0,0 +1,12 @@
+pub mod automorphism; +pub mod encryption; +pub mod external_product; +pub mod keyswitch; + +mod conversion; +mod packing; +mod trace; + +pub use conversion::*; +pub use packing::*; +pub use trace::*;
@@ -0,0 +1,181 @@
+use backend::{ + hal::{api::ModuleNew, layouts::Module}, + implementation::cpu_spqlios::FFT64, +}; + +use crate::tests::generics::{ + automorphism::{test_glwe_automorphism, test_glwe_automorphism_inplace}, + encryption::{test_glwe_compressed_encrypt_sk, test_glwe_encrypt_pk, test_glwe_encrypt_sk, test_glwe_encrypt_zero_sk}, + external_product::{test_glwe_external_product, test_glwe_external_product_inplace}, + keyswitch::{test_glwe_keyswitch, test_glwe_keyswitch_inplace}, + test_glwe_packing, test_glwe_trace_inplace, +}; + +#[test] +fn glwe_encrypt_sk() { + let log_n: usize = 8; + let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); + (1..4).for_each(|rank| { + println!("test_glwe_encrypt_sk rank: {}", rank); + test_glwe_encrypt_sk(&module, 8, 54, 30, 3.2, rank); + }); +} + +#[test] +fn glwe_compressed_encrypt_sk() { + let log_n: usize = 8; + let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); + (1..4).for_each(|rank| { + println!("test_glwe_compressed_encrypt_sk rank: {}", rank); + test_glwe_compressed_encrypt_sk(&module, 8, 54, 30, 3.2, rank); + }); +} + +#[test] +fn glwe_encrypt_zero_sk() { + let log_n: usize = 8; + let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); + (1..4).for_each(|rank| { + println!("test_glwe_encrypt_zero_sk rank: {}", rank); + test_glwe_encrypt_zero_sk(&module, 8, 64, 3.2, rank); + }); +} + +#[test] +fn glwe_encrypt_pk() { + let log_n: usize = 8; + let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); + (1..4).for_each(|rank| { + println!("test_glwe_encrypt_pk rank: {}", rank); + test_glwe_encrypt_pk(&module, 8, 64, 64, 3.2, rank) + }); +} + +#[test] +fn glwe_keyswitch() { + let log_n: usize = 8; + let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); + let basek: usize = 12; + let k_in: usize = 45; + let digits: usize = k_in.div_ceil(basek); + (1..4).for_each(|rank_in| { + (1..4).for_each(|rank_out| { + (1..digits + 1).for_each(|di| { + let k_ksk: usize = k_in + basek * di; + let k_out: usize = k_ksk; // better capture noise + println!( + "test_glwe_keyswitch digits: {} rank_in: {} rank_out: {}", + di, rank_in, rank_out + ); + test_glwe_keyswitch( + &module, basek, k_out, k_in, k_ksk, di, rank_in, rank_out, 3.2, + ); + }) + }); + }); +} + +#[test] +fn glwe_keyswitch_inplace() { + let log_n: usize = 8; + let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); + let basek: usize = 12; + let k_ct: usize = 45; + let digits: usize = k_ct.div_ceil(basek); + (1..4).for_each(|rank| { + (1..digits + 1).for_each(|di| { + let k_ksk: usize = k_ct + basek * di; + println!("test_glwe_keyswitch_inplace digits: {} rank: {}", di, rank); + test_glwe_keyswitch_inplace(&module, basek, k_ct, k_ksk, di, rank, 3.2); + }); + }); +} + +#[test] +fn glwe_automorphism() { + let log_n: usize = 8; + let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); + let basek: usize = 12; + let k_in: usize = 60; + let digits: usize = k_in.div_ceil(basek); + (1..4).for_each(|rank| { + (1..digits + 1).for_each(|di| { + let k_ksk: usize = k_in + basek * di; + let k_out: usize = k_ksk; // Better capture noise. + println!("test_glwe_automorphism digits: {} rank: {}", di, rank); + test_glwe_automorphism(&module, basek, -5, k_out, k_in, k_ksk, di, rank, 3.2); + }) + }); +} + +#[test] +fn glwe_automorphism_inplace() { + let log_n: usize = 8; + let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); + let basek: usize = 12; + let k_ct: usize = 60; + let digits: usize = k_ct.div_ceil(basek); + (1..4).for_each(|rank| { + (1..digits + 1).for_each(|di| { + let k_ksk: usize = k_ct + basek * di; + println!( + "test_glwe_automorphism_inplace digits: {} rank: {}", + di, rank + ); + test_glwe_automorphism_inplace(&module, basek, -5, k_ct, k_ksk, di, rank, 3.2); + }); + }); +} + +#[test] +fn glwe_external_product() { + let log_n: usize = 8; + let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); + let basek: usize = 12; + let k_in: usize = 45; + let digits: usize = k_in.div_ceil(basek); + (1..4).for_each(|rank| { + (1..digits + 1).for_each(|di| { + let k_ggsw: usize = k_in + basek * di; + let k_out: usize = k_ggsw; // Better capture noise + println!("test_glwe_external_product digits: {} rank: {}", di, rank); + test_glwe_external_product(&module, basek, k_out, k_in, k_ggsw, di, rank, 3.2); + }); + }); +} + +#[test] +fn glwe_external_product_inplace() { + let log_n: usize = 8; + let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); + let basek: usize = 12; + let k_ct: usize = 60; + let digits: usize = k_ct.div_ceil(basek); + (1..4).for_each(|rank| { + (1..digits + 1).for_each(|di| { + let k_ggsw: usize = k_ct + basek * di; + println!( + "test_glwe_external_product_inplace digits: {} rank: {}", + di, rank + ); + test_glwe_external_product_inplace(&module, basek, k_ct, k_ggsw, di, rank, 3.2); + }); + }); +} + +#[test] +fn glwe_trace_inplace() { + let log_n: usize = 8; + let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); + (1..4).for_each(|rank| { + println!("test_glwe_trace_inplace rank: {}", rank); + test_glwe_trace_inplace(&module, 8, 54, 3.2, rank); + }); +} + +#[test] +fn glwe_packing() { + let log_n: usize = 5; + let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n); + test_glwe_packing(&module); +}
@@ -0,0 +1,4 @@
+mod gglwe; +mod ggws; +mod glwe; +mod lwe;
@@ -0,0 +1,7 @@
+pub mod generics; + +#[cfg(test)] +mod implementation; + +#[cfg(test)] +mod serialization;
@@ -0,0 +1,139 @@
+use backend::hal::tests::serialization::test_reader_writer_interface; + +use crate::layouts::{ + GGLWEAutomorphismKey, GGLWECiphertext, GGLWETensorKey, GGSWCiphertext, GLWECiphertext, GGLWESwitchingKey, + GLWEToLWESwitchingKey, LWECiphertext, LWESwitchingKey, LWEToGLWESwitchingKey, + compressed::{ + GGLWEAutomorphismKeyCompressed, GGLWECiphertextCompressed, GGSWCiphertextCompressed, GLWECiphertextCompressed, + GGLWESwitchingKeyCompressed, GGLWETensorKeyCompressed, GLWEToLWESwitchingKeyCompressed, LWECiphertextCompressed, + LWESwitchingKeyCompressed, LWEToGLWESwitchingKeyCompressed, + }, +}; + +const N_GLWE: usize = 64; +const N_LWE: usize = 32; +const BASEK: usize = 12; +const K: usize = 33; +const ROWS: usize = 2; +const RANK: usize = 2; +const DIGITS: usize = 1; + +#[test] +fn glwe_serialization() { + let original: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(N_GLWE, BASEK, K, RANK); + backend::hal::tests::serialization::test_reader_writer_interface(original); +} + +#[test] +fn glwe_compressed_serialization() { + let original: GLWECiphertextCompressed<Vec<u8>> = GLWECiphertextCompressed::alloc(N_GLWE, BASEK, K, RANK); + test_reader_writer_interface(original); +} + +#[test] +fn lwe_serialization() { + let original: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(N_LWE, BASEK, K); + test_reader_writer_interface(original); +} + +#[test] +fn lwe_compressed_serialization() { + let original: LWECiphertextCompressed<Vec<u8>> = LWECiphertextCompressed::alloc(BASEK, K); + test_reader_writer_interface(original); +} + +#[test] +fn test_gglwe_serialization() { + let original: GGLWECiphertext<Vec<u8>> = GGLWECiphertext::alloc(1024, 12, 54, 3, 1, 2, 2); + test_reader_writer_interface(original); +} + +#[test] +fn test_gglwe_compressed_serialization() { + let original: GGLWECiphertextCompressed<Vec<u8>> = GGLWECiphertextCompressed::alloc(1024, 12, 54, 3, 1, 2, 2); + test_reader_writer_interface(original); +} + +#[test] +fn test_glwe_switching_key_serialization() { + let original: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(1024, 12, 54, 3, 1, 2, 2); + test_reader_writer_interface(original); +} + +#[test] +fn test_glwe_switching_key_compressed_serialization() { + let original: GGLWESwitchingKeyCompressed<Vec<u8>> = GGLWESwitchingKeyCompressed::alloc(1024, 12, 54, 3, 1, 2, 2); + test_reader_writer_interface(original); +} + +#[test] +fn test_automorphism_key_serialization() { + let original: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(1024, 12, 54, 3, 1, 2); + test_reader_writer_interface(original); +} + +#[test] +fn test_automorphism_key_compressed_serialization() { + let original: GGLWEAutomorphismKeyCompressed<Vec<u8>> = GGLWEAutomorphismKeyCompressed::alloc(1024, 12, 54, 3, 1, 2); + test_reader_writer_interface(original); +} + +#[test] +fn test_tensor_key_serialization() { + let original: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(1024, 12, 54, 3, 1, 2); + test_reader_writer_interface(original); +} + +#[test] +fn test_tensor_key_compressed_serialization() { + let original: GGLWETensorKeyCompressed<Vec<u8>> = GGLWETensorKeyCompressed::alloc(1024, 12, 54, 3, 1, 2); + test_reader_writer_interface(original); +} + +#[test] +fn glwe_to_lwe_switching_key_serialization() { + let original: GLWEToLWESwitchingKey<Vec<u8>> = GLWEToLWESwitchingKey::alloc(N_GLWE, BASEK, K, ROWS, RANK); + test_reader_writer_interface(original); +} + +#[test] +fn glwe_to_lwe_switching_key_compressed_serialization() { + let original: GLWEToLWESwitchingKeyCompressed<Vec<u8>> = GLWEToLWESwitchingKeyCompressed::alloc(N_GLWE, BASEK, K, ROWS, RANK); + test_reader_writer_interface(original); +} + +#[test] +fn lwe_to_glwe_switching_key_serialization() { + let original: LWEToGLWESwitchingKey<Vec<u8>> = LWEToGLWESwitchingKey::alloc(N_GLWE, BASEK, K, ROWS, RANK); + test_reader_writer_interface(original); +} + +#[test] +fn lwe_to_glwe_switching_key_compressed_serialization() { + let original: LWEToGLWESwitchingKeyCompressed<Vec<u8>> = LWEToGLWESwitchingKeyCompressed::alloc(N_GLWE, BASEK, K, ROWS, RANK); + test_reader_writer_interface(original); +} + +#[test] +fn lwe_switching_key_serialization() { + let original: LWESwitchingKey<Vec<u8>> = LWESwitchingKey::alloc(N_GLWE, BASEK, K, ROWS); + test_reader_writer_interface(original); +} + +#[test] +fn lwe_switching_key_compressed_serialization() { + let original: LWESwitchingKeyCompressed<Vec<u8>> = LWESwitchingKeyCompressed::alloc(N_GLWE, BASEK, K, ROWS); + test_reader_writer_interface(original); +} + +#[test] +fn ggsw_serialization() { + let original: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(N_GLWE, BASEK, K, ROWS, DIGITS, RANK); + test_reader_writer_interface(original); +} + +#[test] +fn ggsw_compressed_serialization() { + let original: GGSWCiphertextCompressed<Vec<u8>> = GGSWCiphertextCompressed::alloc(N_GLWE, BASEK, K, ROWS, DIGITS, RANK); + test_reader_writer_interface(original); +}
@@ -0,0 +1,104 @@
+use backend::hal::{ + api::{ + ScratchAvailable, SvpApply, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, TakeVecZnxDft, + VecZnxAddInplace, VecZnxAddNormal, VecZnxAutomorphismInplace, VecZnxBigAddInplace, VecZnxBigAddNormal, + VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigAllocBytes, VecZnxBigAutomorphismInplace, VecZnxBigNormalize, + VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallBInplace, VecZnxCopy, VecZnxDftAddInplace, VecZnxDftAlloc, + VecZnxDftAllocBytes, VecZnxDftCopy, VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigConsume, VecZnxDftToVecZnxBigTmpA, + VecZnxFillUniform, VecZnxNegateInplace, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, + VecZnxRotateInplace, VecZnxRshInplace, VecZnxSub, VecZnxSubABInplace, VmpApply, VmpApplyAdd, VmpApplyTmpBytes, + VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare, + }, + layouts::{Backend, Module}, +}; + +pub trait GGSWKeySwitchFamily<B> = + GLWEKeyswitchFamily<B> + VecZnxBigAllocBytes + VecZnxDftCopy<B> + VecZnxDftAddInplace<B> + VecZnxDftToVecZnxBigTmpA<B>; +pub trait GGLWEEncryptSkFamily<B: Backend> = GLWEEncryptSkFamily<B>; +pub trait GGLWESwitchingKeyEncryptSkFamily<B: Backend> = GGLWEEncryptSkFamily<B>; +pub trait GGLWEAutomorphismKeyEncryptSkFamily<B: Backend> = GGLWEEncryptSkFamily<B>; +pub trait GGLWETensorKeyEncryptSkFamily<B: Backend> = + GGLWEEncryptSkFamily<B> + VecZnxBigAllocBytes + VecZnxDftToVecZnxBigTmpA<B> + SvpApply<B>; +pub trait GGSWEncryptSkFamily<B: Backend> = GLWEEncryptSkFamily<B>; +pub trait GGSWAssertNoiseFamily<B: Backend> = GLWEDecryptFamily<B> + + VecZnxBigAlloc<B> + + VecZnxDftAlloc<B> + + VecZnxBigNormalizeTmpBytes + + VecZnxBigNormalize<B> + + VecZnxDftToVecZnxBigTmpA<B>; +pub trait GLWEDecryptFamily<B: Backend> = VecZnxDftAllocBytes + + VecZnxBigAllocBytes + + VecZnxDftFromVecZnx<B> + + SvpApplyInplace<B> + + VecZnxDftToVecZnxBigConsume<B> + + VecZnxBigAddInplace<B> + + VecZnxBigAddSmallInplace<B> + + VecZnxBigNormalize<B> + + VecZnxNormalizeTmpBytes; +pub trait GLWEEncryptSkFamily<B: Backend> = VecZnxDftAllocBytes + + VecZnxBigNormalize<B> + + VecZnxDftFromVecZnx<B> + + SvpApplyInplace<B> + + VecZnxDftToVecZnxBigConsume<B> + + VecZnxNormalizeTmpBytes + + VecZnxFillUniform + + VecZnxSubABInplace + + VecZnxAddInplace + + VecZnxNormalizeInplace<B> + + VecZnxAddNormal + + VecZnxNormalize<B> + + VecZnxSub; +pub trait GLWEEncryptPkFamily<B: Backend> = VecZnxDftAllocBytes + + VecZnxBigAllocBytes + + SvpPPolAllocBytes + + SvpPrepare<B> + + SvpApply<B> + + VecZnxDftToVecZnxBigConsume<B> + + VecZnxBigAddNormal<B> + + VecZnxBigAddSmallInplace<B> + + VecZnxBigNormalize<B> + + VecZnxNormalizeTmpBytes; +pub trait GLWEExternalProductFamily<B: Backend> = VecZnxDftAllocBytes + + VmpApplyTmpBytes + + VmpApply<B> + + VmpApplyAdd<B> + + VecZnxDftFromVecZnx<B> + + VecZnxDftToVecZnxBigConsume<B> + + VecZnxBigNormalize<B> + + VecZnxNormalizeTmpBytes; +pub trait GLWEKeyswitchFamily<B: Backend> = VecZnxDftAllocBytes + + VmpApplyTmpBytes + + VecZnxBigNormalizeTmpBytes + + VmpApplyTmpBytes + + VmpApply<B> + + VmpApplyAdd<B> + + VecZnxDftFromVecZnx<B> + + VecZnxDftToVecZnxBigConsume<B> + + VecZnxBigAddSmallInplace<B> + + VecZnxBigNormalize<B>; +pub trait GLWEPackingFamily<B: Backend> = GLWEKeyswitchFamily<B> + + VecZnxCopy + + VecZnxRotateInplace + + VecZnxSub + + VecZnxNegateInplace + + VecZnxRshInplace + + VecZnxAddInplace + + VecZnxNormalizeInplace<B> + + VecZnxSubABInplace + + VecZnxRotate + + VecZnxAutomorphismInplace + + VecZnxBigSubSmallBInplace<B> + + VecZnxBigAutomorphismInplace<B>; +pub trait GLWESecretExecModuleFamily<B: Backend> = SvpPrepare<B> + SvpPPolAllocBytes + SvpPPolAlloc<B>; +pub trait GGLWEExecLayoutFamily<B: Backend> = VmpPMatAlloc<B> + VmpPMatAllocBytes + VmpPMatPrepare<B>; +pub trait GLWETraceModuleFamily<B: Backend> = + GLWEKeyswitchFamily<B> + VecZnxCopy + VecZnxRshInplace + VecZnxBigAutomorphismInplace<B>; +pub trait GLWETraceScratchFamily<B: Backend> = TakeVecZnxDft<B> + ScratchAvailable; +pub trait GGSWLayoutFamily<B: Backend> = VmpPMatAlloc<B> + VmpPMatAllocBytes + VmpPMatPrepare<B>; + +pub trait DecompressFamily<B: Backend> = VecZnxFillUniform + VecZnxCopy; +pub trait Decompress<B: Backend, C> { + fn decompress(&mut self, module: &Module<B>, other: &C) + where + Module<B>: DecompressFamily<B>; +}