diff --git a/core/src/blind_rotation/cggi.rs b/bin_fhe/blind_rotation/cggi.rs similarity index 98% rename from core/src/blind_rotation/cggi.rs rename to bin_fhe/blind_rotation/cggi.rs index 1eabdac..b64cef3 100644 --- a/core/src/blind_rotation/cggi.rs +++ b/bin_fhe/blind_rotation/cggi.rs @@ -11,10 +11,11 @@ use backend::hal::{ 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 = VecZnxBigAllocBytes diff --git a/core/src/blind_rotation/key.rs b/bin_fhe/blind_rotation/key.rs similarity index 93% rename from core/src/blind_rotation/key.rs rename to bin_fhe/blind_rotation/key.rs index 7f4aa51..9a33068 100644 --- a/core/src/blind_rotation/key.rs +++ b/bin_fhe/blind_rotation/key.rs @@ -1,17 +1,23 @@ 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 { pub(crate) keys: Vec>, @@ -246,12 +252,12 @@ impl BlindRotationKeyCGGIExec { } } -pub trait BlindRotationKeyCGGIExecLayoutFamily = GGSWLayoutFamily + SvpPPolAlloc + SvpPrepare; +pub trait BlindRotationKeyCGGIExecLayoutFamily = SvpPPolAlloc + SvpPrepare; impl BlindRotationKeyCGGIExec, B> { pub fn alloc(module: &Module, n_glwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self where - Module: BlindRotationKeyCGGIExecLayoutFamily, + Module: BlindRotationKeyCGGIExecLayoutFamily + VmpPMatAlloc + VmpPMatPrepare, { let mut data: Vec, B>> = Vec::with_capacity(n_lwe); (0..n_lwe).for_each(|_| { @@ -269,7 +275,7 @@ impl BlindRotationKeyCGGIExec, B> { pub fn from(module: &Module, other: &BlindRotationKeyCGGI, scratch: &mut Scratch) -> Self where DataOther: DataRef, - Module: BlindRotationKeyCGGIExecLayoutFamily, + Module: BlindRotationKeyCGGIExecLayoutFamily + VmpPMatAlloc + VmpPMatPrepare, { let mut brk: BlindRotationKeyCGGIExec, B> = Self::alloc( module, @@ -289,7 +295,7 @@ impl BlindRotationKeyCGGIExec { pub fn prepare(&mut self, module: &Module, other: &BlindRotationKeyCGGI, scratch: &mut Scratch) where DataOther: DataRef, - Module: BlindRotationKeyCGGIExecLayoutFamily, + Module: BlindRotationKeyCGGIExecLayoutFamily + VmpPMatAlloc + VmpPMatPrepare, { #[cfg(debug_assertions)] { diff --git a/core/src/blind_rotation/key_compressed.rs b/bin_fhe/blind_rotation/key_compressed.rs similarity index 97% rename from core/src/blind_rotation/key_compressed.rs rename to bin_fhe/blind_rotation/key_compressed.rs index b30c753..52501dd 100644 --- a/core/src/blind_rotation/key_compressed.rs +++ b/bin_fhe/blind_rotation/key_compressed.rs @@ -4,9 +4,14 @@ use backend::hal::{ }; 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 { pub(crate) keys: Vec>, diff --git a/core/src/blind_rotation/lut.rs b/bin_fhe/blind_rotation/lut.rs similarity index 100% rename from core/src/blind_rotation/lut.rs rename to bin_fhe/blind_rotation/lut.rs diff --git a/core/src/blind_rotation/mod.rs b/bin_fhe/blind_rotation/mod.rs similarity index 100% rename from core/src/blind_rotation/mod.rs rename to bin_fhe/blind_rotation/mod.rs diff --git a/core/src/blind_rotation/tests/cpu_spqlios/fft64.rs b/bin_fhe/blind_rotation/tests/cpu_spqlios/fft64.rs similarity index 100% rename from core/src/blind_rotation/tests/cpu_spqlios/fft64.rs rename to bin_fhe/blind_rotation/tests/cpu_spqlios/fft64.rs diff --git a/core/src/blind_rotation/tests/cpu_spqlios/mod.rs b/bin_fhe/blind_rotation/tests/cpu_spqlios/mod.rs similarity index 100% rename from core/src/blind_rotation/tests/cpu_spqlios/mod.rs rename to bin_fhe/blind_rotation/tests/cpu_spqlios/mod.rs diff --git a/core/src/blind_rotation/tests/generic_cggi.rs b/bin_fhe/blind_rotation/tests/generic_cggi.rs similarity index 89% rename from core/src/blind_rotation/tests/generic_cggi.rs rename to bin_fhe/blind_rotation/tests/generic_cggi.rs index 01c1a8b..bb53d98 100644 --- a/core/src/blind_rotation/tests/generic_cggi.rs +++ b/bin_fhe/blind_rotation/tests/generic_cggi.rs @@ -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 backend::hal::{ 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 = CCGIBlindRotationFamily - + GLWESecretFamily + + GLWESecretExecModuleFamily + GLWEDecryptFamily + BlindRotationKeyCGGIExecLayoutFamily + VecZnxFillUniform @@ -27,7 +33,9 @@ pub(crate) trait CGGITestModuleFamily = CCGIBlindRotationFamily + VecZnxEncodeCoeffsi64 + VecZnxRotateInplace + VecZnxSwithcDegree - + VecZnxSub; + + VecZnxSub + + VmpPMatAlloc + + VmpPMatPrepare; pub(crate) trait CGGITestScratchFamily = VecZnxDftAllocBytesImpl + VecZnxBigAllocBytesImpl + ScratchOwnedAllocImpl diff --git a/core/src/blind_rotation/tests/generic_lut.rs b/bin_fhe/blind_rotation/tests/generic_lut.rs similarity index 100% rename from core/src/blind_rotation/tests/generic_lut.rs rename to bin_fhe/blind_rotation/tests/generic_lut.rs diff --git a/core/src/blind_rotation/tests/generic_serialization.rs b/bin_fhe/blind_rotation/tests/generic_serialization.rs similarity index 100% rename from core/src/blind_rotation/tests/generic_serialization.rs rename to bin_fhe/blind_rotation/tests/generic_serialization.rs diff --git a/core/src/blind_rotation/tests/generics_automorphism_key.rs b/bin_fhe/blind_rotation/tests/generics_automorphism_key.rs similarity index 100% rename from core/src/blind_rotation/tests/generics_automorphism_key.rs rename to bin_fhe/blind_rotation/tests/generics_automorphism_key.rs diff --git a/core/src/blind_rotation/tests/key.rs b/bin_fhe/blind_rotation/tests/key.rs similarity index 100% rename from core/src/blind_rotation/tests/key.rs rename to bin_fhe/blind_rotation/tests/key.rs diff --git a/core/src/blind_rotation/tests/mod.rs b/bin_fhe/blind_rotation/tests/mod.rs similarity index 100% rename from core/src/blind_rotation/tests/mod.rs rename to bin_fhe/blind_rotation/tests/mod.rs diff --git a/core/src/circuit_bootstrapping/circuit_bootstrapping.rs b/bin_fhe/circuit_bootstrapping/circuit_bootstrapping.rs similarity index 94% rename from core/src/circuit_bootstrapping/circuit_bootstrapping.rs rename to bin_fhe/circuit_bootstrapping/circuit_bootstrapping.rs index 44124b9..de4cd07 100644 --- a/core/src/circuit_bootstrapping/circuit_bootstrapping.rs +++ b/bin_fhe/circuit_bootstrapping/circuit_bootstrapping.rs @@ -6,7 +6,7 @@ use backend::hal::{ 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 backend::hal::{ 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 { @@ -45,8 +51,8 @@ impl CircuitBootstrappingKeyCGGI> { scratch: &mut Scratch, ) -> Self where - Module: GLWESecretFamily - + GGSWEncryptSkFamily + Module: GGSWEncryptSkFamily + + GLWESecretExecModuleFamily + VecZnxAddScalarInplace + AutomorphismKeyEncryptSkFamily + VecZnxAutomorphism @@ -111,7 +117,7 @@ impl CircuitBootstrappingKeyCGGIExec, B> { scratch: &mut Scratch, ) -> CircuitBootstrappingKeyCGGIExec, B> where - Module: BlindRotationKeyCGGIExecLayoutFamily, + Module: BlindRotationKeyCGGIExecLayoutFamily + VmpPMatAlloc + VmpPMatPrepare, { let brk: BlindRotationKeyCGGIExec, B> = BlindRotationKeyCGGIExec::from(module, &other.brk, scratch); let tsk: GLWETensorKeyExec, B> = GLWETensorKeyExec::from(module, &other.tsk, scratch); @@ -137,7 +143,7 @@ pub trait CGGICircuitBootstrapFamily = VecZnxRotateInplace + VecZnxNegateInplace + VecZnxCopy + VecZnxSubABInplace - + GLWETraceFamily + + GLWETraceModuleFamily + VecZnxRotateInplace + VecZnxAutomorphismInplace + VecZnxBigSubSmallBInplace; diff --git a/core/src/circuit_bootstrapping/mod.rs b/bin_fhe/circuit_bootstrapping/mod.rs similarity index 100% rename from core/src/circuit_bootstrapping/mod.rs rename to bin_fhe/circuit_bootstrapping/mod.rs diff --git a/core/src/circuit_bootstrapping/test_fft64/circuit_bootstrapping.rs b/bin_fhe/circuit_bootstrapping/test_fft64/circuit_bootstrapping.rs similarity index 94% rename from core/src/circuit_bootstrapping/test_fft64/circuit_bootstrapping.rs rename to bin_fhe/circuit_bootstrapping/test_fft64/circuit_bootstrapping.rs index 59cd010..0410ec7 100644 --- a/core/src/circuit_bootstrapping/test_fft64/circuit_bootstrapping.rs +++ b/bin_fhe/circuit_bootstrapping/test_fft64/circuit_bootstrapping.rs @@ -5,7 +5,7 @@ use backend::{ 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 backend::{ 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 test_to_exponent() { fn to_exponent(module: &Module) where - Module: GLWESecretFamily - + VecZnxEncodeCoeffsi64 + Module: VecZnxEncodeCoeffsi64 + VecZnxFillUniform + VecZnxAddNormal + VecZnxNormalizeInplace - + GLWESecretFamily + GGSWEncryptSkFamily + VecZnxAddScalarInplace + AutomorphismKeyEncryptSkFamily @@ -52,7 +55,9 @@ where + CGGICircuitBootstrapFamily + GLWEDecryptFamily + GGSWAssertNoiseFamily - + VecZnxStd, + + VecZnxStd + + VmpPMatAlloc + + VmpPMatPrepare, B: ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl + TakeVecZnxDftImpl @@ -202,12 +207,10 @@ fn test_to_constant() { fn to_constant(module: &Module) where - Module: GLWESecretFamily - + VecZnxEncodeCoeffsi64 + Module: VecZnxEncodeCoeffsi64 + VecZnxFillUniform + VecZnxAddNormal + VecZnxNormalizeInplace - + GLWESecretFamily + GGSWEncryptSkFamily + VecZnxAddScalarInplace + AutomorphismKeyEncryptSkFamily @@ -218,7 +221,9 @@ where + CGGICircuitBootstrapFamily + GLWEDecryptFamily + GGSWAssertNoiseFamily - + VecZnxStd, + + VecZnxStd + + VmpPMatAlloc + + VmpPMatPrepare, B: ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl + TakeVecZnxDftImpl diff --git a/core/src/circuit_bootstrapping/test_fft64/mod.rs b/bin_fhe/circuit_bootstrapping/test_fft64/mod.rs similarity index 100% rename from core/src/circuit_bootstrapping/test_fft64/mod.rs rename to bin_fhe/circuit_bootstrapping/test_fft64/mod.rs diff --git a/core/benches/external_product_glwe_fft64.rs b/core/benches/external_product_glwe_fft64.rs index b0c9c1b..db47ebb 100644 --- a/core/benches/external_product_glwe_fft64.rs +++ b/core/benches/external_product_glwe_fft64.rs @@ -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::{ diff --git a/core/benches/keyswitch_glwe_fft64.rs b/core/benches/keyswitch_glwe_fft64.rs index 2a41836..29f30d3 100644 --- a/core/benches/keyswitch_glwe_fft64.rs +++ b/core/benches/keyswitch_glwe_fft64.rs @@ -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 @@ fn bench_keyswitch_glwe_fft64(c: &mut Criterion) { let rows: usize = p.k_ct_in.div_ceil(p.basek * digits); let sigma: f64 = 3.2; - let mut ksk: AutomorphismKey> = AutomorphismKey::alloc(n, basek, k_grlwe, rows, digits, rank_out); + let mut ksk: GGLWEAutomorphismKey> = GGLWEAutomorphismKey::alloc(n, basek, k_grlwe, rows, digits, rank_out); let mut ct_in: GLWECiphertext> = GLWECiphertext::alloc(n, basek, k_rlwe_in, rank_in); let mut ct_out: GLWECiphertext> = GLWECiphertext::alloc(n, basek, k_rlwe_out, rank_out); let mut scratch: ScratchOwned = 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 @@ fn bench_keyswitch_glwe_fft64(c: &mut Criterion) { scratch.borrow(), ); - let ksk_exec: AutomorphismKeyExec, _> = AutomorphismKeyExec::from(&module, &ksk, scratch.borrow()); + let ksk_exec: GGLWEAutomorphismKeyExec, _> = GGLWEAutomorphismKeyExec::from(&module, &ksk, scratch.borrow()); move || { black_box(ct_out.automorphism(&module, &ct_in, &ksk_exec, scratch.borrow())); @@ -149,11 +146,11 @@ fn bench_keyswitch_glwe_inplace_fft64(c: &mut Criterion) { let rows: usize = p.k_ct.div_ceil(p.basek); let sigma: f64 = 3.2; - let mut ksk: GLWESwitchingKey> = GLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank, rank); + let mut ksk: GGLWESwitchingKey> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank, rank); let mut ct: GLWECiphertext> = GLWECiphertext::alloc(n, basek, k_ct, rank); let mut scratch: ScratchOwned = 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 @@ fn bench_keyswitch_glwe_inplace_fft64(c: &mut Criterion) { scratch.borrow(), ); - let ksk_exec: GLWESwitchingKeyExec, FFT64> = GLWESwitchingKeyExec::from(&module, &ksk, scratch.borrow()); + let ksk_exec: GGLWESwitchingKeyExec, FFT64> = GGLWESwitchingKeyExec::from(&module, &ksk, scratch.borrow()); move || { black_box(ct.keyswitch_inplace(&module, &ksk_exec, scratch.borrow())); diff --git a/core/src/gglwe/automorphism.rs b/core/src/automorphism/gglwe_atk.rs similarity index 86% rename from core/src/gglwe/automorphism.rs rename to core/src/automorphism/gglwe_atk.rs index 19b7e88..2a5c7f2 100644 --- a/core/src/gglwe/automorphism.rs +++ b/core/src/automorphism/gglwe_atk.rs @@ -3,9 +3,12 @@ use backend::hal::{ 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> { +impl GGLWEAutomorphismKey> { pub fn automorphism_scratch_space( module: &Module, n: usize, @@ -34,16 +37,16 @@ impl AutomorphismKey> { where Module: GLWEKeyswitchFamily, { - 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 AutomorphismKey { +impl GGLWEAutomorphismKey { pub fn automorphism<'a, DataLhs: DataRef, DataRhs: DataRef, B: Backend>( &mut self, module: &Module, - lhs: &AutomorphismKey, - rhs: &AutomorphismKeyExec, + lhs: &GGLWEAutomorphismKey, + rhs: &GGLWEAutomorphismKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily + VecZnxAutomorphism + VecZnxAutomorphismInplace, @@ -117,14 +120,14 @@ impl AutomorphismKey { pub fn automorphism_inplace( &mut self, module: &Module, - rhs: &AutomorphismKeyExec, + rhs: &GGLWEAutomorphismKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily + VecZnxAutomorphism + VecZnxAutomorphismInplace, Scratch: TakeVecZnxDft + ScratchAvailable, { unsafe { - let self_ptr: *mut AutomorphismKey = self as *mut AutomorphismKey; + let self_ptr: *mut GGLWEAutomorphismKey = self as *mut GGLWEAutomorphismKey; self.automorphism(&module, &*self_ptr, rhs, scratch); } } diff --git a/core/src/ggsw/automorphism.rs b/core/src/automorphism/ggsw_ct.rs similarity index 91% rename from core/src/ggsw/automorphism.rs rename to core/src/automorphism/ggsw_ct.rs index 1081828..fc76dbf 100644 --- a/core/src/ggsw/automorphism.rs +++ b/core/src/automorphism/ggsw_ct.rs @@ -4,7 +4,11 @@ use backend::hal::{ }; use crate::{ - AutomorphismKeyExec, GGSWCiphertext, GGSWKeySwitchFamily, GLWECiphertext, GLWEKeyswitchFamily, GLWETensorKeyExec, Infos, + layouts::{ + GGSWCiphertext, GLWECiphertext, Infos, + prepared::{GGLWEAutomorphismKeyExec, GGLWETensorKeyExec}, + }, + trait_families::{GGSWKeySwitchFamily, GLWEKeyswitchFamily}, }; impl GGSWCiphertext> { @@ -56,8 +60,8 @@ impl GGSWCiphertext { &mut self, module: &Module, lhs: &GGSWCiphertext, - auto_key: &AutomorphismKeyExec, - tensor_key: &GLWETensorKeyExec, + auto_key: &GGLWEAutomorphismKeyExec, + tensor_key: &GGLWETensorKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily + GGSWKeySwitchFamily + VecZnxAutomorphismInplace + VecZnxNormalizeTmpBytes, @@ -65,8 +69,6 @@ impl GGSWCiphertext { { #[cfg(debug_assertions)] { - use crate::Infos; - assert_eq!(self.n(), auto_key.n()); assert_eq!(lhs.n(), auto_key.n()); @@ -115,8 +117,8 @@ impl GGSWCiphertext { pub fn automorphism_inplace( &mut self, module: &Module, - auto_key: &AutomorphismKeyExec, - tensor_key: &GLWETensorKeyExec, + auto_key: &GGLWEAutomorphismKeyExec, + tensor_key: &GGLWETensorKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily + GGSWKeySwitchFamily + VecZnxAutomorphismInplace + VecZnxNormalizeTmpBytes, @@ -132,7 +134,7 @@ impl GGSWCiphertext { &mut self, module: &Module, lhs: &GGSWCiphertext, - auto_key: &AutomorphismKeyExec, + auto_key: &GGLWEAutomorphismKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily + GGSWKeySwitchFamily + VecZnxAutomorphismInplace + VecZnxNormalizeTmpBytes, diff --git a/core/src/glwe/automorphism.rs b/core/src/automorphism/glwe_ct.rs similarity index 88% rename from core/src/glwe/automorphism.rs rename to core/src/automorphism/glwe_ct.rs index ec4ae93..673a7a9 100644 --- a/core/src/glwe/automorphism.rs +++ b/core/src/automorphism/glwe_ct.rs @@ -6,7 +6,10 @@ use backend::hal::{ 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> { pub fn automorphism_scratch_space( @@ -46,7 +49,7 @@ impl GLWECiphertext { &mut self, module: &Module, lhs: &GLWECiphertext, - rhs: &AutomorphismKeyExec, + rhs: &GGLWEAutomorphismKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily + VecZnxAutomorphismInplace, @@ -61,7 +64,7 @@ impl GLWECiphertext { pub fn automorphism_inplace( &mut self, module: &Module, - rhs: &AutomorphismKeyExec, + rhs: &GGLWEAutomorphismKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily + VecZnxAutomorphismInplace, @@ -77,7 +80,7 @@ impl GLWECiphertext { &mut self, module: &Module, lhs: &GLWECiphertext, - rhs: &AutomorphismKeyExec, + rhs: &GGLWEAutomorphismKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily + VecZnxBigAutomorphismInplace, @@ -88,7 +91,7 @@ impl GLWECiphertext { 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 @@ impl GLWECiphertext { pub fn automorphism_add_inplace( &mut self, module: &Module, - rhs: &AutomorphismKeyExec, + rhs: &GGLWEAutomorphismKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily + VecZnxBigAutomorphismInplace, @@ -115,7 +118,7 @@ impl GLWECiphertext { &mut self, module: &Module, lhs: &GLWECiphertext, - rhs: &AutomorphismKeyExec, + rhs: &GGLWEAutomorphismKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily + VecZnxBigAutomorphismInplace + VecZnxBigSubSmallAInplace, @@ -126,7 +129,7 @@ impl GLWECiphertext { 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 @@ impl GLWECiphertext { pub fn automorphism_sub_ab_inplace( &mut self, module: &Module, - rhs: &AutomorphismKeyExec, + rhs: &GGLWEAutomorphismKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily + VecZnxBigAutomorphismInplace + VecZnxBigSubSmallAInplace, @@ -153,7 +156,7 @@ impl GLWECiphertext { &mut self, module: &Module, lhs: &GLWECiphertext, - rhs: &AutomorphismKeyExec, + rhs: &GGLWEAutomorphismKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily + VecZnxBigAutomorphismInplace + VecZnxBigSubSmallBInplace, @@ -164,7 +167,7 @@ impl GLWECiphertext { 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 @@ impl GLWECiphertext { pub fn automorphism_sub_ba_inplace( &mut self, module: &Module, - rhs: &AutomorphismKeyExec, + rhs: &GGLWEAutomorphismKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily + VecZnxBigAutomorphismInplace + VecZnxBigSubSmallBInplace, diff --git a/core/src/automorphism/mod.rs b/core/src/automorphism/mod.rs new file mode 100644 index 0000000..f985c5e --- /dev/null +++ b/core/src/automorphism/mod.rs @@ -0,0 +1,3 @@ +mod gglwe_atk; +mod ggsw_ct; +mod glwe_ct; diff --git a/core/src/conversion/glwe_to_lwe.rs b/core/src/conversion/glwe_to_lwe.rs new file mode 100644 index 0000000..e77c93f --- /dev/null +++ b/core/src/conversion/glwe_to_lwe.rs @@ -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> { + pub fn from_glwe_scratch_space( + module: &Module, + n: usize, + basek: usize, + k_lwe: usize, + k_glwe: usize, + k_ksk: usize, + rank: usize, + ) -> usize + where + Module: GLWEKeyswitchFamily, + { + 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 LWECiphertext { + pub fn sample_extract(&mut self, a: &GLWECiphertext) { + #[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( + &mut self, + module: &Module, + a: &GLWECiphertext, + ks: &GLWEToLWESwitchingKeyExec, + scratch: &mut Scratch, + ) where + DGlwe: DataRef, + DKs: DataRef, + Module: GLWEKeyswitchFamily, + Scratch: TakeVecZnxDft + 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); + } +} diff --git a/core/src/conversion/lwe_to_glwe.rs b/core/src/conversion/lwe_to_glwe.rs new file mode 100644 index 0000000..25aff96 --- /dev/null +++ b/core/src/conversion/lwe_to_glwe.rs @@ -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> { + pub fn from_lwe_scratch_space( + module: &Module, + n: usize, + basek: usize, + k_lwe: usize, + k_glwe: usize, + k_ksk: usize, + rank: usize, + ) -> usize + where + Module: GLWEKeyswitchFamily, + { + 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 GLWECiphertext { + pub fn from_lwe( + &mut self, + module: &Module, + lwe: &LWECiphertext, + ksk: &LWEToGLWESwitchingKeyExec, + scratch: &mut Scratch, + ) where + DLwe: DataRef, + DKsk: DataRef, + Module: GLWEKeyswitchFamily, + Scratch: TakeVecZnxDft + 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); + } +} diff --git a/core/src/conversion/mod.rs b/core/src/conversion/mod.rs new file mode 100644 index 0000000..090208b --- /dev/null +++ b/core/src/conversion/mod.rs @@ -0,0 +1,2 @@ +mod glwe_to_lwe; +mod lwe_to_glwe; diff --git a/core/src/glwe/decryption.rs b/core/src/decryption/glwe_ct.rs similarity index 81% rename from core/src/glwe/decryption.rs rename to core/src/decryption/glwe_ct.rs index 570a486..196c7d0 100644 --- a/core/src/glwe/decryption.rs +++ b/core/src/decryption/glwe_ct.rs @@ -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 = VecZnxDftAllocBytes - + VecZnxBigAllocBytes - + VecZnxDftFromVecZnx - + SvpApplyInplace - + VecZnxDftToVecZnxBigConsume - + VecZnxBigAddInplace - + VecZnxBigAddSmallInplace - + VecZnxBigNormalize - + VecZnxNormalizeTmpBytes; +use crate::{ + layouts::{GLWECiphertext, GLWEPlaintext, Infos, prepared::GLWESecretExec}, + trait_families::GLWEDecryptFamily, +}; impl GLWECiphertext> { pub fn decrypt_scratch_space(module: &Module, n: usize, basek: usize, k: usize) -> usize diff --git a/core/src/lwe/decryption.rs b/core/src/decryption/lwe_ct.rs similarity index 94% rename from core/src/lwe/decryption.rs rename to core/src/decryption/lwe_ct.rs index e27799b..663a1cb 100644 --- a/core/src/lwe/decryption.rs +++ b/core/src/decryption/lwe_ct.rs @@ -4,7 +4,7 @@ use backend::hal::{ oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl}, }; -use crate::{Infos, LWECiphertext, LWESecret, SetMetaData, lwe::LWEPlaintext}; +use crate::layouts::{Infos, LWECiphertext, LWEPlaintext, LWESecret, SetMetaData}; impl LWECiphertext where diff --git a/core/src/decryption/mod.rs b/core/src/decryption/mod.rs new file mode 100644 index 0000000..8165d78 --- /dev/null +++ b/core/src/decryption/mod.rs @@ -0,0 +1,2 @@ +mod glwe_ct; +mod lwe_ct; diff --git a/core/src/encryption/compressed/gglwe_atk.rs b/core/src/encryption/compressed/gglwe_atk.rs new file mode 100644 index 0000000..ff9b384 --- /dev/null +++ b/core/src/encryption/compressed/gglwe_atk.rs @@ -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> { + pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize, rank: usize) -> usize + where + Module: GGLWEAutomorphismKeyEncryptSkFamily + GLWESecretExecModuleFamily, + { + GGLWESwitchingKeyCompressed::encrypt_sk_scratch_space(module, n, basek, k, rank, rank) + GLWESecret::bytes_of(n, rank) + } +} + +impl GGLWEAutomorphismKeyCompressed { + pub fn encrypt_sk( + &mut self, + module: &Module, + p: i64, + sk: &GLWESecret, + seed_xa: [u8; 32], + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) where + Module: GGLWEAutomorphismKeyEncryptSkFamily + + VecZnxSwithcDegree + + VecZnxAutomorphism + + VecZnxAddScalarInplace + + GLWESecretExecModuleFamily, + Scratch: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft + TakeGLWESecretExec + 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; + } +} diff --git a/core/src/encryption/compressed/gglwe_ct.rs b/core/src/encryption/compressed/gglwe_ct.rs new file mode 100644 index 0000000..0c3e5b8 --- /dev/null +++ b/core/src/encryption/compressed/gglwe_ct.rs @@ -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> { + pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize) -> usize + where + Module: GGLWESwitchingKeyEncryptSkFamily, + { + GGLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) + } +} + +impl GGLWECiphertextCompressed { + pub fn encrypt_sk( + &mut self, + module: &Module, + pt: &ScalarZnx, + sk: &GLWESecretExec, + seed: [u8; 32], + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) where + Module: GGLWEEncryptSkFamily + VecZnxAddScalarInplace, + Scratch: TakeVecZnxDft + 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, + ); + }); + }); + } +} diff --git a/core/src/encryption/compressed/gglwe_ksk.rs b/core/src/encryption/compressed/gglwe_ksk.rs new file mode 100644 index 0000000..7a92770 --- /dev/null +++ b/core/src/encryption/compressed/gglwe_ksk.rs @@ -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> { + pub fn encrypt_sk_scratch_space( + module: &Module, + n: usize, + basek: usize, + k: usize, + rank_in: usize, + rank_out: usize, + ) -> usize + where + Module: GGLWESwitchingKeyEncryptSkFamily + GLWESecretExecModuleFamily, + { + (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 GGLWESwitchingKeyCompressed { + pub fn encrypt_sk( + &mut self, + module: &Module, + sk_in: &GLWESecret, + sk_out: &GLWESecret, + seed_xa: [u8; 32], + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) where + Module: + GGLWESwitchingKeyEncryptSkFamily + VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWESecretExecModuleFamily, + Scratch: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft + TakeGLWESecretExec + 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(); + } +} diff --git a/core/src/encryption/compressed/gglwe_tsk.rs b/core/src/encryption/compressed/gglwe_tsk.rs new file mode 100644 index 0000000..1a035e1 --- /dev/null +++ b/core/src/encryption/compressed/gglwe_tsk.rs @@ -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> { + pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize, rank: usize) -> usize + where + Module: GGLWETensorKeyEncryptSkFamily + GLWESecretExecModuleFamily, + { + GGLWETensorKey::encrypt_sk_scratch_space(module, n, basek, k, rank) + } +} + +impl GGLWETensorKeyCompressed { + pub fn encrypt_sk( + &mut self, + module: &Module, + sk: &GLWESecret, + seed_xa: [u8; 32], + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) where + Module: GGLWETensorKeyEncryptSkFamily + VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWESecretExecModuleFamily, + Scratch: ScratchAvailable + TakeVecZnxDft + TakeVecZnxBig + TakeGLWESecretExec + 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); + }); + }) + } +} diff --git a/core/src/ggsw/encryption.rs b/core/src/encryption/compressed/ggsw_ct.rs similarity index 51% rename from core/src/ggsw/encryption.rs rename to core/src/encryption/compressed/ggsw_ct.rs index c309c41..9a62765 100644 --- a/core/src/ggsw/encryption.rs +++ b/core/src/encryption/compressed/ggsw_ct.rs @@ -1,82 +1,16 @@ use backend::hal::{ api::{ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, VecZnxNormalizeInplace, ZnxZero}, - layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch, VecZnx}, + layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch}, }; use sampling::source::Source; use crate::{ - GGLWEEncryptSkFamily, GGSWCiphertext, GGSWCiphertextCompressed, GLWECiphertext, GLWEEncryptSkFamily, GLWESecretExec, Infos, - TakeGLWEPt, encrypt_sk_internal, + TakeGLWEPt, + encryption::glwe_encrypt_sk_internal, + layouts::{GGSWCiphertext, Infos, compressed::GGSWCiphertextCompressed, prepared::GLWESecretExec}, }; -pub trait GGSWEncryptSkFamily = GLWEEncryptSkFamily; - -impl GGSWCiphertext> { - pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize, rank: usize) -> usize - where - Module: GGSWEncryptSkFamily, - { - 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 GGSWCiphertext { - pub fn encrypt_sk( - &mut self, - module: &Module, - pt: &ScalarZnx, - sk: &GLWESecretExec, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) where - Module: GGSWEncryptSkFamily + VecZnxAddScalarInplace, - Scratch: TakeVecZnxDft + 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, - ); - }); - }); - } -} +use crate::trait_families::GGSWEncryptSkFamily; impl GGSWCiphertextCompressed> { pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize, rank: usize) -> usize @@ -136,7 +70,7 @@ impl GGSWCiphertextCompressed { self.seed[row_i * cols + col_j] = seed; - encrypt_sk_internal( + glwe_encrypt_sk_internal( module, self.basek(), self.k(), diff --git a/core/src/encryption/compressed/glwe_ct.rs b/core/src/encryption/compressed/glwe_ct.rs new file mode 100644 index 0000000..959f6dd --- /dev/null +++ b/core/src/encryption/compressed/glwe_ct.rs @@ -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> { + pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize) -> usize + where + Module: GLWEEncryptSkFamily, + { + GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) + } +} + +impl GLWECiphertextCompressed { + pub fn encrypt_sk( + &mut self, + module: &Module, + pt: &GLWEPlaintext, + sk: &GLWESecretExec, + seed_xa: [u8; 32], + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) where + Module: GLWEEncryptSkFamily, + Scratch: TakeVecZnxDft + ScratchAvailable + TakeVecZnx, + { + self.encrypt_sk_internal( + module, + Some((pt, 0)), + sk, + seed_xa, + source_xe, + sigma, + scratch, + ); + } + + pub(crate) fn encrypt_sk_internal( + &mut self, + module: &Module, + pt: Option<(&GLWEPlaintext, usize)>, + sk: &GLWESecretExec, + seed_xa: [u8; 32], + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) where + Module: GLWEEncryptSkFamily, + Scratch: TakeVecZnxDft + 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; + } +} diff --git a/core/src/encryption/compressed/mod.rs b/core/src/encryption/compressed/mod.rs new file mode 100644 index 0000000..e763db4 --- /dev/null +++ b/core/src/encryption/compressed/mod.rs @@ -0,0 +1,6 @@ +mod gglwe_atk; +mod gglwe_ct; +mod gglwe_ksk; +mod gglwe_tsk; +mod ggsw_ct; +mod glwe_ct; diff --git a/core/src/encryption/gglwe_atk.rs b/core/src/encryption/gglwe_atk.rs new file mode 100644 index 0000000..181289e --- /dev/null +++ b/core/src/encryption/gglwe_atk.rs @@ -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> { + pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize, rank: usize) -> usize + where + Module: GGLWEAutomorphismKeyEncryptSkFamily + GLWESecretExecModuleFamily, + { + GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank, rank) + GLWESecret::bytes_of(n, rank) + } + + pub fn encrypt_pk_scratch_space(module: &Module, _n: usize, _basek: usize, _k: usize, _rank: usize) -> usize { + GGLWESwitchingKey::encrypt_pk_scratch_space(module, _n, _basek, _k, _rank, _rank) + } +} + +impl GGLWEAutomorphismKey { + pub fn encrypt_sk( + &mut self, + module: &Module, + p: i64, + sk: &GLWESecret, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) where + Module: GGLWEAutomorphismKeyEncryptSkFamily + + VecZnxAutomorphism + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + GLWESecretExecModuleFamily, + Scratch: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft + TakeGLWESecretExec + 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; + } +} diff --git a/core/src/encryption/gglwe_ct.rs b/core/src/encryption/gglwe_ct.rs new file mode 100644 index 0000000..2a5da8c --- /dev/null +++ b/core/src/encryption/gglwe_ct.rs @@ -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> { + pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize) -> usize + where + Module: GGLWEEncryptSkFamily, + { + 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(_module: &Module, _n: usize, _basek: usize, _k: usize, _rank: usize) -> usize { + unimplemented!() + } +} + +impl GGLWECiphertext { + pub fn encrypt_sk( + &mut self, + module: &Module, + pt: &ScalarZnx, + sk: &GLWESecretExec, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) where + Module: GGLWEEncryptSkFamily + VecZnxAddScalarInplace, + Scratch: TakeVecZnxDft + 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); + }); + }); + } +} diff --git a/core/src/encryption/gglwe_ksk.rs b/core/src/encryption/gglwe_ksk.rs new file mode 100644 index 0000000..d18339f --- /dev/null +++ b/core/src/encryption/gglwe_ksk.rs @@ -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> { + pub fn encrypt_sk_scratch_space( + module: &Module, + n: usize, + basek: usize, + k: usize, + rank_in: usize, + rank_out: usize, + ) -> usize + where + Module: GGLWESwitchingKeyEncryptSkFamily + GLWESecretExecModuleFamily, + { + (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( + module: &Module, + _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 GGLWESwitchingKey { + pub fn encrypt_sk( + &mut self, + module: &Module, + sk_in: &GLWESecret, + sk_out: &GLWESecret, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) where + Module: + GGLWESwitchingKeyEncryptSkFamily + VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWESecretExecModuleFamily, + Scratch: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft + TakeGLWESecretExec + 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(); + } +} diff --git a/core/src/encryption/gglwe_tsk.rs b/core/src/encryption/gglwe_tsk.rs new file mode 100644 index 0000000..f1f462c --- /dev/null +++ b/core/src/encryption/gglwe_tsk.rs @@ -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> { + pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize, rank: usize) -> usize + where + Module: GGLWETensorKeyEncryptSkFamily + GLWESecretExecModuleFamily, + { + 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 GGLWETensorKey { + pub fn encrypt_sk( + &mut self, + module: &Module, + sk: &GLWESecret, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) where + Module: GGLWETensorKeyEncryptSkFamily + VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWESecretExecModuleFamily, + Scratch: ScratchAvailable + TakeVecZnxDft + TakeVecZnxBig + TakeGLWESecretExec + 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); + }); + }) + } +} diff --git a/core/src/encryption/ggsw_ct.rs b/core/src/encryption/ggsw_ct.rs new file mode 100644 index 0000000..463299e --- /dev/null +++ b/core/src/encryption/ggsw_ct.rs @@ -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 = GLWEEncryptSkFamily; + +impl GGSWCiphertext> { + pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize, rank: usize) -> usize + where + Module: GGSWEncryptSkFamily, + { + 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 GGSWCiphertext { + pub fn encrypt_sk( + &mut self, + module: &Module, + pt: &ScalarZnx, + sk: &GLWESecretExec, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) where + Module: GGSWEncryptSkFamily + VecZnxAddScalarInplace, + Scratch: TakeVecZnxDft + 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, + ); + }); + }); + } +} diff --git a/core/src/glwe/encryption.rs b/core/src/encryption/glwe_ct.rs similarity index 78% rename from core/src/glwe/encryption.rs rename to core/src/encryption/glwe_ct.rs index 0b5edbc..6b058ae 100644 --- a/core/src/glwe/encryption.rs +++ b/core/src/encryption/glwe_ct.rs @@ -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 = VecZnxDftAllocBytes - + VecZnxBigNormalize - + VecZnxDftFromVecZnx - + SvpApplyInplace - + VecZnxDftToVecZnxBigConsume - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubABInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace - + VecZnxAddNormal - + VecZnxNormalize - + VecZnxSub; - -pub trait GLWEEncryptPkFamily = VecZnxDftAllocBytes - + VecZnxBigAllocBytes - + SvpPPolAllocBytes - + SvpPrepare - + SvpApply - + VecZnxDftToVecZnxBigConsume - + VecZnxBigAddNormal - + VecZnxBigAddSmallInplace - + VecZnxBigNormalize - + VecZnxNormalizeTmpBytes; - impl GLWECiphertext> { pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize) -> usize where @@ -144,7 +123,7 @@ impl GLWECiphertext { Scratch: TakeVecZnxDft + 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 GLWECiphertext { } } -impl GLWECiphertextCompressed> { - pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize) -> usize - where - Module: GLWEEncryptSkFamily, - { - GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) - } -} -impl GLWECiphertextCompressed { - pub fn encrypt_sk( - &mut self, - module: &Module, - pt: &GLWEPlaintext, - sk: &GLWESecretExec, - seed_xa: [u8; 32], - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) where - Module: GLWEEncryptSkFamily, - Scratch: TakeVecZnxDft + ScratchAvailable + TakeVecZnx, - { - self.encrypt_sk_internal( - module, - Some((pt, 0)), - sk, - seed_xa, - source_xe, - sigma, - scratch, - ); - } - - pub(crate) fn encrypt_sk_internal( - &mut self, - module: &Module, - pt: Option<(&GLWEPlaintext, usize)>, - sk: &GLWESecretExec, - seed_xa: [u8; 32], - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) where - Module: GLWEEncryptSkFamily, - Scratch: TakeVecZnxDft + 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( +pub(crate) fn glwe_encrypt_sk_internal( module: &Module, basek: usize, k: usize, @@ -382,6 +295,8 @@ pub(crate) fn encrypt_sk_internal GLWEPublicKey { + pub fn generate_from_sk( + &mut self, + module: &Module, + sk: &GLWESecretExec, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + ) where + Module: GLWEEncryptSkFamily, + B: ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + TakeVecZnxDftImpl + + ScratchAvailableImpl + + TakeVecZnxImpl, + { + #[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 = ScratchOwned::alloc(GLWECiphertext::encrypt_sk_scratch_space( + module, + self.n(), + self.basek(), + self.k(), + )); + + let mut tmp: GLWECiphertext> = 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; + } +} diff --git a/core/src/encryption/glwe_to_lwe_ksk.rs b/core/src/encryption/glwe_to_lwe_ksk.rs new file mode 100644 index 0000000..b746fb6 --- /dev/null +++ b/core/src/encryption/glwe_to_lwe_ksk.rs @@ -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> { + pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize, rank_in: usize) -> usize + where + Module: GGLWEEncryptSkFamily + GLWESecretExecModuleFamily, + { + 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 GLWEToLWESwitchingKey { + pub fn encrypt_sk( + &mut self, + module: &Module, + sk_lwe: &LWESecret, + sk_glwe: &GLWESecret, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) where + DLwe: DataRef, + DGlwe: DataRef, + Module: GGLWESwitchingKeyEncryptSkFamily + + VecZnxAutomorphismInplace + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + GLWESecretExecModuleFamily, + Scratch: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft + TakeGLWESecretExec + 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, + ); + } +} diff --git a/core/src/encryption/lwe_ct.rs b/core/src/encryption/lwe_ct.rs new file mode 100644 index 0000000..ca13157 --- /dev/null +++ b/core/src/encryption/lwe_ct.rs @@ -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 LWECiphertext { + pub fn encrypt_sk( + &mut self, + module: &Module, + pt: &LWEPlaintext, + sk: &LWESecret, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + ) where + DataPt: DataRef, + DataSk: DataRef, + Module: VecZnxFillUniform + VecZnxAddNormal + VecZnxNormalizeInplace, + B: ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl, + { + #[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> = 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::(); + }); + + (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::(); + }); + + 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::()).borrow(), + ); + + (0..self.size()).for_each(|i| { + self.data.at_mut(0, i)[0] = tmp_znx.at(0, i)[0]; + }); + } +} diff --git a/core/src/encryption/lwe_ksk.rs b/core/src/encryption/lwe_ksk.rs new file mode 100644 index 0000000..d423f69 --- /dev/null +++ b/core/src/encryption/lwe_ksk.rs @@ -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> { + pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize) -> usize + where + Module: GGLWEEncryptSkFamily + GLWESecretExecModuleFamily, + { + GLWESecret::bytes_of(n, 1) + + GLWESecretExec::bytes_of(module, n, 1) + + GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, 1, 1) + } +} + +impl LWESwitchingKey { + pub fn encrypt_sk( + &mut self, + module: &Module, + sk_lwe_in: &LWESecret, + sk_lwe_out: &LWESecret, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) where + DIn: DataRef, + DOut: DataRef, + Module: GGLWESwitchingKeyEncryptSkFamily + + VecZnxAutomorphismInplace + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + GLWESecretExecModuleFamily, + Scratch: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft + TakeGLWESecretExec + 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, + ); + } +} diff --git a/core/src/encryption/lwe_to_glwe_ksk.rs b/core/src/encryption/lwe_to_glwe_ksk.rs new file mode 100644 index 0000000..73a261c --- /dev/null +++ b/core/src/encryption/lwe_to_glwe_ksk.rs @@ -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> { + pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize, rank_out: usize) -> usize + where + Module: GGLWEEncryptSkFamily + GLWESecretExecModuleFamily, + { + GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, 1, rank_out) + GLWESecret::bytes_of(n, 1) + } +} + +impl LWEToGLWESwitchingKey { + pub fn encrypt_sk( + &mut self, + module: &Module, + sk_lwe: &LWESecret, + sk_glwe: &GLWESecret, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) where + DLwe: DataRef, + DGlwe: DataRef, + Module: GGLWESwitchingKeyEncryptSkFamily + + VecZnxAutomorphismInplace + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + GLWESecretExecModuleFamily, + Scratch: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft + TakeGLWESecretExec + 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, + ); + } +} diff --git a/core/src/encryption/mod.rs b/core/src/encryption/mod.rs new file mode 100644 index 0000000..ce43f85 --- /dev/null +++ b/core/src/encryption/mod.rs @@ -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; diff --git a/core/src/external_product/gglwe_atk.rs b/core/src/external_product/gglwe_atk.rs new file mode 100644 index 0000000..e82dbfc --- /dev/null +++ b/core/src/external_product/gglwe_atk.rs @@ -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> { + pub fn external_product_scratch_space( + module: &Module, + n: usize, + basek: usize, + k_out: usize, + k_in: usize, + ggsw_k: usize, + digits: usize, + rank: usize, + ) -> usize + where + Module: GLWEExternalProductFamily, + { + GGLWESwitchingKey::external_product_scratch_space(module, n, basek, k_out, k_in, ggsw_k, digits, rank) + } + + pub fn external_product_inplace_scratch_space( + module: &Module, + n: usize, + basek: usize, + k_out: usize, + ggsw_k: usize, + digits: usize, + rank: usize, + ) -> usize + where + Module: GLWEExternalProductFamily, + { + GGLWESwitchingKey::external_product_inplace_scratch_space(module, n, basek, k_out, ggsw_k, digits, rank) + } +} + +impl GGLWEAutomorphismKey { + pub fn external_product( + &mut self, + module: &Module, + lhs: &GGLWEAutomorphismKey, + rhs: &GGSWCiphertextExec, + scratch: &mut Scratch, + ) where + Module: GLWEExternalProductFamily, + Scratch: TakeVecZnxDft + ScratchAvailable, + { + self.key.external_product(module, &lhs.key, rhs, scratch); + } + + pub fn external_product_inplace( + &mut self, + module: &Module, + rhs: &GGSWCiphertextExec, + scratch: &mut Scratch, + ) where + Module: GLWEExternalProductFamily, + Scratch: TakeVecZnxDft + ScratchAvailable, + { + self.key.external_product_inplace(module, rhs, scratch); + } +} diff --git a/core/src/gglwe/external_product.rs b/core/src/external_product/gglwe_ksk.rs similarity index 62% rename from core/src/gglwe/external_product.rs rename to core/src/external_product/gglwe_ksk.rs index 4b47789..4bd34f4 100644 --- a/core/src/gglwe/external_product.rs +++ b/core/src/external_product/gglwe_ksk.rs @@ -3,9 +3,12 @@ use backend::hal::{ 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> { +impl GGLWESwitchingKey> { pub fn external_product_scratch_space( module: &Module, n: usize, @@ -38,11 +41,11 @@ impl GLWESwitchingKey> { } } -impl GLWESwitchingKey { +impl GGLWESwitchingKey { pub fn external_product( &mut self, module: &Module, - lhs: &GLWESwitchingKey, + lhs: &GGLWESwitchingKey, rhs: &GGSWCiphertextExec, scratch: &mut Scratch, ) where @@ -116,63 +119,3 @@ impl GLWESwitchingKey { }); } } - -impl AutomorphismKey> { - pub fn external_product_scratch_space( - module: &Module, - n: usize, - basek: usize, - k_out: usize, - k_in: usize, - ggsw_k: usize, - digits: usize, - rank: usize, - ) -> usize - where - Module: GLWEExternalProductFamily, - { - GLWESwitchingKey::external_product_scratch_space(module, n, basek, k_out, k_in, ggsw_k, digits, rank) - } - - pub fn external_product_inplace_scratch_space( - module: &Module, - n: usize, - basek: usize, - k_out: usize, - ggsw_k: usize, - digits: usize, - rank: usize, - ) -> usize - where - Module: GLWEExternalProductFamily, - { - GLWESwitchingKey::external_product_inplace_scratch_space(module, n, basek, k_out, ggsw_k, digits, rank) - } -} - -impl AutomorphismKey { - pub fn external_product( - &mut self, - module: &Module, - lhs: &AutomorphismKey, - rhs: &GGSWCiphertextExec, - scratch: &mut Scratch, - ) where - Module: GLWEExternalProductFamily, - Scratch: TakeVecZnxDft + ScratchAvailable, - { - self.key.external_product(module, &lhs.key, rhs, scratch); - } - - pub fn external_product_inplace( - &mut self, - module: &Module, - rhs: &GGSWCiphertextExec, - scratch: &mut Scratch, - ) where - Module: GLWEExternalProductFamily, - Scratch: TakeVecZnxDft + ScratchAvailable, - { - self.key.external_product_inplace(module, rhs, scratch); - } -} diff --git a/core/src/ggsw/external_product.rs b/core/src/external_product/ggsw_ct.rs similarity index 95% rename from core/src/ggsw/external_product.rs rename to core/src/external_product/ggsw_ct.rs index 26d2bab..5074fc8 100644 --- a/core/src/ggsw/external_product.rs +++ b/core/src/external_product/ggsw_ct.rs @@ -3,7 +3,10 @@ use backend::hal::{ 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> { pub fn external_product_scratch_space( @@ -51,7 +54,7 @@ impl GGSWCiphertext { { #[cfg(debug_assertions)] { - use crate::{GGSWCiphertext, Infos}; + use crate::layouts::Infos; assert_eq!(lhs.n(), self.n()); assert_eq!(rhs.n(), self.n()); diff --git a/core/src/glwe/external_product.rs b/core/src/external_product/glwe_ct.rs similarity index 94% rename from core/src/glwe/external_product.rs rename to core/src/external_product/glwe_ct.rs index 91fb70c..b114f1e 100644 --- a/core/src/glwe/external_product.rs +++ b/core/src/external_product/glwe_ct.rs @@ -6,16 +6,10 @@ use backend::hal::{ layouts::{Backend, DataMut, DataRef, Module, Scratch, VecZnxBig}, }; -use crate::{GGSWCiphertextExec, GLWECiphertext, Infos}; - -pub trait GLWEExternalProductFamily = VecZnxDftAllocBytes - + VmpApplyTmpBytes - + VmpApply - + VmpApplyAdd - + VecZnxDftFromVecZnx - + VecZnxDftToVecZnxBigConsume - + VecZnxBigNormalize - + VecZnxNormalizeTmpBytes; +use crate::{ + layouts::{GLWECiphertext, Infos, prepared::GGSWCiphertextExec}, + trait_families::GLWEExternalProductFamily, +}; impl GLWECiphertext> { pub fn external_product_scratch_space( diff --git a/core/src/external_product/mod.rs b/core/src/external_product/mod.rs new file mode 100644 index 0000000..0779074 --- /dev/null +++ b/core/src/external_product/mod.rs @@ -0,0 +1,4 @@ +mod gglwe_atk; +mod gglwe_ksk; +mod ggsw_ct; +mod glwe_ct; diff --git a/core/src/gglwe/encryption.rs b/core/src/gglwe/encryption.rs deleted file mode 100644 index f4cc8de..0000000 --- a/core/src/gglwe/encryption.rs +++ /dev/null @@ -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 = GLWEEncryptSkFamily + GLWESecretFamily; - -impl GGLWECiphertext> { - pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize) -> usize - where - Module: GGLWEEncryptSkFamily, - { - 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(_module: &Module, _n: usize, _basek: usize, _k: usize, _rank: usize) -> usize { - unimplemented!() - } -} - -impl GGLWECiphertext { - pub fn encrypt_sk( - &mut self, - module: &Module, - pt: &ScalarZnx, - sk: &GLWESecretExec, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) where - Module: GGLWEEncryptSkFamily + VecZnxAddScalarInplace, - Scratch: TakeVecZnxDft + 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> { - pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize) -> usize - where - Module: GLWESwitchingKeyEncryptSkFamily, - { - GGLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) - } -} - -impl GGLWECiphertextCompressed { - pub fn encrypt_sk( - &mut self, - module: &Module, - pt: &ScalarZnx, - sk: &GLWESecretExec, - seed: [u8; 32], - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) where - Module: GGLWEEncryptSkFamily + VecZnxAddScalarInplace, - Scratch: TakeVecZnxDft + 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 = GGLWEEncryptSkFamily; - -impl GLWESwitchingKey> { - pub fn encrypt_sk_scratch_space( - module: &Module, - n: usize, - basek: usize, - k: usize, - rank_in: usize, - rank_out: usize, - ) -> usize - where - Module: GLWESwitchingKeyEncryptSkFamily, - { - (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( - module: &Module, - _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 GLWESwitchingKey { - pub fn encrypt_sk( - &mut self, - module: &Module, - sk_in: &GLWESecret, - sk_out: &GLWESecret, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) where - Module: GLWESwitchingKeyEncryptSkFamily + VecZnxSwithcDegree + VecZnxAddScalarInplace, - Scratch: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft + TakeGLWESecretExec + 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> { - pub fn encrypt_sk_scratch_space( - module: &Module, - n: usize, - basek: usize, - k: usize, - rank_in: usize, - rank_out: usize, - ) -> usize - where - Module: GLWESwitchingKeyEncryptSkFamily, - { - (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 GLWESwitchingKeyCompressed { - pub fn encrypt_sk( - &mut self, - module: &Module, - sk_in: &GLWESecret, - sk_out: &GLWESecret, - seed_xa: [u8; 32], - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) where - Module: GLWESwitchingKeyEncryptSkFamily + VecZnxSwithcDegree + VecZnxAddScalarInplace, - Scratch: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft + TakeGLWESecretExec + 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 = GGLWEEncryptSkFamily; - -impl AutomorphismKey> { - pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize, rank: usize) -> usize - where - Module: AutomorphismKeyEncryptSkFamily, - { - GLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank, rank) + GLWESecret::bytes_of(n, rank) - } - - pub fn encrypt_pk_scratch_space(module: &Module, _n: usize, _basek: usize, _k: usize, _rank: usize) -> usize { - GLWESwitchingKey::encrypt_pk_scratch_space(module, _n, _basek, _k, _rank, _rank) - } -} - -impl AutomorphismKey { - pub fn encrypt_sk( - &mut self, - module: &Module, - p: i64, - sk: &GLWESecret, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) where - Module: AutomorphismKeyEncryptSkFamily + VecZnxAutomorphism + VecZnxSwithcDegree + VecZnxAddScalarInplace, - Scratch: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft + TakeGLWESecretExec + 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> { - pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize, rank: usize) -> usize - where - Module: AutomorphismKeyEncryptSkFamily, - { - GLWESwitchingKeyCompressed::encrypt_sk_scratch_space(module, n, basek, k, rank, rank) + GLWESecret::bytes_of(n, rank) - } -} - -impl AutomorphismKeyCompressed { - pub fn encrypt_sk( - &mut self, - module: &Module, - p: i64, - sk: &GLWESecret, - seed_xa: [u8; 32], - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) where - Module: AutomorphismKeyEncryptSkFamily + VecZnxSwithcDegree + VecZnxAutomorphism + VecZnxAddScalarInplace, - Scratch: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft + TakeGLWESecretExec + 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 = - GGLWEEncryptSkFamily + VecZnxBigAllocBytes + VecZnxDftToVecZnxBigTmpA + SvpApply; - -impl GLWETensorKey> { - pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize, rank: usize) -> usize - where - Module: GLWETensorKeyEncryptSkFamily, - { - 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 GLWETensorKey { - pub fn encrypt_sk( - &mut self, - module: &Module, - sk: &GLWESecret, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) where - Module: GLWETensorKeyEncryptSkFamily + VecZnxSwithcDegree + VecZnxAddScalarInplace, - Scratch: ScratchAvailable + TakeVecZnxDft + TakeVecZnxBig + TakeGLWESecretExec + 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> { - pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize, rank: usize) -> usize - where - Module: GLWETensorKeyEncryptSkFamily, - { - GLWETensorKey::encrypt_sk_scratch_space(module, n, basek, k, rank) - } -} - -impl GLWETensorKeyCompressed { - pub fn encrypt_sk( - &mut self, - module: &Module, - sk: &GLWESecret, - seed_xa: [u8; 32], - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) where - Module: GLWETensorKeyEncryptSkFamily + VecZnxSwithcDegree + VecZnxAddScalarInplace, - Scratch: ScratchAvailable + TakeVecZnxDft + TakeVecZnxBig + TakeGLWESecretExec + 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); - }); - }) - } -} diff --git a/core/src/gglwe/layout.rs b/core/src/gglwe/layout.rs deleted file mode 100644 index 99f78ee..0000000 --- a/core/src/gglwe/layout.rs +++ /dev/null @@ -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 = VmpPMatAlloc + VmpPMatAllocBytes + VmpPMatPrepare; -use std::fmt; - -#[derive(PartialEq, Eq, Clone)] -pub struct GGLWECiphertext { - pub(crate) data: MatZnx, - pub(crate) basek: usize, - pub(crate) k: usize, - pub(crate) digits: usize, -} - -impl fmt::Debug for GGLWECiphertext { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl FillUniform for GGLWECiphertext { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.data.fill_uniform(source); - } -} - -impl Reset for GGLWECiphertext { - fn reset(&mut self) { - self.data.reset(); - self.basek = 0; - self.k = 0; - self.digits = 0; - } -} - -impl fmt::Display for GGLWECiphertext { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "(GGLWECiphertext: basek={} k={} digits={}) {}", - self.basek, self.k, self.digits, self.data - ) - } -} - -impl GGLWECiphertext { - pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> { - GLWECiphertext { - data: self.data.at(row, col), - basek: self.basek, - k: self.k, - } - } -} - -impl GGLWECiphertext { - 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> { - 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 Infos for GGLWECiphertext { - type Inner = MatZnx; - - fn inner(&self) -> &Self::Inner { - &self.data - } - - fn basek(&self) -> usize { - self.basek - } - - fn k(&self) -> usize { - self.k - } -} - -impl GGLWECiphertext { - 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 ReaderFrom for GGLWECiphertext { - fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { - self.k = reader.read_u64::()? as usize; - self.basek = reader.read_u64::()? as usize; - self.digits = reader.read_u64::()? as usize; - self.data.read_from(reader) - } -} - -impl WriterTo for GGLWECiphertext { - fn write_to(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::(self.k as u64)?; - writer.write_u64::(self.basek as u64)?; - writer.write_u64::(self.digits as u64)?; - self.data.write_to(writer) - } -} - -#[derive(PartialEq, Eq, Clone)] -pub struct GLWESwitchingKey { - pub(crate) key: GGLWECiphertext, - pub(crate) sk_in_n: usize, // Degree of sk_in - pub(crate) sk_out_n: usize, // Degree of sk_out -} - -impl fmt::Debug for GLWESwitchingKey { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl fmt::Display for GLWESwitchingKey { - 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 FillUniform for GLWESwitchingKey { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.key.fill_uniform(source); - } -} - -impl Reset for GLWESwitchingKey -where - MatZnx: Reset, -{ - fn reset(&mut self) { - self.key.reset(); - self.sk_in_n = 0; - self.sk_out_n = 0; - } -} - -impl GLWESwitchingKey> { - 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::>::bytes_of(n, basek, k, rows, digits, rank_in, rank_out) - } -} - -impl Infos for GLWESwitchingKey { - type Inner = MatZnx; - - fn inner(&self) -> &Self::Inner { - self.key.inner() - } - - fn basek(&self) -> usize { - self.key.basek() - } - - fn k(&self) -> usize { - self.key.k() - } -} - -impl GLWESwitchingKey { - 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 GLWESwitchingKey { - pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> { - self.key.at(row, col) - } -} - -impl GLWESwitchingKey { - pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> { - self.key.at_mut(row, col) - } -} - -impl ReaderFrom for GLWESwitchingKey { - fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { - self.sk_in_n = reader.read_u64::()? as usize; - self.sk_out_n = reader.read_u64::()? as usize; - self.key.read_from(reader) - } -} - -impl WriterTo for GLWESwitchingKey { - fn write_to(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::(self.sk_in_n as u64)?; - writer.write_u64::(self.sk_out_n as u64)?; - self.key.write_to(writer) - } -} - -#[derive(PartialEq, Eq, Clone)] -pub struct AutomorphismKey { - pub(crate) key: GLWESwitchingKey, - pub(crate) p: i64, -} - -impl fmt::Debug for AutomorphismKey { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl FillUniform for AutomorphismKey { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.key.fill_uniform(source); - } -} - -impl Reset for AutomorphismKey -where - MatZnx: Reset, -{ - fn reset(&mut self) { - self.key.reset(); - self.p = 0; - } -} - -impl fmt::Display for AutomorphismKey { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "(AutomorphismKey: p={}) {}", self.p, self.key) - } -} - -impl AutomorphismKey> { - 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 Infos for AutomorphismKey { - type Inner = MatZnx; - - fn inner(&self) -> &Self::Inner { - &self.key.inner() - } - - fn basek(&self) -> usize { - self.key.basek() - } - - fn k(&self) -> usize { - self.key.k() - } -} - -impl AutomorphismKey { - 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 AutomorphismKey { - pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> { - self.key.at(row, col) - } -} - -impl AutomorphismKey { - pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> { - self.key.at_mut(row, col) - } -} - -impl ReaderFrom for AutomorphismKey { - fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { - self.p = reader.read_u64::()? as i64; - self.key.read_from(reader) - } -} - -impl WriterTo for AutomorphismKey { - fn write_to(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::(self.p as u64)?; - self.key.write_to(writer) - } -} - -#[derive(PartialEq, Eq, Clone)] -pub struct GLWETensorKey { - pub(crate) keys: Vec>, -} - -impl fmt::Debug for GLWETensorKey { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl FillUniform for GLWETensorKey { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.keys - .iter_mut() - .for_each(|key: &mut GLWESwitchingKey| key.fill_uniform(source)) - } -} - -impl Reset for GLWETensorKey -where - MatZnx: Reset, -{ - fn reset(&mut self) { - self.keys - .iter_mut() - .for_each(|key: &mut GLWESwitchingKey| key.reset()) - } -} - -impl fmt::Display for GLWETensorKey { - 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> { - pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self { - let mut keys: Vec>> = 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::>::bytes_of(n, basek, k, rows, digits, 1, rank) - } -} - -impl Infos for GLWETensorKey { - type Inner = MatZnx; - - 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 GLWETensorKey { - 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 GLWETensorKey { - // 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 { - 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 GLWETensorKey { - // Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j]) - pub fn at(&self, mut i: usize, mut j: usize) -> &GLWESwitchingKey { - 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 ReaderFrom for GLWETensorKey { - fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { - let len: usize = reader.read_u64::()? 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 WriterTo for GLWETensorKey { - fn write_to(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::(self.keys.len() as u64)?; - for key in &self.keys { - key.write_to(writer)?; - } - Ok(()) - } -} diff --git a/core/src/gglwe/layouts_compressed.rs b/core/src/gglwe/layouts_compressed.rs deleted file mode 100644 index 8b85629..0000000 --- a/core/src/gglwe/layouts_compressed.rs +++ /dev/null @@ -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 { - pub(crate) data: MatZnx, - pub(crate) basek: usize, - pub(crate) k: usize, - pub(crate) rank_out: usize, - pub(crate) digits: usize, - pub(crate) seed: Vec<[u8; 32]>, -} - -impl fmt::Debug for GGLWECiphertextCompressed { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl FillUniform for GGLWECiphertextCompressed { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.data.fill_uniform(source); - } -} - -impl Reset for GGLWECiphertextCompressed -where - MatZnx: 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 fmt::Display for GGLWECiphertextCompressed { - 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> { - 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 Infos for GGLWECiphertextCompressed { - type Inner = MatZnx; - - fn inner(&self) -> &Self::Inner { - &self.data - } - - fn basek(&self) -> usize { - self.basek - } - - fn k(&self) -> usize { - self.k - } -} - -impl GGLWECiphertextCompressed { - 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 GGLWECiphertextCompressed { - 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 GGLWECiphertextCompressed { - 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 ReaderFrom for GGLWECiphertextCompressed { - fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { - self.k = reader.read_u64::()? as usize; - self.basek = reader.read_u64::()? as usize; - self.digits = reader.read_u64::()? as usize; - self.rank_out = reader.read_u64::()? as usize; - let seed_len = reader.read_u64::()? 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 WriterTo for GGLWECiphertextCompressed { - fn write_to(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::(self.k as u64)?; - writer.write_u64::(self.basek as u64)?; - writer.write_u64::(self.digits as u64)?; - writer.write_u64::(self.rank_out as u64)?; - writer.write_u64::(self.seed.len() as u64)?; - for s in &self.seed { - writer.write_all(s)?; - } - self.data.write_to(writer) - } -} - -impl Decompress> for GGLWECiphertext { - fn decompress(&mut self, module: &Module, other: &GGLWECiphertextCompressed) - where - Module: 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 { - pub(crate) key: GGLWECiphertextCompressed, - pub(crate) sk_in_n: usize, // Degree of sk_in - pub(crate) sk_out_n: usize, // Degree of sk_out -} - -impl fmt::Debug for GLWESwitchingKeyCompressed { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl FillUniform for GLWESwitchingKeyCompressed { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.key.fill_uniform(source); - } -} - -impl Reset for GLWESwitchingKeyCompressed -where - MatZnx: Reset, -{ - fn reset(&mut self) { - self.key.reset(); - self.sk_in_n = 0; - self.sk_out_n = 0; - } -} - -impl fmt::Display for GLWESwitchingKeyCompressed { - 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 Infos for GLWESwitchingKeyCompressed { - type Inner = MatZnx; - - fn inner(&self) -> &Self::Inner { - &self.key.inner() - } - - fn basek(&self) -> usize { - self.key.basek() - } - - fn k(&self) -> usize { - self.key.k() - } -} - -impl GLWESwitchingKeyCompressed { - 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> { - 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 ReaderFrom for GLWESwitchingKeyCompressed { - fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { - self.sk_in_n = reader.read_u64::()? as usize; - self.sk_out_n = reader.read_u64::()? as usize; - self.key.read_from(reader) - } -} - -impl WriterTo for GLWESwitchingKeyCompressed { - fn write_to(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::(self.sk_in_n as u64)?; - writer.write_u64::(self.sk_out_n as u64)?; - self.key.write_to(writer) - } -} - -impl GLWESwitchingKey { - pub fn decompress( - &mut self, - module: &Module, - other: &GLWESwitchingKeyCompressed, - ) where - Module: 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 { - pub(crate) key: GLWESwitchingKeyCompressed, - pub(crate) p: i64, -} - -impl fmt::Debug for AutomorphismKeyCompressed { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl FillUniform for AutomorphismKeyCompressed { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.key.fill_uniform(source); - } -} - -impl Reset for AutomorphismKeyCompressed -where - MatZnx: Reset, -{ - fn reset(&mut self) { - self.key.reset(); - self.p = 0; - } -} - -impl fmt::Display for AutomorphismKeyCompressed { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "(AutomorphismKeyCompressed: p={}) {}", self.p, self.key) - } -} - -impl AutomorphismKeyCompressed> { - 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::>::bytes_of(n, basek, k, rows, digits, rank) - } -} - -impl Infos for AutomorphismKeyCompressed { - type Inner = MatZnx; - - fn inner(&self) -> &Self::Inner { - &self.key.inner() - } - - fn basek(&self) -> usize { - self.key.basek() - } - - fn k(&self) -> usize { - self.key.k() - } -} - -impl AutomorphismKeyCompressed { - 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 ReaderFrom for AutomorphismKeyCompressed { - fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { - self.p = reader.read_u64::()? as i64; - self.key.read_from(reader) - } -} - -impl WriterTo for AutomorphismKeyCompressed { - fn write_to(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::(self.p as u64)?; - self.key.write_to(writer) - } -} - -impl AutomorphismKey { - pub fn decompress(&mut self, module: &Module, other: &AutomorphismKeyCompressed) - where - Module: VecZnxFillUniform + VecZnxCopy, - { - self.key.decompress(module, &other.key); - self.p = other.p; - } -} - -#[derive(PartialEq, Eq, Clone)] -pub struct GLWETensorKeyCompressed { - pub(crate) keys: Vec>, -} - -impl fmt::Debug for GLWETensorKeyCompressed { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl FillUniform for GLWETensorKeyCompressed { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.keys - .iter_mut() - .for_each(|key: &mut GLWESwitchingKeyCompressed| key.fill_uniform(source)) - } -} - -impl Reset for GLWETensorKeyCompressed -where - MatZnx: Reset, -{ - fn reset(&mut self) { - self.keys - .iter_mut() - .for_each(|key: &mut GLWESwitchingKeyCompressed| key.reset()) - } -} - -impl fmt::Display for GLWETensorKeyCompressed { - 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> { - pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self { - let mut keys: Vec>> = 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 Infos for GLWETensorKeyCompressed { - type Inner = MatZnx; - - 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 GLWETensorKeyCompressed { - 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 ReaderFrom for GLWETensorKeyCompressed { - fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { - let len: usize = reader.read_u64::()? 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 WriterTo for GLWETensorKeyCompressed { - fn write_to(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::(self.keys.len() as u64)?; - for key in &self.keys { - key.write_to(writer)?; - } - Ok(()) - } -} - -impl GLWETensorKeyCompressed { - pub(crate) fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GLWESwitchingKeyCompressed { - 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 GLWETensorKey { - pub fn decompress(&mut self, module: &Module, other: &GLWETensorKeyCompressed) - where - Module: 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); - }); - } -} diff --git a/core/src/gglwe/layouts_exec.rs b/core/src/gglwe/layouts_exec.rs deleted file mode 100644 index 52bbbee..0000000 --- a/core/src/gglwe/layouts_exec.rs +++ /dev/null @@ -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 { - pub(crate) data: VmpPMat, - pub(crate) basek: usize, - pub(crate) k: usize, - pub(crate) digits: usize, -} - -impl GGLWECiphertextExec, B> { - pub fn alloc( - module: &Module, - n: usize, - basek: usize, - k: usize, - rows: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - ) -> Self - where - Module: GGLWEExecLayoutFamily, - { - 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, - n: usize, - basek: usize, - k: usize, - rows: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - ) -> usize - where - Module: GGLWEExecLayoutFamily, - { - 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 Infos for GGLWECiphertextExec { - type Inner = VmpPMat; - - fn inner(&self) -> &Self::Inner { - &self.data - } - - fn basek(&self) -> usize { - self.basek - } - - fn k(&self) -> usize { - self.k - } -} - -impl GGLWECiphertextExec { - 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 GGLWECiphertextExec { - pub fn prepare(&mut self, module: &Module, other: &GGLWECiphertext, scratch: &mut Scratch) - where - DataOther: DataRef, - Module: GGLWEExecLayoutFamily, - { - 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 { - pub(crate) key: GGLWECiphertextExec, - pub(crate) sk_in_n: usize, // Degree of sk_in - pub(crate) sk_out_n: usize, // Degree of sk_out -} - -impl GLWESwitchingKeyExec, B> { - pub fn alloc( - module: &Module, - n: usize, - basek: usize, - k: usize, - rows: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - ) -> Self - where - Module: GGLWEExecLayoutFamily, - { - GLWESwitchingKeyExec::, 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, - n: usize, - basek: usize, - k: usize, - rows: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - ) -> usize - where - Module: GGLWEExecLayoutFamily, - { - GGLWECiphertextExec::bytes_of(module, n, basek, k, rows, digits, rank_in, rank_out) - } - - pub fn from(module: &Module, other: &GLWESwitchingKey, scratch: &mut Scratch) -> Self - where - Module: GGLWEExecLayoutFamily, - { - let mut ksk_exec: GLWESwitchingKeyExec, 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 Infos for GLWESwitchingKeyExec { - type Inner = VmpPMat; - - fn inner(&self) -> &Self::Inner { - self.key.inner() - } - - fn basek(&self) -> usize { - self.key.basek() - } - - fn k(&self) -> usize { - self.key.k() - } -} - -impl GLWESwitchingKeyExec { - 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 GLWESwitchingKeyExec { - pub fn prepare(&mut self, module: &Module, other: &GLWESwitchingKey, scratch: &mut Scratch) - where - DataOther: DataRef, - Module: GGLWEExecLayoutFamily, - { - 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 { - pub(crate) key: GLWESwitchingKeyExec, - pub(crate) p: i64, -} - -impl AutomorphismKeyExec, B> { - pub fn alloc(module: &Module, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self - where - Module: GGLWEExecLayoutFamily, - { - AutomorphismKeyExec::, B> { - key: GLWESwitchingKeyExec::alloc(module, n, basek, k, rows, digits, rank, rank), - p: 0, - } - } - - pub fn bytes_of(module: &Module, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize - where - Module: GGLWEExecLayoutFamily, - { - GLWESwitchingKeyExec::bytes_of(module, n, basek, k, rows, digits, rank, rank) - } - - pub fn from(module: &Module, other: &AutomorphismKey, scratch: &mut Scratch) -> Self - where - Module: GGLWEExecLayoutFamily, - { - let mut atk_exec: AutomorphismKeyExec, 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 AutomorphismKeyExec { - pub fn prepare(&mut self, module: &Module, other: &AutomorphismKey, scratch: &mut Scratch) - where - DataOther: DataRef, - Module: GGLWEExecLayoutFamily, - { - self.key.prepare(module, &other.key, scratch); - self.p = other.p; - } -} - -impl Infos for AutomorphismKeyExec { - type Inner = VmpPMat; - - fn inner(&self) -> &Self::Inner { - &self.key.inner() - } - - fn basek(&self) -> usize { - self.key.basek() - } - - fn k(&self) -> usize { - self.key.k() - } -} - -impl AutomorphismKeyExec { - 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 { - pub(crate) keys: Vec>, -} - -impl GLWETensorKeyExec, B> { - pub fn alloc(module: &Module, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self - where - Module: GGLWEExecLayoutFamily, - { - let mut keys: Vec, 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, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize - where - Module: GGLWEExecLayoutFamily, - { - let pairs: usize = (((rank + 1) * rank) >> 1).max(1); - pairs * GLWESwitchingKeyExec::bytes_of(module, n, basek, k, rows, digits, 1, rank) - } - - pub fn from( - module: &Module, - other: &GLWETensorKey, - scratch: &mut Scratch, - ) -> GLWETensorKeyExec, B> - where - Module: GGLWEExecLayoutFamily, - { - let mut tsk_exec: GLWETensorKeyExec, 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 Infos for GLWETensorKeyExec { - type Inner = VmpPMat; - - 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 GLWETensorKeyExec { - 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 GLWETensorKeyExec { - // 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 { - 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 GLWETensorKeyExec { - // Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j]) - pub fn at(&self, mut i: usize, mut j: usize) -> &GLWESwitchingKeyExec { - 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 GLWETensorKeyExec { - pub fn prepare(&mut self, module: &Module, other: &GLWETensorKey, scratch: &mut Scratch) - where - DataOther: DataRef, - Module: GGLWEExecLayoutFamily, - { - #[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); - }); - } -} diff --git a/core/src/gglwe/mod.rs b/core/src/gglwe/mod.rs deleted file mode 100644 index 0d9dc48..0000000 --- a/core/src/gglwe/mod.rs +++ /dev/null @@ -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; diff --git a/core/src/gglwe/tests/generic_serialization.rs b/core/src/gglwe/tests/generic_serialization.rs deleted file mode 100644 index 903c396..0000000 --- a/core/src/gglwe/tests/generic_serialization.rs +++ /dev/null @@ -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> = GGLWECiphertext::alloc(1024, 12, 54, 3, 1, 2, 2); - test_reader_writer_interface(original); -} - -#[test] -fn test_gglwe_compressed_serialization() { - let original: GGLWECiphertextCompressed> = GGLWECiphertextCompressed::alloc(1024, 12, 54, 3, 1, 2, 2); - test_reader_writer_interface(original); -} - -#[test] -fn test_glwe_switching_key_serialization() { - let original: GLWESwitchingKey> = 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> = GLWESwitchingKeyCompressed::alloc(1024, 12, 54, 3, 1, 2, 2); - test_reader_writer_interface(original); -} - -#[test] -fn test_automorphism_key_serialization() { - let original: AutomorphismKey> = AutomorphismKey::alloc(1024, 12, 54, 3, 1, 2); - test_reader_writer_interface(original); -} - -#[test] -fn test_automorphism_key_compressed_serialization() { - let original: AutomorphismKeyCompressed> = AutomorphismKeyCompressed::alloc(1024, 12, 54, 3, 1, 2); - test_reader_writer_interface(original); -} - -#[test] -fn test_tensor_key_serialization() { - let original: GLWETensorKey> = GLWETensorKey::alloc(1024, 12, 54, 3, 1, 2); - test_reader_writer_interface(original); -} - -#[test] -fn test_tensor_key_compressed_serialization() { - let original: GLWETensorKeyCompressed> = GLWETensorKeyCompressed::alloc(1024, 12, 54, 3, 1, 2); - test_reader_writer_interface(original); -} diff --git a/core/src/gglwe/tests/generics_gglwe.rs b/core/src/gglwe/tests/generics_gglwe.rs deleted file mode 100644 index ef909e7..0000000 --- a/core/src/gglwe/tests/generics_gglwe.rs +++ /dev/null @@ -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 = GGLWEEncryptSkFamily - + GLWEDecryptFamily - + VecZnxSwithcDegree - + VecZnxAddScalarInplace - + VecZnxStd - + VecZnxSubScalarInplace - + VecZnxCopy; - -pub(crate) trait TestScratchFamily = TakeVecZnxDftImpl - + TakeVecZnxBigImpl - + TakeSvpPPolImpl - + ScratchOwnedAllocImpl - + ScratchOwnedBorrowImpl - + ScratchAvailableImpl - + TakeScalarZnxImpl - + TakeVecZnxImpl - + VecZnxDftAllocBytesImpl - + VecZnxBigAllocBytesImpl - + TakeSvpPPolImpl; - -pub(crate) fn test_gglwe_encrypt_sk( - module: &Module, - basek: usize, - k_ksk: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - sigma: f64, -) where - Module: TestModuleFamily, - B: TestScratchFamily, -{ - let n: usize = module.n(); - let rows: usize = (k_ksk - digits * basek) / (digits * basek); - - let mut ksk: GLWESwitchingKey> = 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 = ScratchOwned::alloc(GLWESwitchingKey::encrypt_sk_scratch_space( - module, n, basek, k_ksk, rank_in, rank_out, - )); - - let mut sk_in: GLWESecret> = GLWESecret::alloc(n, rank_in); - sk_in.fill_ternary_prob(0.5, &mut source_xs); - - let mut sk_out: GLWESecret> = GLWESecret::alloc(n, rank_out); - sk_out.fill_ternary_prob(0.5, &mut source_xs); - let sk_out_exec: GLWESecretExec, 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( - module: &Module, - basek: usize, - k_ksk: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - sigma: f64, -) where - Module: TestModuleFamily, - B: TestScratchFamily, -{ - let n: usize = module.n(); - let rows: usize = (k_ksk - digits * basek) / (digits * basek); - - let mut ksk_compressed: GLWESwitchingKeyCompressed> = - 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 = ScratchOwned::alloc(GLWESwitchingKeyCompressed::encrypt_sk_scratch_space( - module, n, basek, k_ksk, rank_in, rank_out, - )); - - let mut sk_in: GLWESecret> = GLWESecret::alloc(n, rank_in); - sk_in.fill_ternary_prob(0.5, &mut source_xs); - - let mut sk_out: GLWESecret> = GLWESecret::alloc(n, rank_out); - sk_out.fill_ternary_prob(0.5, &mut source_xs); - let sk_out_exec: GLWESecretExec, 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> = 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( - module: &Module, - 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: - TestModuleFamily + GGLWEEncryptSkFamily + GLWEDecryptFamily + GLWEKeyswitchFamily + GGLWEExecLayoutFamily, - B: TestScratchFamily, -{ - 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> = - GLWESwitchingKey::alloc(n, basek, k_in, rows, digits_in, rank_in_s0s1, rank_out_s0s1); - let mut ct_gglwe_s1s2: GLWESwitchingKey> = - GLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_out_s0s1, rank_out_s1s2); - let mut ct_gglwe_s0s2: GLWESwitchingKey> = 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 = 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 = 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> = GLWESecret::alloc(n, rank_in_s0s1); - sk0.fill_ternary_prob(0.5, &mut source_xs); - - let mut sk1: GLWESecret> = GLWESecret::alloc(n, rank_out_s0s1); - sk1.fill_ternary_prob(0.5, &mut source_xs); - - let mut sk2: GLWESecret> = GLWESecret::alloc(n, rank_out_s1s2); - sk2.fill_ternary_prob(0.5, &mut source_xs); - let sk2_exec: GLWESecretExec, 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, 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( - module: &Module, - basek: usize, - k_ct: usize, - k_ksk: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - sigma: f64, -) where - Module: TestModuleFamily - + GLWESwitchingKeyEncryptSkFamily - + GLWEKeyswitchFamily - + GGLWEExecLayoutFamily - + GLWEDecryptFamily, - B: TestScratchFamily, -{ - 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> = - GLWESwitchingKey::alloc(n, basek, k_ct, rows, digits_in, rank_in, rank_out); - let mut ct_gglwe_s1s2: GLWESwitchingKey> = 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 = ScratchOwned::alloc(GLWESwitchingKey::encrypt_sk_scratch_space( - module, - n, - basek, - k_ksk, - rank_in | rank_out, - rank_out, - )); - let mut scratch_apply: ScratchOwned = 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> = GLWESecret::alloc(n, rank_in); - sk0.fill_ternary_prob(var_xs, &mut source_xs); - - let mut sk1: GLWESecret> = GLWESecret::alloc(n, rank_out); - sk1.fill_ternary_prob(var_xs, &mut source_xs); - - let mut sk2: GLWESecret> = GLWESecret::alloc(n, rank_out); - sk2.fill_ternary_prob(var_xs, &mut source_xs); - let sk2_exec: GLWESecretExec, 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, 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> = 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( - module: &Module, - basek: usize, - k_out: usize, - k_in: usize, - k_ggsw: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - sigma: f64, -) where - Module: TestModuleFamily - + GLWESwitchingKeyEncryptSkFamily - + GLWEExternalProductFamily - + GGSWLayoutFamily - + GLWEDecryptFamily - + VecZnxRotateInplace, - B: TestScratchFamily, -{ - 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> = GLWESwitchingKey::alloc(n, basek, k_in, rows, digits_in, rank_in, rank_out); - let mut ct_gglwe_out: GLWESwitchingKey> = - GLWESwitchingKey::alloc(n, basek, k_out, rows, digits_in, rank_in, rank_out); - let mut ct_rgsw: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank_out); - - let mut pt_rgsw: ScalarZnx> = 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 = 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> = GLWESecret::alloc(n, rank_in); - sk_in.fill_ternary_prob(var_xs, &mut source_xs); - - let mut sk_out: GLWESecret> = GLWESecret::alloc(n, rank_out); - sk_out.fill_ternary_prob(var_xs, &mut source_xs); - let sk_out_exec: GLWESecretExec, 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, 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( - module: &Module, - basek: usize, - k_ct: usize, - k_ggsw: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - sigma: f64, -) where - Module: TestModuleFamily - + GLWESwitchingKeyEncryptSkFamily - + GLWEExternalProductFamily - + GGSWLayoutFamily - + GLWEDecryptFamily - + VecZnxRotateInplace, - B: TestScratchFamily, -{ - let n: usize = module.n(); - let rows: usize = k_ct.div_ceil(basek * digits); - - let digits_in: usize = 1; - - let mut ct_gglwe: GLWESwitchingKey> = GLWESwitchingKey::alloc(n, basek, k_ct, rows, digits_in, rank_in, rank_out); - let mut ct_rgsw: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank_out); - - let mut pt_rgsw: ScalarZnx> = 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 = 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> = GLWESecret::alloc(n, rank_in); - sk_in.fill_ternary_prob(var_xs, &mut source_xs); - - let mut sk_out: GLWESecret> = GLWESecret::alloc(n, rank_out); - sk_out.fill_ternary_prob(var_xs, &mut source_xs); - let sk_out_exec: GLWESecretExec, 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, 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); -} diff --git a/core/src/gglwe/tests/mod.rs b/core/src/gglwe/tests/mod.rs deleted file mode 100644 index 586f4c5..0000000 --- a/core/src/gglwe/tests/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod cpu_spqlios; -mod generic_serialization; -mod generics_automorphism_key; -mod generics_gglwe; -mod generics_tensor_key; diff --git a/core/src/ggsw/mod.rs b/core/src/ggsw/mod.rs deleted file mode 100644 index 38c972a..0000000 --- a/core/src/ggsw/mod.rs +++ /dev/null @@ -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; diff --git a/core/src/ggsw/test/cpu_spqlios/mod.rs b/core/src/ggsw/test/cpu_spqlios/mod.rs deleted file mode 100644 index aebaafb..0000000 --- a/core/src/ggsw/test/cpu_spqlios/mod.rs +++ /dev/null @@ -1 +0,0 @@ -mod fft64; diff --git a/core/src/ggsw/test/generic_serialization.rs b/core/src/ggsw/test/generic_serialization.rs deleted file mode 100644 index e12108d..0000000 --- a/core/src/ggsw/test/generic_serialization.rs +++ /dev/null @@ -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> = GGSWCiphertext::alloc(1024, 12, 54, 3, 1, 2); - test_reader_writer_interface(original); -} - -#[test] -fn ggsw_test_compressed_serialization() { - let original: GGSWCiphertextCompressed> = GGSWCiphertextCompressed::alloc(1024, 12, 54, 3, 1, 2); - test_reader_writer_interface(original); -} diff --git a/core/src/ggsw/test/generic_tests.rs b/core/src/ggsw/test/generic_tests.rs deleted file mode 100644 index dfb1c6d..0000000 --- a/core/src/ggsw/test/generic_tests.rs +++ /dev/null @@ -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 = GLWESecretFamily - + GGSWEncryptSkFamily - + GGSWAssertNoiseFamily - + VecZnxAddScalarInplace - + VecZnxSubABInplace - + VecZnxStd - + VecZnxCopy; -pub(crate) trait TestScratchFamily = TakeVecZnxDftImpl - + TakeVecZnxBigImpl - + TakeSvpPPolImpl - + ScratchOwnedAllocImpl - + ScratchOwnedBorrowImpl - + ScratchAvailableImpl - + TakeScalarZnxImpl - + TakeVecZnxImpl - + VecZnxDftAllocBytesImpl - + VecZnxBigAllocBytesImpl - + TakeSvpPPolImpl; - -pub(crate) fn test_encrypt_sk(module: &Module, basek: usize, k: usize, digits: usize, rank: usize, sigma: f64) -where - Module: TestModuleFamily, - B: TestScratchFamily, -{ - let n: usize = module.n(); - let rows: usize = (k - digits * basek) / (digits * basek); - - let mut ct: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k, rows, digits, rank); - - let mut pt_scalar: ScalarZnx> = 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 = ScratchOwned::alloc(GGSWCiphertext::encrypt_sk_scratch_space( - module, n, basek, k, rank, - )); - - let mut sk: GLWESecret> = GLWESecret::alloc(n, rank); - sk.fill_ternary_prob(0.5, &mut source_xs); - let mut sk_exec: GLWESecretExec, 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( - module: &Module, - basek: usize, - k: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module: TestModuleFamily, - B: TestScratchFamily, -{ - let n: usize = module.n(); - let rows: usize = (k - digits * basek) / (digits * basek); - - let mut ct_compressed: GGSWCiphertextCompressed> = GGSWCiphertextCompressed::alloc(n, basek, k, rows, digits, rank); - - let mut pt_scalar: ScalarZnx> = 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 = ScratchOwned::alloc(GGSWCiphertextCompressed::encrypt_sk_scratch_space( - module, n, basek, k, rank, - )); - - let mut sk: GLWESecret> = GLWESecret::alloc(n, rank); - sk.fill_ternary_prob(0.5, &mut source_xs); - let mut sk_exec: GLWESecretExec, 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> = 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( - module: &Module, - basek: usize, - k_out: usize, - k_in: usize, - k_ksk: usize, - k_tsk: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module: TestModuleFamily - + GGSWAssertNoiseFamily - + GGSWKeySwitchFamily - + GLWESwitchingKeyEncryptSkFamily - + GLWETensorKeyEncryptSkFamily - + GGLWEExecLayoutFamily - + VecZnxSwithcDegree, - B: TestScratchFamily + VecZnxDftAllocBytesImpl + VecZnxBigAllocBytesImpl + TakeSvpPPolImpl, -{ - let n: usize = module.n(); - let rows: usize = k_in.div_ceil(digits * basek); - - let digits_in: usize = 1; - - let mut ct_in: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k_in, rows, digits_in, rank); - let mut ct_out: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k_out, rows, digits_in, rank); - let mut tsk: GLWETensorKey> = GLWETensorKey::alloc(n, basek, k_ksk, rows, digits, rank); - let mut ksk: GLWESwitchingKey> = GLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank, rank); - let mut pt_scalar: ScalarZnx> = 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 = 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> = GLWESecret::alloc(n, rank); - sk_in.fill_ternary_prob(var_xs, &mut source_xs); - let sk_in_dft: GLWESecretExec, B> = GLWESecretExec::from(module, &sk_in); - - let mut sk_out: GLWESecret> = GLWESecret::alloc(n, rank); - sk_out.fill_ternary_prob(var_xs, &mut source_xs); - let sk_out_exec: GLWESecretExec, 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, B> = - GLWESwitchingKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank, rank); - let mut tsk_exec: GLWETensorKeyExec, 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( - module: &Module, - basek: usize, - k_ct: usize, - k_ksk: usize, - k_tsk: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module: TestModuleFamily - + GGSWAssertNoiseFamily - + GGSWKeySwitchFamily - + GLWESwitchingKeyEncryptSkFamily - + GLWETensorKeyEncryptSkFamily - + GGLWEExecLayoutFamily - + VecZnxSwithcDegree, - B: TestScratchFamily, -{ - let n: usize = module.n(); - let rows: usize = k_ct.div_ceil(digits * basek); - - let digits_in: usize = 1; - - let mut ct: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k_ct, rows, digits_in, rank); - let mut tsk: GLWETensorKey> = GLWETensorKey::alloc(n, basek, k_tsk, rows, digits, rank); - let mut ksk: GLWESwitchingKey> = GLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank, rank); - let mut pt_scalar: ScalarZnx> = 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 = 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> = GLWESecret::alloc(n, rank); - sk_in.fill_ternary_prob(var_xs, &mut source_xs); - let sk_in_dft: GLWESecretExec, B> = GLWESecretExec::from(module, &sk_in); - - let mut sk_out: GLWESecret> = GLWESecret::alloc(n, rank); - sk_out.fill_ternary_prob(var_xs, &mut source_xs); - let sk_out_exec: GLWESecretExec, 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, B> = - GLWESwitchingKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank, rank); - let mut tsk_exec: GLWETensorKeyExec, 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( - p: i64, - module: &Module, - basek: usize, - k_out: usize, - k_in: usize, - k_ksk: usize, - k_tsk: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module: TestModuleFamily - + GGSWAssertNoiseFamily - + GGSWKeySwitchFamily - + GLWESwitchingKeyEncryptSkFamily - + GLWETensorKeyEncryptSkFamily - + GGLWEExecLayoutFamily - + VecZnxSwithcDegree - + VecZnxAutomorphismInplace - + VecZnxAutomorphismInplace - + VecZnxAutomorphism, - B: TestScratchFamily, -{ - 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> = GGSWCiphertext::alloc(n, basek, k_in, rows_in, digits_in, rank); - let mut ct_out: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k_out, rows_in, digits_in, rank); - let mut tensor_key: GLWETensorKey> = GLWETensorKey::alloc(n, basek, k_tsk, rows, digits, rank); - let mut auto_key: AutomorphismKey> = AutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); - let mut pt_scalar: ScalarZnx> = 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 = 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> = GLWESecret::alloc(n, rank); - sk.fill_ternary_prob(var_xs, &mut source_xs); - let sk_exec: GLWESecretExec, 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, 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, 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( - p: i64, - module: &Module, - basek: usize, - k_ct: usize, - k_ksk: usize, - k_tsk: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module: TestModuleFamily - + GGSWAssertNoiseFamily - + GGSWKeySwitchFamily - + GLWESwitchingKeyEncryptSkFamily - + GLWETensorKeyEncryptSkFamily - + GGLWEExecLayoutFamily - + VecZnxSwithcDegree - + VecZnxAutomorphismInplace - + VecZnxAutomorphism - + VecZnxAutomorphismInplace, - B: TestScratchFamily, -{ - 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> = GGSWCiphertext::alloc(n, basek, k_ct, rows_in, digits_in, rank); - let mut tensor_key: GLWETensorKey> = GLWETensorKey::alloc(n, basek, k_tsk, rows, digits, rank); - let mut auto_key: AutomorphismKey> = AutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); - let mut pt_scalar: ScalarZnx> = 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 = 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> = GLWESecret::alloc(n, rank); - sk.fill_ternary_prob(var_xs, &mut source_xs); - let sk_exec: GLWESecretExec, 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, 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, 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( - module: &Module, - basek: usize, - k_in: usize, - k_out: usize, - k_ggsw: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module: TestModuleFamily - + GGSWAssertNoiseFamily - + GGSWKeySwitchFamily - + GLWESwitchingKeyEncryptSkFamily - + GLWETensorKeyEncryptSkFamily - + GGLWEExecLayoutFamily - + VecZnxRotateInplace, - B: TestScratchFamily, -{ - 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> = GGSWCiphertext::alloc(n, basek, k_in, rows_in, digits_in, rank); - let mut ct_ggsw_lhs_out: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k_out, rows_in, digits_in, rank); - let mut ct_ggsw_rhs: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank); - let mut pt_ggsw_lhs: ScalarZnx> = ScalarZnx::alloc(n, 1); - let mut pt_ggsw_rhs: ScalarZnx> = 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 = 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> = GLWESecret::alloc(n, rank); - sk.fill_ternary_prob(0.5, &mut source_xs); - let sk_exec: GLWESecretExec, 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, 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( - module: &Module, - basek: usize, - k_ct: usize, - k_ggsw: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module: TestModuleFamily - + GGSWAssertNoiseFamily - + GGSWKeySwitchFamily - + GLWESwitchingKeyEncryptSkFamily - + GLWETensorKeyEncryptSkFamily - + GGLWEExecLayoutFamily - + VecZnxRotateInplace, - B: TestScratchFamily, -{ - 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> = GGSWCiphertext::alloc(n, basek, k_ct, rows_in, digits_in, rank); - let mut ct_ggsw_rhs: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank); - - let mut pt_ggsw_lhs: ScalarZnx> = ScalarZnx::alloc(n, 1); - let mut pt_ggsw_rhs: ScalarZnx> = 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 = 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> = GLWESecret::alloc(n, rank); - sk.fill_ternary_prob(0.5, &mut source_xs); - let sk_exec: GLWESecretExec, 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, 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); -} diff --git a/core/src/ggsw/test/mod.rs b/core/src/ggsw/test/mod.rs deleted file mode 100644 index c3e241f..0000000 --- a/core/src/ggsw/test/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod cpu_spqlios; -mod generic_serialization; -mod generic_tests; diff --git a/core/src/glwe/mod.rs b/core/src/glwe/mod.rs deleted file mode 100644 index ec4a48d..0000000 --- a/core/src/glwe/mod.rs +++ /dev/null @@ -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::*; diff --git a/core/src/glwe/public_key.rs b/core/src/glwe/public_key.rs deleted file mode 100644 index d45f663..0000000 --- a/core/src/glwe/public_key.rs +++ /dev/null @@ -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 = GLWEEncryptSkFamily; - -#[derive(PartialEq, Eq)] -pub struct GLWEPublicKey { - pub(crate) data: VecZnx, - pub(crate) basek: usize, - pub(crate) k: usize, - pub(crate) dist: Distribution, -} - -impl GLWEPublicKey> { - 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 Infos for GLWEPublicKey { - type Inner = VecZnx; - - fn inner(&self) -> &Self::Inner { - &self.data - } - - fn basek(&self) -> usize { - self.basek - } - - fn k(&self) -> usize { - self.k - } -} - -impl GLWEPublicKey { - pub fn rank(&self) -> usize { - self.cols() - 1 - } -} - -impl GLWEPublicKey { - pub fn generate_from_sk( - &mut self, - module: &Module, - sk: &GLWESecretExec, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - ) where - Module: GLWEPublicKeyFamily, - B: ScratchOwnedAllocImpl - + ScratchOwnedBorrowImpl - + TakeVecZnxDftImpl - + ScratchAvailableImpl - + TakeVecZnxImpl, - { - #[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 = ScratchOwned::alloc(GLWECiphertext::encrypt_sk_scratch_space( - module, - self.n(), - self.basek(), - self.k(), - )); - - let mut tmp: GLWECiphertext> = 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 ReaderFrom for GLWEPublicKey { - fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { - self.k = reader.read_u64::()? as usize; - self.basek = reader.read_u64::()? as usize; - match Distribution::read_from(reader) { - Ok(dist) => self.dist = dist, - Err(e) => return Err(e), - } - self.data.read_from(reader) - } -} - -impl WriterTo for GLWEPublicKey { - fn write_to(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::(self.k as u64)?; - writer.write_u64::(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 { - pub(crate) data: VecZnxDft, - pub(crate) basek: usize, - pub(crate) k: usize, - pub(crate) dist: Distribution, -} - -impl Infos for GLWEPublicKeyExec { - type Inner = VecZnxDft; - - fn inner(&self) -> &Self::Inner { - &self.data - } - - fn basek(&self) -> usize { - self.basek - } - - fn k(&self) -> usize { - self.k - } -} - -impl GLWEPublicKeyExec { - pub fn rank(&self) -> usize { - self.cols() - 1 - } -} - -impl GLWEPublicKeyExec, B> { - pub fn alloc(module: &Module, n: usize, basek: usize, k: usize, rank: usize) -> Self - where - Module: VecZnxDftAlloc, - { - 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, n: usize, basek: usize, k: usize, rank: usize) -> usize - where - Module: VecZnxDftAllocBytes, - { - module.vec_znx_dft_alloc_bytes(n, rank + 1, k.div_ceil(basek)) - } - - pub fn from(module: &Module, other: &GLWEPublicKey, scratch: &mut Scratch) -> Self - where - DataOther: DataRef, - Module: VecZnxDftAlloc + VecZnxDftFromVecZnx, - { - let mut pk_exec: GLWEPublicKeyExec, B> = - GLWEPublicKeyExec::alloc(module, other.n(), other.basek(), other.k(), other.rank()); - pk_exec.prepare(module, other, scratch); - pk_exec - } -} - -impl GLWEPublicKeyExec { - pub fn prepare(&mut self, module: &Module, other: &GLWEPublicKey, _scratch: &mut Scratch) - where - DataOther: DataRef, - Module: VecZnxDftFromVecZnx, - { - #[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; - } -} diff --git a/core/src/glwe/tests/cpu_spqlios/mod.rs b/core/src/glwe/tests/cpu_spqlios/mod.rs deleted file mode 100644 index aebaafb..0000000 --- a/core/src/glwe/tests/cpu_spqlios/mod.rs +++ /dev/null @@ -1 +0,0 @@ -mod fft64; diff --git a/core/src/glwe/tests/generic_serialization.rs b/core/src/glwe/tests/generic_serialization.rs deleted file mode 100644 index 9ae772b..0000000 --- a/core/src/glwe/tests/generic_serialization.rs +++ /dev/null @@ -1,15 +0,0 @@ -use backend::hal::tests::serialization::test_reader_writer_interface; - -use crate::{GLWECiphertext, GLWECiphertextCompressed}; - -#[test] -fn test_serialization() { - let original: GLWECiphertext> = GLWECiphertext::alloc(1024, 12, 54, 3); - test_reader_writer_interface(original); -} - -#[test] -fn test_compressed_serialization() { - let original: GLWECiphertextCompressed> = GLWECiphertextCompressed::alloc(1024, 12, 54, 3); - test_reader_writer_interface(original); -} diff --git a/core/src/glwe/tests/mod.rs b/core/src/glwe/tests/mod.rs deleted file mode 100644 index c025340..0000000 --- a/core/src/glwe/tests/mod.rs +++ /dev/null @@ -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; diff --git a/core/src/glwe/packing.rs b/core/src/glwe_packing.rs similarity index 91% rename from core/src/glwe/packing.rs rename to core/src/glwe_packing.rs index 602a6c4..d7329e2 100644 --- a/core/src/glwe/packing.rs +++ b/core/src/glwe_packing.rs @@ -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 = GLWEKeyswitchFamily - + VecZnxCopy - + VecZnxRotateInplace - + VecZnxSub - + VecZnxNegateInplace - + VecZnxRshInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace - + VecZnxSubABInplace - + VecZnxRotate - + VecZnxAutomorphismInplace - + VecZnxBigSubSmallBInplace - + VecZnxBigAutomorphismInplace; +use crate::trait_families::{GLWEKeyswitchFamily, GLWEPackingFamily}; /// [GLWEPacker] enables only the fly GLWE packing /// with constant memory of Log(N) ciphertexts. @@ -128,7 +115,7 @@ impl GLWEPacker { &mut self, module: &Module, a: Option<&GLWECiphertext>, - auto_keys: &HashMap>, + auto_keys: &HashMap>, scratch: &mut Scratch, ) where Module: GLWEPackingFamily, @@ -187,7 +174,7 @@ fn pack_core( a: Option<&GLWECiphertext>, accumulators: &mut [Accumulator], i: usize, - auto_keys: &HashMap>, + auto_keys: &HashMap>, scratch: &mut Scratch, ) where Module: GLWEPackingFamily, @@ -265,7 +252,7 @@ fn combine( acc: &mut Accumulator, b: Option<&GLWECiphertext>, i: usize, - auto_keys: &HashMap>, + auto_keys: &HashMap>, scratch: &mut Scratch, ) where Module: GLWEPackingFamily, diff --git a/core/src/glwe/trace.rs b/core/src/glwe_trace.rs similarity index 68% rename from core/src/glwe/trace.rs rename to core/src/glwe_trace.rs index ab21375..6891b78 100644 --- a/core/src/glwe/trace.rs +++ b/core/src/glwe_trace.rs @@ -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 = GLWEKeyswitchFamily + VecZnxCopy + VecZnxRshInplace + VecZnxBigAutomorphismInplace; +use crate::trait_families::{GLWETraceModuleFamily, GLWETraceScratchFamily}; impl GLWECiphertext> { pub fn trace_galois_elements(module: &Module) -> Vec { @@ -33,7 +33,7 @@ impl GLWECiphertext> { rank: usize, ) -> usize where - Module: GLWEKeyswitchFamily, + Module: GLWETraceModuleFamily, { Self::automorphism_inplace_scratch_space(module, n, basek, out_k.min(in_k), ksk_k, digits, rank) } @@ -48,27 +48,24 @@ impl GLWECiphertext> { rank: usize, ) -> usize where - Module: GLWEKeyswitchFamily, + Module: GLWETraceModuleFamily, { Self::automorphism_inplace_scratch_space(module, n, basek, out_k, ksk_k, digits, rank) } } -impl GLWECiphertext -where - GLWECiphertext: GLWECiphertextToMut + Infos + SetMetaData, -{ +impl GLWECiphertext { pub fn trace( &mut self, module: &Module, start: usize, end: usize, lhs: &GLWECiphertext, - auto_keys: &HashMap>, + auto_keys: &HashMap>, scratch: &mut Scratch, ) where - Module: GLWETraceFamily, - Scratch: TakeVecZnxDft + ScratchAvailable, + Module: GLWETraceModuleFamily, + Scratch: GLWETraceScratchFamily, { self.copy(module, lhs); self.trace_inplace(module, start, end, auto_keys, scratch); @@ -79,11 +76,11 @@ where module: &Module, start: usize, end: usize, - auto_keys: &HashMap>, + auto_keys: &HashMap>, scratch: &mut Scratch, ) where - Module: GLWETraceFamily, - Scratch: TakeVecZnxDft + ScratchAvailable, + Module: GLWETraceModuleFamily, + Scratch: GLWETraceScratchFamily, { (start..end).for_each(|i| { self.rsh(module, 1); diff --git a/core/src/gglwe/keyswitch.rs b/core/src/keyswitching/gglwe_ct.rs similarity index 83% rename from core/src/gglwe/keyswitch.rs rename to core/src/keyswitching/gglwe_ct.rs index e210419..19d8242 100644 --- a/core/src/gglwe/keyswitch.rs +++ b/core/src/keyswitching/gglwe_ct.rs @@ -4,10 +4,14 @@ use backend::hal::{ }; use crate::{ - AutomorphismKey, AutomorphismKeyExec, GLWECiphertext, GLWEKeyswitchFamily, GLWESwitchingKey, GLWESwitchingKeyExec, Infos, + layouts::{ + GGLWEAutomorphismKey, GLWECiphertext, GGLWESwitchingKey, Infos, + prepared::{GGLWEAutomorphismKeyExec, GGLWESwitchingKeyExec}, + }, + trait_families::GLWEKeyswitchFamily, }; -impl AutomorphismKey> { +impl GGLWEAutomorphismKey> { pub fn keyswitch_scratch_space( module: &Module, n: usize, @@ -21,7 +25,7 @@ impl AutomorphismKey> { where Module: GLWEKeyswitchFamily, { - 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( @@ -36,16 +40,16 @@ impl AutomorphismKey> { where Module: GLWEKeyswitchFamily, { - 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 AutomorphismKey { +impl GGLWEAutomorphismKey { pub fn keyswitch( &mut self, module: &Module, - lhs: &AutomorphismKey, - rhs: &GLWESwitchingKeyExec, + lhs: &GGLWEAutomorphismKey, + rhs: &GGLWESwitchingKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily, @@ -57,7 +61,7 @@ impl AutomorphismKey { pub fn keyswitch_inplace( &mut self, module: &Module, - rhs: &AutomorphismKeyExec, + rhs: &GGLWEAutomorphismKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily, @@ -67,7 +71,7 @@ impl AutomorphismKey { } } -impl GLWESwitchingKey> { +impl GGLWESwitchingKey> { pub fn keyswitch_scratch_space( module: &Module, n: usize, @@ -103,12 +107,12 @@ impl GLWESwitchingKey> { } } -impl GLWESwitchingKey { +impl GGLWESwitchingKey { pub fn keyswitch( &mut self, module: &Module, - lhs: &GLWESwitchingKey, - rhs: &GLWESwitchingKeyExec, + lhs: &GGLWESwitchingKey, + rhs: &GGLWESwitchingKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily, @@ -156,7 +160,7 @@ impl GLWESwitchingKey { pub fn keyswitch_inplace( &mut self, module: &Module, - rhs: &GLWESwitchingKeyExec, + rhs: &GGLWESwitchingKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily, diff --git a/core/src/ggsw/keyswitch.rs b/core/src/keyswitching/ggsw_ct.rs similarity index 95% rename from core/src/ggsw/keyswitch.rs rename to core/src/keyswitching/ggsw_ct.rs index 4c85b0c..4aaf96b 100644 --- a/core/src/ggsw/keyswitch.rs +++ b/core/src/keyswitching/ggsw_ct.rs @@ -7,12 +7,14 @@ use backend::hal::{ }; 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 = - GLWEKeyswitchFamily + VecZnxBigAllocBytes + VecZnxDftCopy + VecZnxDftAddInplace + VecZnxDftToVecZnxBigTmpA; - impl GGSWCiphertext> { pub(crate) fn expand_row_scratch_space( module: &Module, @@ -95,7 +97,7 @@ impl GGSWCiphertext { &mut self, module: &Module, a: &GGLWECiphertext, - tsk: &GLWETensorKeyExec, + tsk: &GGLWETensorKeyExec, scratch: &mut Scratch, ) where DataA: DataRef, @@ -121,8 +123,8 @@ impl GGSWCiphertext { &mut self, module: &Module, lhs: &GGSWCiphertext, - ksk: &GLWESwitchingKeyExec, - tsk: &GLWETensorKeyExec, + ksk: &GGLWESwitchingKeyExec, + tsk: &GGLWETensorKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily + GGSWKeySwitchFamily + VecZnxNormalizeTmpBytes, @@ -135,8 +137,8 @@ impl GGSWCiphertext { pub fn keyswitch_inplace( &mut self, module: &Module, - ksk: &GLWESwitchingKeyExec, - tsk: &GLWETensorKeyExec, + ksk: &GGLWESwitchingKeyExec, + tsk: &GGLWETensorKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily + GGSWKeySwitchFamily + VecZnxNormalizeTmpBytes, @@ -151,7 +153,7 @@ impl GGSWCiphertext { pub fn expand_row( &mut self, module: &Module, - tsk: &GLWETensorKeyExec, + tsk: &GGLWETensorKeyExec, scratch: &mut Scratch, ) where Module: GGSWKeySwitchFamily + VecZnxNormalizeTmpBytes, @@ -276,7 +278,7 @@ impl GGSWCiphertext { &mut self, module: &Module, lhs: &GGSWCiphertext, - ksk: &GLWESwitchingKeyExec, + ksk: &GGLWESwitchingKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily + GGSWKeySwitchFamily + VecZnxNormalizeTmpBytes, diff --git a/core/src/glwe/keyswitch.rs b/core/src/keyswitching/glwe_ct.rs similarity index 83% rename from core/src/glwe/keyswitch.rs rename to core/src/keyswitching/glwe_ct.rs index 909910e..cfc5297 100644 --- a/core/src/glwe/keyswitch.rs +++ b/core/src/keyswitching/glwe_ct.rs @@ -6,18 +6,10 @@ use backend::hal::{ layouts::{Backend, DataMut, DataRef, Module, Scratch, VecZnx, VecZnxBig, VecZnxDft, VmpPMat}, }; -use crate::{GLWECiphertext, GLWESwitchingKeyExec, Infos}; - -pub trait GLWEKeyswitchFamily = VecZnxDftAllocBytes - + VmpApplyTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyTmpBytes - + VmpApply - + VmpApplyAdd - + VecZnxDftFromVecZnx - + VecZnxDftToVecZnxBigConsume - + VecZnxBigAddSmallInplace - + VecZnxBigNormalize; +use crate::{ + layouts::{GLWECiphertext, Infos, prepared::GGLWESwitchingKeyExec}, + trait_families::GLWEKeyswitchFamily, +}; impl GLWECiphertext> { pub fn keyswitch_scratch_space( @@ -52,25 +44,6 @@ impl GLWECiphertext> { return res_dft + ((ai_dft + vmp) | normalize); } - pub fn keyswitch_from_fourier_scratch_space( - module: &Module, - n: usize, - basek: usize, - k_out: usize, - k_in: usize, - k_ksk: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - ) -> usize - where - Module: GLWEKeyswitchFamily, - { - Self::keyswitch_scratch_space( - module, n, basek, k_out, k_in, k_ksk, digits, rank_in, rank_out, - ) - } - pub fn keyswitch_inplace_scratch_space( module: &Module, n: usize, @@ -92,7 +65,7 @@ impl GLWECiphertext { &self, module: &Module, lhs: &GLWECiphertext, - rhs: &GLWESwitchingKeyExec, + rhs: &GGLWESwitchingKeyExec, scratch: &Scratch, ) where DataLhs: DataRef, @@ -163,7 +136,7 @@ impl GLWECiphertext { &mut self, module: &Module, lhs: &GLWECiphertext, - rhs: &GLWESwitchingKeyExec, + rhs: &GGLWESwitchingKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily, @@ -174,7 +147,7 @@ impl GLWECiphertext { 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 @@ impl GLWECiphertext { pub fn keyswitch_inplace( &mut self, module: &Module, - rhs: &GLWESwitchingKeyExec, + rhs: &GGLWESwitchingKeyExec, scratch: &mut Scratch, ) where Module: GLWEKeyswitchFamily, @@ -196,32 +169,33 @@ impl GLWECiphertext { } } -pub(crate) fn keyswitch( - module: &Module, - res_dft: VecZnxDft, - lhs: &GLWECiphertext, - rhs: &GLWESwitchingKeyExec, - scratch: &mut Scratch, -) -> VecZnxBig -where - DataRes: DataMut, - DataIn: DataRef, - DataKey: DataRef, - Module: GLWEKeyswitchFamily, - Scratch: TakeVecZnxDft, -{ - if rhs.digits() == 1 { - return keyswitch_vmp_one_digit(module, res_dft, &lhs.data, &rhs.key.data, scratch); - } +impl GLWECiphertext { + pub(crate) fn keyswitch_internal( + &self, + module: &Module, + res_dft: VecZnxDft, + rhs: &GGLWESwitchingKeyExec, + scratch: &mut Scratch, + ) -> VecZnxBig + where + DataRes: DataMut, + DataKey: DataRef, + Module: GLWEKeyswitchFamily, + Scratch: TakeVecZnxDft, + { + 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, - &lhs.data, - &rhs.key.data, - rhs.digits(), - scratch, - ) + keyswitch_vmp_multiple_digits( + module, + res_dft, + &self.data, + &rhs.key.data, + rhs.digits(), + scratch, + ) + } } fn keyswitch_vmp_one_digit( diff --git a/core/src/keyswitching/lwe_ct.rs b/core/src/keyswitching/lwe_ct.rs new file mode 100644 index 0000000..1623b21 --- /dev/null +++ b/core/src/keyswitching/lwe_ct.rs @@ -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> { + pub fn keyswitch_scratch_space( + module: &Module, + n: usize, + basek: usize, + k_lwe_out: usize, + k_lwe_in: usize, + k_ksk: usize, + ) -> usize + where + Module: GLWEKeyswitchFamily, + { + 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 LWECiphertext { + pub fn keyswitch( + &mut self, + module: &Module, + a: &LWECiphertext, + ksk: &LWESwitchingKeyExec, + scratch: &mut Scratch, + ) where + A: DataRef, + DKs: DataRef, + Module: GLWEKeyswitchFamily, + Scratch: TakeVecZnxDft + 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); + } +} diff --git a/core/src/keyswitching/mod.rs b/core/src/keyswitching/mod.rs new file mode 100644 index 0000000..c6a3610 --- /dev/null +++ b/core/src/keyswitching/mod.rs @@ -0,0 +1,4 @@ +mod gglwe_ct; +mod ggsw_ct; +mod glwe_ct; +mod lwe_ct; diff --git a/core/src/layouts/compressed/gglwe_atk.rs b/core/src/layouts/compressed/gglwe_atk.rs new file mode 100644 index 0000000..dcdb303 --- /dev/null +++ b/core/src/layouts/compressed/gglwe_atk.rs @@ -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 { + pub(crate) key: GGLWESwitchingKeyCompressed, + pub(crate) p: i64, +} + +impl fmt::Debug for GGLWEAutomorphismKeyCompressed { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl FillUniform for GGLWEAutomorphismKeyCompressed { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.key.fill_uniform(source); + } +} + +impl Reset for GGLWEAutomorphismKeyCompressed +where + MatZnx: Reset, +{ + fn reset(&mut self) { + self.key.reset(); + self.p = 0; + } +} + +impl fmt::Display for GGLWEAutomorphismKeyCompressed { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(AutomorphismKeyCompressed: p={}) {}", self.p, self.key) + } +} + +impl GGLWEAutomorphismKeyCompressed> { + 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::>::bytes_of(n, basek, k, rows, digits, rank) + } +} + +impl Infos for GGLWEAutomorphismKeyCompressed { + type Inner = MatZnx; + + fn inner(&self) -> &Self::Inner { + &self.key.inner() + } + + fn basek(&self) -> usize { + self.key.basek() + } + + fn k(&self) -> usize { + self.key.k() + } +} + +impl GGLWEAutomorphismKeyCompressed { + 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 ReaderFrom for GGLWEAutomorphismKeyCompressed { + fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { + self.p = reader.read_u64::()? as i64; + self.key.read_from(reader) + } +} + +impl WriterTo for GGLWEAutomorphismKeyCompressed { + fn write_to(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::(self.p as u64)?; + self.key.write_to(writer) + } +} + +impl Decompress> for GGLWEAutomorphismKey { + fn decompress(&mut self, module: &Module, other: &GGLWEAutomorphismKeyCompressed) + where + Module: VecZnxFillUniform + VecZnxCopy, + { + self.key.decompress(module, &other.key); + self.p = other.p; + } +} diff --git a/core/src/layouts/compressed/gglwe_ct.rs b/core/src/layouts/compressed/gglwe_ct.rs new file mode 100644 index 0000000..59643ce --- /dev/null +++ b/core/src/layouts/compressed/gglwe_ct.rs @@ -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 { + pub(crate) data: MatZnx, + pub(crate) basek: usize, + pub(crate) k: usize, + pub(crate) rank_out: usize, + pub(crate) digits: usize, + pub(crate) seed: Vec<[u8; 32]>, +} + +impl fmt::Debug for GGLWECiphertextCompressed { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl FillUniform for GGLWECiphertextCompressed { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.data.fill_uniform(source); + } +} + +impl Reset for GGLWECiphertextCompressed +where + MatZnx: 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 fmt::Display for GGLWECiphertextCompressed { + 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> { + 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 Infos for GGLWECiphertextCompressed { + type Inner = MatZnx; + + fn inner(&self) -> &Self::Inner { + &self.data + } + + fn basek(&self) -> usize { + self.basek + } + + fn k(&self) -> usize { + self.k + } +} + +impl GGLWECiphertextCompressed { + 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 GGLWECiphertextCompressed { + 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 GGLWECiphertextCompressed { + 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 ReaderFrom for GGLWECiphertextCompressed { + fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { + self.k = reader.read_u64::()? as usize; + self.basek = reader.read_u64::()? as usize; + self.digits = reader.read_u64::()? as usize; + self.rank_out = reader.read_u64::()? as usize; + let seed_len = reader.read_u64::()? 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 WriterTo for GGLWECiphertextCompressed { + fn write_to(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::(self.k as u64)?; + writer.write_u64::(self.basek as u64)?; + writer.write_u64::(self.digits as u64)?; + writer.write_u64::(self.rank_out as u64)?; + writer.write_u64::(self.seed.len() as u64)?; + for s in &self.seed { + writer.write_all(s)?; + } + self.data.write_to(writer) + } +} + +impl Decompress> for GGLWECiphertext { + fn decompress(&mut self, module: &Module, other: &GGLWECiphertextCompressed) + where + Module: 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)); + }); + }); + } +} diff --git a/core/src/layouts/compressed/gglwe_ksk.rs b/core/src/layouts/compressed/gglwe_ksk.rs new file mode 100644 index 0000000..02543cf --- /dev/null +++ b/core/src/layouts/compressed/gglwe_ksk.rs @@ -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 { + pub(crate) key: GGLWECiphertextCompressed, + pub(crate) sk_in_n: usize, // Degree of sk_in + pub(crate) sk_out_n: usize, // Degree of sk_out +} + +impl fmt::Debug for GGLWESwitchingKeyCompressed { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl FillUniform for GGLWESwitchingKeyCompressed { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.key.fill_uniform(source); + } +} + +impl Reset for GGLWESwitchingKeyCompressed +where + MatZnx: Reset, +{ + fn reset(&mut self) { + self.key.reset(); + self.sk_in_n = 0; + self.sk_out_n = 0; + } +} + +impl fmt::Display for GGLWESwitchingKeyCompressed { + 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 Infos for GGLWESwitchingKeyCompressed { + type Inner = MatZnx; + + fn inner(&self) -> &Self::Inner { + &self.key.inner() + } + + fn basek(&self) -> usize { + self.key.basek() + } + + fn k(&self) -> usize { + self.key.k() + } +} + +impl GGLWESwitchingKeyCompressed { + 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> { + 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 ReaderFrom for GGLWESwitchingKeyCompressed { + fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { + self.sk_in_n = reader.read_u64::()? as usize; + self.sk_out_n = reader.read_u64::()? as usize; + self.key.read_from(reader) + } +} + +impl WriterTo for GGLWESwitchingKeyCompressed { + fn write_to(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::(self.sk_in_n as u64)?; + writer.write_u64::(self.sk_out_n as u64)?; + self.key.write_to(writer) + } +} + +impl Decompress> for GGLWESwitchingKey { + fn decompress(&mut self, module: &Module, other: &GGLWESwitchingKeyCompressed) + where + Module: VecZnxFillUniform + VecZnxCopy, + { + self.key.decompress(module, &other.key); + self.sk_in_n = other.sk_in_n; + self.sk_out_n = other.sk_out_n; + } +} diff --git a/core/src/layouts/compressed/gglwe_tsk.rs b/core/src/layouts/compressed/gglwe_tsk.rs new file mode 100644 index 0000000..6fc913c --- /dev/null +++ b/core/src/layouts/compressed/gglwe_tsk.rs @@ -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 { + pub(crate) keys: Vec>, +} + +impl fmt::Debug for GGLWETensorKeyCompressed { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl FillUniform for GGLWETensorKeyCompressed { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.keys + .iter_mut() + .for_each(|key: &mut GGLWESwitchingKeyCompressed| key.fill_uniform(source)) + } +} + +impl Reset for GGLWETensorKeyCompressed +where + MatZnx: Reset, +{ + fn reset(&mut self) { + self.keys + .iter_mut() + .for_each(|key: &mut GGLWESwitchingKeyCompressed| key.reset()) + } +} + +impl fmt::Display for GGLWETensorKeyCompressed { + 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> { + pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self { + let mut keys: Vec>> = 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 Infos for GGLWETensorKeyCompressed { + type Inner = MatZnx; + + 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 GGLWETensorKeyCompressed { + 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 ReaderFrom for GGLWETensorKeyCompressed { + fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { + let len: usize = reader.read_u64::()? 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 WriterTo for GGLWETensorKeyCompressed { + fn write_to(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::(self.keys.len() as u64)?; + for key in &self.keys { + key.write_to(writer)?; + } + Ok(()) + } +} + +impl GGLWETensorKeyCompressed { + pub(crate) fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWESwitchingKeyCompressed { + 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 Decompress> for GGLWETensorKey { + fn decompress(&mut self, module: &Module, other: &GGLWETensorKeyCompressed) + where + Module: 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); + }); + } +} diff --git a/core/src/ggsw/layout_compressed.rs b/core/src/layouts/compressed/ggsw_ct.rs similarity index 97% rename from core/src/ggsw/layout_compressed.rs rename to core/src/layouts/compressed/ggsw_ct.rs index 6aef85f..4dce213 100644 --- a/core/src/ggsw/layout_compressed.rs +++ b/core/src/layouts/compressed/ggsw_ct.rs @@ -3,7 +3,10 @@ use backend::hal::{ 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; diff --git a/core/src/glwe/layout.rs b/core/src/layouts/compressed/glwe_ct.rs similarity index 54% rename from core/src/glwe/layout.rs rename to core/src/layouts/compressed/glwe_ct.rs index ec8fbb3..3d429b0 100644 --- a/core/src/glwe/layout.rs +++ b/core/src/layouts/compressed/glwe_ct.rs @@ -1,160 +1,15 @@ use backend::hal::{ api::{FillUniform, Reset, VecZnxCopy, VecZnxFillUniform, ZnxInfos}, - layouts::{Backend, Data, DataMut, DataRef, Module, ReaderFrom, VecZnx, VecZnxToMut, VecZnxToRef, WriterTo}, + layouts::{Backend, Data, DataMut, DataRef, Module, ReaderFrom, VecZnx, WriterTo}, }; use sampling::source::Source; -use crate::{Decompress, GLWEOps, Infos, SetMetaData}; -use std::fmt; - -#[derive(PartialEq, Eq, Clone)] -pub struct GLWECiphertext { - pub data: VecZnx, - pub basek: usize, - pub k: usize, -} - -impl fmt::Debug for GLWECiphertext { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl fmt::Display for GLWECiphertext { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "GLWECiphertext: basek={} k={}: {}", - self.basek(), - self.k(), - self.data - ) - } -} - -impl Reset for GLWECiphertext -where - VecZnx: Reset, -{ - fn reset(&mut self) { - self.data.reset(); - self.basek = 0; - self.k = 0; - } -} - -impl FillUniform for GLWECiphertext -where - VecZnx: FillUniform, -{ - fn fill_uniform(&mut self, source: &mut Source) { - self.data.fill_uniform(source); - } -} - -impl GLWECiphertext> { - 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 Infos for GLWECiphertext { - type Inner = VecZnx; - - fn inner(&self) -> &Self::Inner { - &self.data - } - - fn basek(&self) -> usize { - self.basek - } - - fn k(&self) -> usize { - self.k - } -} - -impl GLWECiphertext { - pub fn rank(&self) -> usize { - self.cols() - 1 - } -} - -impl GLWECiphertext { - pub fn clone(&self) -> GLWECiphertext> { - GLWECiphertext { - data: self.data.clone(), - basek: self.basek(), - k: self.k(), - } - } -} - -impl SetMetaData for GLWECiphertext { - 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 GLWECiphertextToRef for GLWECiphertext { - 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 GLWECiphertextToMut for GLWECiphertext { - fn to_mut(&mut self) -> GLWECiphertext<&mut [u8]> { - GLWECiphertext { - data: self.data.to_mut(), - basek: self.basek, - k: self.k, - } - } -} - -impl GLWEOps for GLWECiphertext where GLWECiphertext: GLWECiphertextToMut + Infos + SetMetaData {} - +use crate::{ + layouts::{GLWECiphertext, Infos}, + trait_families::{Decompress, DecompressFamily}, +}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; - -impl ReaderFrom for GLWECiphertext { - fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { - self.k = reader.read_u64::()? as usize; - self.basek = reader.read_u64::()? as usize; - self.data.read_from(reader) - } -} - -impl WriterTo for GLWECiphertext { - fn write_to(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::(self.k as u64)?; - writer.write_u64::(self.basek as u64)?; - self.data.write_to(writer) - } -} +use std::fmt; #[derive(PartialEq, Eq, Clone)] pub struct GLWECiphertextCompressed { @@ -185,10 +40,7 @@ impl fmt::Display for GLWECiphertextCompressed { } } -impl Reset for GLWECiphertextCompressed -where - VecZnx: Reset, -{ +impl Reset for GLWECiphertextCompressed { fn reset(&mut self) { self.data.reset(); self.basek = 0; @@ -198,10 +50,7 @@ where } } -impl FillUniform for GLWECiphertextCompressed -where - VecZnx: FillUniform, -{ +impl FillUniform for GLWECiphertextCompressed { fn fill_uniform(&mut self, source: &mut Source) { self.data.fill_uniform(source); } @@ -268,7 +117,7 @@ impl WriterTo for GLWECiphertextCompressed { impl Decompress> for GLWECiphertext { fn decompress(&mut self, module: &Module, other: &GLWECiphertextCompressed) where - Module: VecZnxFillUniform + VecZnxCopy, + Module: DecompressFamily, { #[cfg(debug_assertions)] { @@ -307,7 +156,7 @@ impl GLWECiphertext { source: &mut Source, ) where DataOther: DataRef, - Module: VecZnxFillUniform + VecZnxCopy, + Module: DecompressFamily, { #[cfg(debug_assertions)] { diff --git a/core/src/layouts/compressed/glwe_to_lwe_ksk.rs b/core/src/layouts/compressed/glwe_to_lwe_ksk.rs new file mode 100644 index 0000000..a2b752c --- /dev/null +++ b/core/src/layouts/compressed/glwe_to_lwe_ksk.rs @@ -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(pub(crate) GGLWESwitchingKeyCompressed); + +impl fmt::Debug for GLWEToLWESwitchingKeyCompressed { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl FillUniform for GLWEToLWESwitchingKeyCompressed { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.0.fill_uniform(source); + } +} + +impl Reset for GLWEToLWESwitchingKeyCompressed { + fn reset(&mut self) { + self.0.reset(); + } +} + +impl fmt::Display for GLWEToLWESwitchingKeyCompressed { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(GLWEToLWESwitchingKeyCompressed) {}", self.0) + } +} + +impl Infos for GLWEToLWESwitchingKeyCompressed { + type Inner = MatZnx; + + fn inner(&self) -> &Self::Inner { + &self.0.inner() + } + + fn basek(&self) -> usize { + self.0.basek() + } + + fn k(&self) -> usize { + self.0.k() + } +} + +impl GLWEToLWESwitchingKeyCompressed { + 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 ReaderFrom for GLWEToLWESwitchingKeyCompressed { + fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { + self.0.read_from(reader) + } +} + +impl WriterTo for GLWEToLWESwitchingKeyCompressed { + fn write_to(&self, writer: &mut W) -> std::io::Result<()> { + self.0.write_to(writer) + } +} + +impl GLWEToLWESwitchingKeyCompressed> { + 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(module: &Module, n: usize, basek: usize, k: usize, rank_in: usize) -> usize + where + Module: GGLWEEncryptSkFamily + GLWESecretExecModuleFamily, + { + GLWEToLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank_in) + } +} diff --git a/core/src/layouts/compressed/lwe_ct.rs b/core/src/layouts/compressed/lwe_ct.rs new file mode 100644 index 0000000..7871b56 --- /dev/null +++ b/core/src/layouts/compressed/lwe_ct.rs @@ -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 { + pub(crate) data: VecZnx, + pub(crate) k: usize, + pub(crate) basek: usize, + pub(crate) seed: [u8; 32], +} + +impl fmt::Debug for LWECiphertextCompressed { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl fmt::Display for LWECiphertextCompressed { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "LWECiphertextCompressed: basek={} k={} seed={:?}: {}", + self.basek(), + self.k(), + self.seed, + self.data + ) + } +} + +impl Reset for LWECiphertextCompressed +where + VecZnx: Reset, +{ + fn reset(&mut self) { + self.data.reset(); + self.basek = 0; + self.k = 0; + self.seed = [0u8; 32]; + } +} + +impl FillUniform for LWECiphertextCompressed { + fn fill_uniform(&mut self, source: &mut Source) { + self.data.fill_uniform(source); + } +} + +impl LWECiphertextCompressed> { + 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 Infos for LWECiphertextCompressed +where + VecZnx: ZnxInfos, +{ + type Inner = VecZnx; + + 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 SetMetaData for LWECiphertextCompressed { + 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 ReaderFrom for LWECiphertextCompressed { + fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { + self.k = reader.read_u64::()? as usize; + self.basek = reader.read_u64::()? as usize; + reader.read(&mut self.seed)?; + self.data.read_from(reader) + } +} + +impl WriterTo for LWECiphertextCompressed { + fn write_to(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::(self.k as u64)?; + writer.write_u64::(self.basek as u64)?; + writer.write_all(&self.seed)?; + self.data.write_to(writer) + } +} + +impl Decompress> for LWECiphertext { + fn decompress(&mut self, module: &Module, other: &LWECiphertextCompressed) + where + Module: 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]; + }); + } +} diff --git a/core/src/layouts/compressed/lwe_ksk.rs b/core/src/layouts/compressed/lwe_ksk.rs new file mode 100644 index 0000000..55b2c78 --- /dev/null +++ b/core/src/layouts/compressed/lwe_ksk.rs @@ -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(pub(crate) GGLWESwitchingKeyCompressed); + +impl fmt::Debug for LWESwitchingKeyCompressed { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl FillUniform for LWESwitchingKeyCompressed { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.0.fill_uniform(source); + } +} + +impl Reset for LWESwitchingKeyCompressed { + fn reset(&mut self) { + self.0.reset(); + } +} + +impl fmt::Display for LWESwitchingKeyCompressed { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(LWESwitchingKeyCompressed) {}", self.0) + } +} + +impl Infos for LWESwitchingKeyCompressed { + type Inner = MatZnx; + + fn inner(&self) -> &Self::Inner { + &self.0.inner() + } + + fn basek(&self) -> usize { + self.0.basek() + } + + fn k(&self) -> usize { + self.0.k() + } +} + +impl LWESwitchingKeyCompressed { + 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 ReaderFrom for LWESwitchingKeyCompressed { + fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { + self.0.read_from(reader) + } +} + +impl WriterTo for LWESwitchingKeyCompressed { + fn write_to(&self, writer: &mut W) -> std::io::Result<()> { + self.0.write_to(writer) + } +} + +impl LWESwitchingKeyCompressed> { + 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(module: &Module, n: usize, basek: usize, k: usize) -> usize + where + Module: GGLWEEncryptSkFamily + GLWESecretExecModuleFamily, + { + LWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k) + } +} + +impl Decompress> for LWESwitchingKey { + fn decompress(&mut self, module: &Module, other: &LWESwitchingKeyCompressed) + where + Module: crate::trait_families::DecompressFamily, + { + self.0.decompress(module, &other.0); + } +} diff --git a/core/src/layouts/compressed/lwe_to_glwe_ksk.rs b/core/src/layouts/compressed/lwe_to_glwe_ksk.rs new file mode 100644 index 0000000..2e0be41 --- /dev/null +++ b/core/src/layouts/compressed/lwe_to_glwe_ksk.rs @@ -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(pub(crate) GGLWESwitchingKeyCompressed); + +impl fmt::Debug for LWEToGLWESwitchingKeyCompressed { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl FillUniform for LWEToGLWESwitchingKeyCompressed { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.0.fill_uniform(source); + } +} + +impl Reset for LWEToGLWESwitchingKeyCompressed { + fn reset(&mut self) { + self.0.reset(); + } +} + +impl fmt::Display for LWEToGLWESwitchingKeyCompressed { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(LWEToGLWESwitchingKeyCompressed) {}", self.0) + } +} + +impl Infos for LWEToGLWESwitchingKeyCompressed { + type Inner = MatZnx; + + fn inner(&self) -> &Self::Inner { + &self.0.inner() + } + + fn basek(&self) -> usize { + self.0.basek() + } + + fn k(&self) -> usize { + self.0.k() + } +} + +impl LWEToGLWESwitchingKeyCompressed { + 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 ReaderFrom for LWEToGLWESwitchingKeyCompressed { + fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { + self.0.read_from(reader) + } +} + +impl WriterTo for LWEToGLWESwitchingKeyCompressed { + fn write_to(&self, writer: &mut W) -> std::io::Result<()> { + self.0.write_to(writer) + } +} + +impl LWEToGLWESwitchingKeyCompressed> { + 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(module: &Module, n: usize, basek: usize, k: usize, rank_out: usize) -> usize + where + Module: GGLWEEncryptSkFamily + GLWESecretExecModuleFamily, + { + LWEToGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank_out) + } +} + +impl Decompress> for LWEToGLWESwitchingKey { + fn decompress(&mut self, module: &Module, other: &LWEToGLWESwitchingKeyCompressed) + where + Module: crate::trait_families::DecompressFamily, + { + self.0.decompress(module, &other.0); + } +} diff --git a/core/src/layouts/compressed/mod.rs b/core/src/layouts/compressed/mod.rs new file mode 100644 index 0000000..cd7c459 --- /dev/null +++ b/core/src/layouts/compressed/mod.rs @@ -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::*; diff --git a/core/src/layouts/gglwe_atk.rs b/core/src/layouts/gglwe_atk.rs new file mode 100644 index 0000000..535eda0 --- /dev/null +++ b/core/src/layouts/gglwe_atk.rs @@ -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 { + pub(crate) key: GGLWESwitchingKey, + pub(crate) p: i64, +} + +impl fmt::Debug for GGLWEAutomorphismKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl FillUniform for GGLWEAutomorphismKey { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.key.fill_uniform(source); + } +} + +impl Reset for GGLWEAutomorphismKey +where + MatZnx: Reset, +{ + fn reset(&mut self) { + self.key.reset(); + self.p = 0; + } +} + +impl fmt::Display for GGLWEAutomorphismKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(AutomorphismKey: p={}) {}", self.p, self.key) + } +} + +impl GGLWEAutomorphismKey> { + 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 Infos for GGLWEAutomorphismKey { + type Inner = MatZnx; + + fn inner(&self) -> &Self::Inner { + &self.key.inner() + } + + fn basek(&self) -> usize { + self.key.basek() + } + + fn k(&self) -> usize { + self.key.k() + } +} + +impl GGLWEAutomorphismKey { + 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 GGLWEAutomorphismKey { + pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> { + self.key.at(row, col) + } +} + +impl GGLWEAutomorphismKey { + pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> { + self.key.at_mut(row, col) + } +} + +impl ReaderFrom for GGLWEAutomorphismKey { + fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { + self.p = reader.read_u64::()? as i64; + self.key.read_from(reader) + } +} + +impl WriterTo for GGLWEAutomorphismKey { + fn write_to(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::(self.p as u64)?; + self.key.write_to(writer) + } +} diff --git a/core/src/layouts/gglwe_ct.rs b/core/src/layouts/gglwe_ct.rs new file mode 100644 index 0000000..791e59b --- /dev/null +++ b/core/src/layouts/gglwe_ct.rs @@ -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 { + pub(crate) data: MatZnx, + pub(crate) basek: usize, + pub(crate) k: usize, + pub(crate) digits: usize, +} + +impl fmt::Debug for GGLWECiphertext { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl FillUniform for GGLWECiphertext { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.data.fill_uniform(source); + } +} + +impl Reset for GGLWECiphertext { + fn reset(&mut self) { + self.data.reset(); + self.basek = 0; + self.k = 0; + self.digits = 0; + } +} + +impl fmt::Display for GGLWECiphertext { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "(GGLWECiphertext: basek={} k={} digits={}) {}", + self.basek, self.k, self.digits, self.data + ) + } +} + +impl GGLWECiphertext { + pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> { + GLWECiphertext { + data: self.data.at(row, col), + basek: self.basek, + k: self.k, + } + } +} + +impl GGLWECiphertext { + 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> { + 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 Infos for GGLWECiphertext { + type Inner = MatZnx; + + fn inner(&self) -> &Self::Inner { + &self.data + } + + fn basek(&self) -> usize { + self.basek + } + + fn k(&self) -> usize { + self.k + } +} + +impl GGLWECiphertext { + 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 ReaderFrom for GGLWECiphertext { + fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { + self.k = reader.read_u64::()? as usize; + self.basek = reader.read_u64::()? as usize; + self.digits = reader.read_u64::()? as usize; + self.data.read_from(reader) + } +} + +impl WriterTo for GGLWECiphertext { + fn write_to(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::(self.k as u64)?; + writer.write_u64::(self.basek as u64)?; + writer.write_u64::(self.digits as u64)?; + self.data.write_to(writer) + } +} diff --git a/core/src/layouts/gglwe_ksk.rs b/core/src/layouts/gglwe_ksk.rs new file mode 100644 index 0000000..bce023b --- /dev/null +++ b/core/src/layouts/gglwe_ksk.rs @@ -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 { + pub(crate) key: GGLWECiphertext, + pub(crate) sk_in_n: usize, // Degree of sk_in + pub(crate) sk_out_n: usize, // Degree of sk_out +} + +impl fmt::Debug for GGLWESwitchingKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl fmt::Display for GGLWESwitchingKey { + 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 FillUniform for GGLWESwitchingKey { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.key.fill_uniform(source); + } +} + +impl Reset for GGLWESwitchingKey +where + MatZnx: Reset, +{ + fn reset(&mut self) { + self.key.reset(); + self.sk_in_n = 0; + self.sk_out_n = 0; + } +} + +impl GGLWESwitchingKey> { + 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::>::bytes_of(n, basek, k, rows, digits, rank_in, rank_out) + } +} + +impl Infos for GGLWESwitchingKey { + type Inner = MatZnx; + + fn inner(&self) -> &Self::Inner { + self.key.inner() + } + + fn basek(&self) -> usize { + self.key.basek() + } + + fn k(&self) -> usize { + self.key.k() + } +} + +impl GGLWESwitchingKey { + 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 GGLWESwitchingKey { + pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> { + self.key.at(row, col) + } +} + +impl GGLWESwitchingKey { + pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> { + self.key.at_mut(row, col) + } +} + +impl ReaderFrom for GGLWESwitchingKey { + fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { + self.sk_in_n = reader.read_u64::()? as usize; + self.sk_out_n = reader.read_u64::()? as usize; + self.key.read_from(reader) + } +} + +impl WriterTo for GGLWESwitchingKey { + fn write_to(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::(self.sk_in_n as u64)?; + writer.write_u64::(self.sk_out_n as u64)?; + self.key.write_to(writer) + } +} diff --git a/core/src/layouts/gglwe_tsk.rs b/core/src/layouts/gglwe_tsk.rs new file mode 100644 index 0000000..d092774 --- /dev/null +++ b/core/src/layouts/gglwe_tsk.rs @@ -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 { + pub(crate) keys: Vec>, +} + +impl fmt::Debug for GGLWETensorKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl FillUniform for GGLWETensorKey { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.keys + .iter_mut() + .for_each(|key: &mut GGLWESwitchingKey| key.fill_uniform(source)) + } +} + +impl Reset for GGLWETensorKey +where + MatZnx: Reset, +{ + fn reset(&mut self) { + self.keys + .iter_mut() + .for_each(|key: &mut GGLWESwitchingKey| key.reset()) + } +} + +impl fmt::Display for GGLWETensorKey { + 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> { + pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self { + let mut keys: Vec>> = 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::>::bytes_of(n, basek, k, rows, digits, 1, rank) + } +} + +impl Infos for GGLWETensorKey { + type Inner = MatZnx; + + 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 GGLWETensorKey { + 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 GGLWETensorKey { + // 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 { + 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 GGLWETensorKey { + // Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j]) + pub fn at(&self, mut i: usize, mut j: usize) -> &GGLWESwitchingKey { + 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 ReaderFrom for GGLWETensorKey { + fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { + let len: usize = reader.read_u64::()? 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 WriterTo for GGLWETensorKey { + fn write_to(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::(self.keys.len() as u64)?; + for key in &self.keys { + key.write_to(writer)?; + } + Ok(()) + } +} diff --git a/core/src/ggsw/layout.rs b/core/src/layouts/ggsw_ct.rs similarity index 93% rename from core/src/ggsw/layout.rs rename to core/src/layouts/ggsw_ct.rs index f4e1458..5927ec8 100644 --- a/core/src/ggsw/layout.rs +++ b/core/src/layouts/ggsw_ct.rs @@ -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 = VmpPMatAlloc + VmpPMatAllocBytes + VmpPMatPrepare; +use crate::layouts::{GLWECiphertext, Infos}; #[derive(PartialEq, Eq, Clone)] pub struct GGSWCiphertext { diff --git a/core/src/layouts/glwe_ct.rs b/core/src/layouts/glwe_ct.rs new file mode 100644 index 0000000..3d5828f --- /dev/null +++ b/core/src/layouts/glwe_ct.rs @@ -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 { + pub data: VecZnx, + pub basek: usize, + pub k: usize, +} + +impl fmt::Debug for GLWECiphertext { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl fmt::Display for GLWECiphertext { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "GLWECiphertext: basek={} k={}: {}", + self.basek(), + self.k(), + self.data + ) + } +} + +impl Reset for GLWECiphertext +where + VecZnx: Reset, +{ + fn reset(&mut self) { + self.data.reset(); + self.basek = 0; + self.k = 0; + } +} + +impl FillUniform for GLWECiphertext { + fn fill_uniform(&mut self, source: &mut Source) { + self.data.fill_uniform(source); + } +} + +impl GLWECiphertext> { + 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 Infos for GLWECiphertext { + type Inner = VecZnx; + + fn inner(&self) -> &Self::Inner { + &self.data + } + + fn basek(&self) -> usize { + self.basek + } + + fn k(&self) -> usize { + self.k + } +} + +impl GLWECiphertext { + pub fn rank(&self) -> usize { + self.cols() - 1 + } +} + +impl GLWECiphertext { + pub fn clone(&self) -> GLWECiphertext> { + GLWECiphertext { + data: self.data.clone(), + basek: self.basek(), + k: self.k(), + } + } +} + +impl SetMetaData for GLWECiphertext { + 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 GLWECiphertextToRef for GLWECiphertext { + 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 GLWECiphertextToMut for GLWECiphertext { + fn to_mut(&mut self) -> GLWECiphertext<&mut [u8]> { + GLWECiphertext { + data: self.data.to_mut(), + basek: self.basek, + k: self.k, + } + } +} + +impl ReaderFrom for GLWECiphertext { + fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { + self.k = reader.read_u64::()? as usize; + self.basek = reader.read_u64::()? as usize; + self.data.read_from(reader) + } +} + +impl WriterTo for GLWECiphertext { + fn write_to(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::(self.k as u64)?; + writer.write_u64::(self.basek as u64)?; + self.data.write_to(writer) + } +} diff --git a/core/src/layouts/glwe_pk.rs b/core/src/layouts/glwe_pk.rs new file mode 100644 index 0000000..92c0175 --- /dev/null +++ b/core/src/layouts/glwe_pk.rs @@ -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 { + pub(crate) data: VecZnx, + pub(crate) basek: usize, + pub(crate) k: usize, + pub(crate) dist: Distribution, +} + +impl GLWEPublicKey> { + 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 Infos for GLWEPublicKey { + type Inner = VecZnx; + + fn inner(&self) -> &Self::Inner { + &self.data + } + + fn basek(&self) -> usize { + self.basek + } + + fn k(&self) -> usize { + self.k + } +} + +impl GLWEPublicKey { + pub fn rank(&self) -> usize { + self.cols() - 1 + } +} + +impl ReaderFrom for GLWEPublicKey { + fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { + self.k = reader.read_u64::()? as usize; + self.basek = reader.read_u64::()? as usize; + match Distribution::read_from(reader) { + Ok(dist) => self.dist = dist, + Err(e) => return Err(e), + } + self.data.read_from(reader) + } +} + +impl WriterTo for GLWEPublicKey { + fn write_to(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_u64::(self.k as u64)?; + writer.write_u64::(self.basek as u64)?; + match self.dist.write_to(writer) { + Ok(()) => {} + Err(e) => return Err(e), + } + self.data.write_to(writer) + } +} diff --git a/core/src/glwe/plaintext.rs b/core/src/layouts/glwe_pt.rs similarity index 86% rename from core/src/glwe/plaintext.rs rename to core/src/layouts/glwe_pt.rs index 60754eb..e7724c8 100644 --- a/core/src/glwe/plaintext.rs +++ b/core/src/layouts/glwe_pt.rs @@ -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 { pub data: VecZnx, @@ -67,10 +67,3 @@ impl GLWECiphertextToMut for GLWEPlaintext { } } } - -impl GLWEOps for GLWEPlaintext -where - D: DataMut, - GLWEPlaintext: GLWECiphertextToMut + Infos + SetMetaData, -{ -} diff --git a/core/src/glwe/secret.rs b/core/src/layouts/glwe_sk.rs similarity index 59% rename from core/src/glwe/secret.rs rename to core/src/layouts/glwe_sk.rs index 90b4c72..399d098 100644 --- a/core/src/glwe/secret.rs +++ b/core/src/layouts/glwe_sk.rs @@ -1,13 +1,11 @@ use backend::hal::{ - api::{SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, ZnxInfos, ZnxZero}, - layouts::{Backend, Data, DataMut, DataRef, Module, ReaderFrom, ScalarZnx, SvpPPol, WriterTo}, + api::{ZnxInfos, ZnxZero}, + layouts::{Data, DataMut, DataRef, ReaderFrom, ScalarZnx, WriterTo}, }; use sampling::source::Source; use crate::dist::Distribution; -pub trait GLWESecretFamily = SvpPrepare + SvpPPolAllocBytes + SvpPPolAlloc; - #[derive(PartialEq, Eq, Clone)] pub struct GLWESecret { pub(crate) data: ScalarZnx, @@ -102,66 +100,3 @@ impl WriterTo for GLWESecret { self.data.write_to(writer) } } - -pub struct GLWESecretExec { - pub(crate) data: SvpPPol, - pub(crate) dist: Distribution, -} - -impl GLWESecretExec, B> { - pub fn alloc(module: &Module, n: usize, rank: usize) -> Self - where - Module: SvpPPolAlloc, - { - Self { - data: module.svp_ppol_alloc(n, rank), - dist: Distribution::NONE, - } - } - - pub fn bytes_of(module: &Module, n: usize, rank: usize) -> usize - where - Module: SvpPPolAllocBytes, - { - module.svp_ppol_alloc_bytes(n, rank) - } -} - -impl GLWESecretExec, B> { - pub fn from(module: &Module, sk: &GLWESecret) -> Self - where - D: DataRef, - Module: SvpPrepare + SvpPPolAlloc, - { - let mut sk_dft: GLWESecretExec, B> = Self::alloc(module, sk.n(), sk.rank()); - sk_dft.prepare(module, sk); - sk_dft - } -} - -impl GLWESecretExec { - 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 GLWESecretExec { - pub(crate) fn prepare(&mut self, module: &Module, sk: &GLWESecret) - where - O: DataRef, - Module: SvpPrepare, - { - (0..self.rank()).for_each(|i| { - module.svp_prepare(&mut self.data, i, &sk.data, i); - }); - self.dist = sk.dist - } -} diff --git a/core/src/layouts/glwe_to_lwe_ksk.rs b/core/src/layouts/glwe_to_lwe_ksk.rs new file mode 100644 index 0000000..7c22c1c --- /dev/null +++ b/core/src/layouts/glwe_to_lwe_ksk.rs @@ -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(pub(crate) GGLWESwitchingKey); + +impl fmt::Debug for GLWEToLWESwitchingKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl FillUniform for GLWEToLWESwitchingKey { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.0.fill_uniform(source); + } +} + +impl Reset for GLWEToLWESwitchingKey { + fn reset(&mut self) { + self.0.reset(); + } +} + +impl fmt::Display for GLWEToLWESwitchingKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(GLWEToLWESwitchingKey) {}", self.0) + } +} + +impl Infos for GLWEToLWESwitchingKey { + type Inner = MatZnx; + + fn inner(&self) -> &Self::Inner { + &self.0.inner() + } + + fn basek(&self) -> usize { + self.0.basek() + } + + fn k(&self) -> usize { + self.0.k() + } +} + +impl GLWEToLWESwitchingKey { + 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 ReaderFrom for GLWEToLWESwitchingKey { + fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { + self.0.read_from(reader) + } +} + +impl WriterTo for GLWEToLWESwitchingKey { + fn write_to(&self, writer: &mut W) -> std::io::Result<()> { + self.0.write_to(writer) + } +} + +impl GLWEToLWESwitchingKey> { + 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)) + } +} diff --git a/core/src/elem.rs b/core/src/layouts/infos.rs similarity index 82% rename from core/src/elem.rs rename to core/src/layouts/infos.rs index 3ba5499..6de038b 100644 --- a/core/src/elem.rs +++ b/core/src/layouts/infos.rs @@ -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 { - fn decompress(&mut self, module: &Module, other: &C) - where - Module: VecZnxFillUniform + VecZnxCopy; -} diff --git a/core/src/lwe/layouts.rs b/core/src/layouts/lwe_ct.rs similarity index 98% rename from core/src/lwe/layouts.rs rename to core/src/layouts/lwe_ct.rs index 2b0c773..c38b1a0 100644 --- a/core/src/lwe/layouts.rs +++ b/core/src/layouts/lwe_ct.rs @@ -6,8 +6,6 @@ use backend::hal::{ }; use sampling::source::Source; -use crate::{Infos, SetMetaData}; - #[derive(PartialEq, Eq, Clone)] pub struct LWECiphertext { pub(crate) data: VecZnx, @@ -127,6 +125,8 @@ impl LWECiphertextToMut for LWECiphertext { use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use crate::layouts::{Infos, SetMetaData}; + impl ReaderFrom for LWECiphertext { fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { self.k = reader.read_u64::()? as usize; diff --git a/core/src/layouts/lwe_ksk.rs b/core/src/layouts/lwe_ksk.rs new file mode 100644 index 0000000..5da7fb9 --- /dev/null +++ b/core/src/layouts/lwe_ksk.rs @@ -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(pub(crate) GGLWESwitchingKey); + +impl LWESwitchingKey> { + pub fn alloc(n: usize, basek: usize, k: usize, rows: usize) -> Self { + Self(GGLWESwitchingKey::alloc(n, basek, k, rows, 1, 1, 1)) + } +} + +impl fmt::Debug for LWESwitchingKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl FillUniform for LWESwitchingKey { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.0.fill_uniform(source); + } +} + +impl Reset for LWESwitchingKey { + fn reset(&mut self) { + self.0.reset(); + } +} + +impl fmt::Display for LWESwitchingKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(LWESwitchingKey) {}", self.0) + } +} + +impl Infos for LWESwitchingKey { + type Inner = MatZnx; + + fn inner(&self) -> &Self::Inner { + &self.0.inner() + } + + fn basek(&self) -> usize { + self.0.basek() + } + + fn k(&self) -> usize { + self.0.k() + } +} + +impl LWESwitchingKey { + 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 ReaderFrom for LWESwitchingKey { + fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { + self.0.read_from(reader) + } +} + +impl WriterTo for LWESwitchingKey { + fn write_to(&self, writer: &mut W) -> std::io::Result<()> { + self.0.write_to(writer) + } +} diff --git a/core/src/lwe/plaintext.rs b/core/src/layouts/lwe_pt.rs similarity index 97% rename from core/src/lwe/plaintext.rs rename to core/src/layouts/lwe_pt.rs index d5f1aa2..06e87ed 100644 --- a/core/src/lwe/plaintext.rs +++ b/core/src/layouts/lwe_pt.rs @@ -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 { pub(crate) data: VecZnx, diff --git a/core/src/lwe/secret.rs b/core/src/layouts/lwe_sk.rs similarity index 98% rename from core/src/lwe/secret.rs rename to core/src/layouts/lwe_sk.rs index 1c2c7c3..a2cb2fc 100644 --- a/core/src/lwe/secret.rs +++ b/core/src/layouts/lwe_sk.rs @@ -4,7 +4,7 @@ use backend::hal::{ }; use sampling::source::Source; -use crate::Distribution; +use crate::dist::Distribution; pub struct LWESecret { pub(crate) data: ScalarZnx, diff --git a/core/src/layouts/lwe_to_glwe_ksk.rs b/core/src/layouts/lwe_to_glwe_ksk.rs new file mode 100644 index 0000000..3e1fdbf --- /dev/null +++ b/core/src/layouts/lwe_to_glwe_ksk.rs @@ -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(pub(crate) GGLWESwitchingKey); + +impl fmt::Debug for LWEToGLWESwitchingKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl FillUniform for LWEToGLWESwitchingKey { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.0.fill_uniform(source); + } +} + +impl Reset for LWEToGLWESwitchingKey { + fn reset(&mut self) { + self.0.reset(); + } +} + +impl fmt::Display for LWEToGLWESwitchingKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(LWEToGLWESwitchingKey) {}", self.0) + } +} + +impl Infos for LWEToGLWESwitchingKey { + type Inner = MatZnx; + + fn inner(&self) -> &Self::Inner { + &self.0.inner() + } + + fn basek(&self) -> usize { + self.0.basek() + } + + fn k(&self) -> usize { + self.0.k() + } +} + +impl LWEToGLWESwitchingKey { + 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 ReaderFrom for LWEToGLWESwitchingKey { + fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { + self.0.read_from(reader) + } +} + +impl WriterTo for LWEToGLWESwitchingKey { + fn write_to(&self, writer: &mut W) -> std::io::Result<()> { + self.0.write_to(writer) + } +} + +impl LWEToGLWESwitchingKey> { + 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)) + } +} diff --git a/core/src/layouts/mod.rs b/core/src/layouts/mod.rs new file mode 100644 index 0000000..81b6936 --- /dev/null +++ b/core/src/layouts/mod.rs @@ -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::*; diff --git a/core/src/layouts/prepared/gglwe_atk.rs b/core/src/layouts/prepared/gglwe_atk.rs new file mode 100644 index 0000000..d0fea01 --- /dev/null +++ b/core/src/layouts/prepared/gglwe_atk.rs @@ -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 { + pub(crate) key: GGLWESwitchingKeyExec, + pub(crate) p: i64, +} + +impl GGLWEAutomorphismKeyExec, B> { + pub fn alloc(module: &Module, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self + where + Module: VmpPMatAlloc, + { + GGLWEAutomorphismKeyExec::, B> { + key: GGLWESwitchingKeyExec::alloc(module, n, basek, k, rows, digits, rank, rank), + p: 0, + } + } + + pub fn bytes_of(module: &Module, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize + where + Module: VmpPMatAllocBytes, + { + GGLWESwitchingKeyExec::bytes_of(module, n, basek, k, rows, digits, rank, rank) + } + + pub fn from(module: &Module, other: &GGLWEAutomorphismKey, scratch: &mut Scratch) -> Self + where + Module: VmpPMatAlloc + VmpPMatPrepare, + { + let mut atk_exec: GGLWEAutomorphismKeyExec, 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 Infos for GGLWEAutomorphismKeyExec { + type Inner = VmpPMat; + + fn inner(&self) -> &Self::Inner { + &self.key.inner() + } + + fn basek(&self) -> usize { + self.key.basek() + } + + fn k(&self) -> usize { + self.key.k() + } +} + +impl GGLWEAutomorphismKeyExec { + 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 GGLWEAutomorphismKeyExec { + pub fn prepare(&mut self, module: &Module, other: &GGLWEAutomorphismKey, scratch: &mut Scratch) + where + DataOther: DataRef, + Module: VmpPMatPrepare, + { + self.key.prepare(module, &other.key, scratch); + self.p = other.p; + } +} \ No newline at end of file diff --git a/core/src/layouts/prepared/gglwe_ct.rs b/core/src/layouts/prepared/gglwe_ct.rs new file mode 100644 index 0000000..aace85a --- /dev/null +++ b/core/src/layouts/prepared/gglwe_ct.rs @@ -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 { + pub(crate) data: VmpPMat, + pub(crate) basek: usize, + pub(crate) k: usize, + pub(crate) digits: usize, +} + +impl GGLWECiphertextExec, B> { + pub fn alloc( + module: &Module, + n: usize, + basek: usize, + k: usize, + rows: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + ) -> Self + where + Module: VmpPMatAlloc, + { + 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, + n: usize, + basek: usize, + k: usize, + rows: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + ) -> usize + where + Module: 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 Infos for GGLWECiphertextExec { + type Inner = VmpPMat; + + fn inner(&self) -> &Self::Inner { + &self.data + } + + fn basek(&self) -> usize { + self.basek + } + + fn k(&self) -> usize { + self.k + } +} + +impl GGLWECiphertextExec { + 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 GGLWECiphertextExec { + pub fn prepare(&mut self, module: &Module, other: &GGLWECiphertext, scratch: &mut Scratch) + where + DataOther: DataRef, + Module: VmpPMatPrepare, + { + module.vmp_prepare(&mut self.data, &other.data, scratch); + self.basek = other.basek; + self.k = other.k; + self.digits = other.digits; + } +} diff --git a/core/src/layouts/prepared/gglwe_ksk.rs b/core/src/layouts/prepared/gglwe_ksk.rs new file mode 100644 index 0000000..b28ab4e --- /dev/null +++ b/core/src/layouts/prepared/gglwe_ksk.rs @@ -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 { + pub(crate) key: GGLWECiphertextExec, + pub(crate) sk_in_n: usize, // Degree of sk_in + pub(crate) sk_out_n: usize, // Degree of sk_out +} + +impl GGLWESwitchingKeyExec, B> { + pub fn alloc( + module: &Module, + n: usize, + basek: usize, + k: usize, + rows: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + ) -> Self + where + Module: VmpPMatAlloc, + { + GGLWESwitchingKeyExec::, 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, + n: usize, + basek: usize, + k: usize, + rows: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + ) -> usize + where + Module: VmpPMatAllocBytes, + { + GGLWECiphertextExec::bytes_of(module, n, basek, k, rows, digits, rank_in, rank_out) + } + + pub fn from(module: &Module, other: &GGLWESwitchingKey, scratch: &mut Scratch) -> Self + where + Module: VmpPMatAlloc + VmpPMatPrepare, + { + let mut ksk_exec: GGLWESwitchingKeyExec, 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 Infos for GGLWESwitchingKeyExec { + type Inner = VmpPMat; + + fn inner(&self) -> &Self::Inner { + self.key.inner() + } + + fn basek(&self) -> usize { + self.key.basek() + } + + fn k(&self) -> usize { + self.key.k() + } +} + +impl GGLWESwitchingKeyExec { + 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 GGLWESwitchingKeyExec { + pub fn prepare(&mut self, module: &Module, other: &GGLWESwitchingKey, scratch: &mut Scratch) + where + DataOther: DataRef, + Module: VmpPMatPrepare, + { + self.key.prepare(module, &other.key, scratch); + self.sk_in_n = other.sk_in_n; + self.sk_out_n = other.sk_out_n; + } +} diff --git a/core/src/layouts/prepared/gglwe_tsk.rs b/core/src/layouts/prepared/gglwe_tsk.rs new file mode 100644 index 0000000..a1af02a --- /dev/null +++ b/core/src/layouts/prepared/gglwe_tsk.rs @@ -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 { + pub(crate) keys: Vec>, +} + +impl GGLWETensorKeyExec, B> { + pub fn alloc(module: &Module, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self + where + Module: VmpPMatAlloc, + { + let mut keys: Vec, 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, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize + where + Module: 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( + module: &Module, + other: &GGLWETensorKey, + scratch: &mut Scratch, + ) -> GGLWETensorKeyExec, B> + where + Module: VmpPMatAlloc + VmpPMatPrepare, + { + let mut tsk_exec: GGLWETensorKeyExec, 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 Infos for GGLWETensorKeyExec { + type Inner = VmpPMat; + + 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 GGLWETensorKeyExec { + 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 GGLWETensorKeyExec { + // 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 { + 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 GGLWETensorKeyExec { + // Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j]) + pub fn at(&self, mut i: usize, mut j: usize) -> &GGLWESwitchingKeyExec { + 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 GGLWETensorKeyExec { + pub fn prepare(&mut self, module: &Module, other: &GGLWETensorKey, scratch: &mut Scratch) + where + DataOther: DataRef, + Module: VmpPMatPrepare, + { + #[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); + }); + } +} diff --git a/core/src/ggsw/layout_exec.rs b/core/src/layouts/prepared/ggsw_ct.rs similarity index 93% rename from core/src/ggsw/layout_exec.rs rename to core/src/layouts/prepared/ggsw_ct.rs index d349f9c..b954e1e 100644 --- a/core/src/ggsw/layout_exec.rs +++ b/core/src/layouts/prepared/ggsw_ct.rs @@ -3,7 +3,7 @@ use backend::hal::{ layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}, }; -use crate::{GGSWCiphertext, GGSWLayoutFamily, Infos}; +use crate::layouts::{GGSWCiphertext, Infos}; #[derive(PartialEq, Eq)] pub struct GGSWCiphertextExec { @@ -16,7 +16,7 @@ pub struct GGSWCiphertextExec { impl GGSWCiphertextExec, B> { pub fn alloc(module: &Module, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self where - Module: GGSWLayoutFamily, + Module: VmpPMatAlloc, { let size: usize = k.div_ceil(basek); debug_assert!(digits > 0, "invalid ggsw: `digits` == 0"); @@ -46,7 +46,7 @@ impl GGSWCiphertextExec, B> { pub fn bytes_of(module: &Module, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize where - Module: GGSWLayoutFamily, + Module: VmpPMatAllocBytes, { let size: usize = k.div_ceil(basek); debug_assert!( @@ -73,7 +73,7 @@ impl GGSWCiphertextExec, B> { scratch: &mut Scratch, ) -> GGSWCiphertextExec, B> where - Module: GGSWLayoutFamily, + Module: VmpPMatAlloc + VmpPMatPrepare, { let mut ggsw_exec: GGSWCiphertextExec, B> = Self::alloc( module, @@ -119,7 +119,7 @@ impl GGSWCiphertextExec { pub fn prepare(&mut self, module: &Module, other: &GGSWCiphertext, scratch: &mut Scratch) where DataOther: DataRef, - Module: GGSWLayoutFamily, + Module: VmpPMatPrepare, { module.vmp_prepare(&mut self.data, &other.data, scratch); self.k = other.k; diff --git a/core/src/layouts/prepared/glwe_pk.rs b/core/src/layouts/prepared/glwe_pk.rs new file mode 100644 index 0000000..9e8088c --- /dev/null +++ b/core/src/layouts/prepared/glwe_pk.rs @@ -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 { + pub(crate) data: VecZnxDft, + pub(crate) basek: usize, + pub(crate) k: usize, + pub(crate) dist: Distribution, +} + +impl Infos for GLWEPublicKeyExec { + type Inner = VecZnxDft; + + fn inner(&self) -> &Self::Inner { + &self.data + } + + fn basek(&self) -> usize { + self.basek + } + + fn k(&self) -> usize { + self.k + } +} + +impl GLWEPublicKeyExec { + pub fn rank(&self) -> usize { + self.cols() - 1 + } +} + +impl GLWEPublicKeyExec, B> { + pub fn alloc(module: &Module, n: usize, basek: usize, k: usize, rank: usize) -> Self + where + Module: VecZnxDftAlloc, + { + 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, n: usize, basek: usize, k: usize, rank: usize) -> usize + where + Module: VecZnxDftAllocBytes, + { + module.vec_znx_dft_alloc_bytes(n, rank + 1, k.div_ceil(basek)) + } + + pub fn from(module: &Module, other: &GLWEPublicKey, scratch: &mut Scratch) -> Self + where + DataOther: DataRef, + Module: VecZnxDftAlloc + VecZnxDftFromVecZnx, + { + let mut pk_exec: GLWEPublicKeyExec, B> = + GLWEPublicKeyExec::alloc(module, other.n(), other.basek(), other.k(), other.rank()); + pk_exec.prepare(module, other, scratch); + pk_exec + } +} + +impl GLWEPublicKeyExec { + pub fn prepare(&mut self, module: &Module, other: &GLWEPublicKey, _scratch: &mut Scratch) + where + DataOther: DataRef, + Module: VecZnxDftFromVecZnx, + { + #[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; + } +} diff --git a/core/src/layouts/prepared/glwe_sk.rs b/core/src/layouts/prepared/glwe_sk.rs new file mode 100644 index 0000000..b495a92 --- /dev/null +++ b/core/src/layouts/prepared/glwe_sk.rs @@ -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 { + pub(crate) data: SvpPPol, + pub(crate) dist: Distribution, +} + +impl GLWESecretExec, B> { + pub fn alloc(module: &Module, n: usize, rank: usize) -> Self + where + Module: GLWESecretExecModuleFamily, + { + Self { + data: module.svp_ppol_alloc(n, rank), + dist: Distribution::NONE, + } + } + + pub fn bytes_of(module: &Module, n: usize, rank: usize) -> usize + where + Module: GLWESecretExecModuleFamily, + { + module.svp_ppol_alloc_bytes(n, rank) + } +} + +impl GLWESecretExec, B> { + pub fn from(module: &Module, sk: &GLWESecret) -> Self + where + D: DataRef, + Module: GLWESecretExecModuleFamily, + { + let mut sk_dft: GLWESecretExec, B> = Self::alloc(module, sk.n(), sk.rank()); + sk_dft.prepare(module, sk); + sk_dft + } +} + +impl GLWESecretExec { + 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 GLWESecretExec { + pub(crate) fn prepare(&mut self, module: &Module, sk: &GLWESecret) + where + O: DataRef, + Module: GLWESecretExecModuleFamily, + { + (0..self.rank()).for_each(|i| { + module.svp_prepare(&mut self.data, i, &sk.data, i); + }); + self.dist = sk.dist + } +} diff --git a/core/src/layouts/prepared/glwe_to_lwe_ksk.rs b/core/src/layouts/prepared/glwe_to_lwe_ksk.rs new file mode 100644 index 0000000..d1b7907 --- /dev/null +++ b/core/src/layouts/prepared/glwe_to_lwe_ksk.rs @@ -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(pub(crate) GGLWESwitchingKeyExec); + +impl Infos for GLWEToLWESwitchingKeyExec { + type Inner = VmpPMat; + + fn inner(&self) -> &Self::Inner { + &self.0.inner() + } + + fn basek(&self) -> usize { + self.0.basek() + } + + fn k(&self) -> usize { + self.0.k() + } +} + +impl GLWEToLWESwitchingKeyExec { + 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 GLWEToLWESwitchingKeyExec, B> { + pub fn alloc(module: &Module, n: usize, basek: usize, k: usize, rows: usize, rank_in: usize) -> Self + where + Module: VmpPMatAlloc, + { + Self(GGLWESwitchingKeyExec::alloc( + module, n, basek, k, rows, 1, rank_in, 1, + )) + } + + pub fn bytes_of(module: &Module, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize) -> usize + where + Module: VmpPMatAllocBytes, + { + GGLWESwitchingKeyExec::, B>::bytes_of(module, n, basek, k, rows, digits, rank_in, 1) + } + + pub fn from( + module: &Module, + other: &GLWEToLWESwitchingKey, + scratch: &mut Scratch, + ) -> Self + where + Module: VmpPMatAlloc + VmpPMatPrepare, + { + let mut ksk_exec: GLWEToLWESwitchingKeyExec, 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 GLWEToLWESwitchingKeyExec { + pub fn prepare(&mut self, module: &Module, other: &GLWEToLWESwitchingKey, scratch: &mut Scratch) + where + DataOther: DataRef, + Module: VmpPMatPrepare, + { + self.0.prepare(module, &other.0, scratch); + } +} diff --git a/core/src/layouts/prepared/lwe_ksk.rs b/core/src/layouts/prepared/lwe_ksk.rs new file mode 100644 index 0000000..ae6c14e --- /dev/null +++ b/core/src/layouts/prepared/lwe_ksk.rs @@ -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(pub(crate) GGLWESwitchingKeyExec); + +impl Infos for LWESwitchingKeyExec { + type Inner = VmpPMat; + + fn inner(&self) -> &Self::Inner { + &self.0.inner() + } + + fn basek(&self) -> usize { + self.0.basek() + } + + fn k(&self) -> usize { + self.0.k() + } +} + +impl LWESwitchingKeyExec { + 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 LWESwitchingKeyExec, B> { + pub fn alloc(module: &Module, n: usize, basek: usize, k: usize, rows: usize) -> Self + where + Module: VmpPMatAlloc, + { + Self(GGLWESwitchingKeyExec::alloc( + module, n, basek, k, rows, 1, 1, 1, + )) + } + + pub fn bytes_of(module: &Module, n: usize, basek: usize, k: usize, rows: usize, digits: usize) -> usize + where + Module: VmpPMatAllocBytes, + { + GGLWESwitchingKeyExec::, B>::bytes_of(module, n, basek, k, rows, digits, 1, 1) + } + + pub fn from(module: &Module, other: &LWESwitchingKey, scratch: &mut Scratch) -> Self + where + Module: VmpPMatAlloc + VmpPMatPrepare, + { + let mut ksk_exec: LWESwitchingKeyExec, 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 LWESwitchingKeyExec { + pub fn prepare(&mut self, module: &Module, other: &LWESwitchingKey, scratch: &mut Scratch) + where + DataOther: DataRef, + Module: VmpPMatPrepare, + { + self.0.prepare(module, &other.0, scratch); + } +} diff --git a/core/src/layouts/prepared/lwe_to_glwe_ksk.rs b/core/src/layouts/prepared/lwe_to_glwe_ksk.rs new file mode 100644 index 0000000..e4c1d52 --- /dev/null +++ b/core/src/layouts/prepared/lwe_to_glwe_ksk.rs @@ -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(pub(crate) GGLWESwitchingKeyExec); + +impl Infos for LWEToGLWESwitchingKeyExec { + type Inner = VmpPMat; + + fn inner(&self) -> &Self::Inner { + &self.0.inner() + } + + fn basek(&self) -> usize { + self.0.basek() + } + + fn k(&self) -> usize { + self.0.k() + } +} + +impl LWEToGLWESwitchingKeyExec { + 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 LWEToGLWESwitchingKeyExec, B> { + pub fn alloc(module: &Module, n: usize, basek: usize, k: usize, rows: usize, rank_out: usize) -> Self + where + Module: VmpPMatAlloc, + { + Self(GGLWESwitchingKeyExec::alloc( + module, n, basek, k, rows, 1, 1, rank_out, + )) + } + + pub fn bytes_of(module: &Module, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_out: usize) -> usize + where + Module: VmpPMatAllocBytes, + { + GGLWESwitchingKeyExec::, B>::bytes_of(module, n, basek, k, rows, digits, 1, rank_out) + } + + pub fn from( + module: &Module, + other: &LWEToGLWESwitchingKey, + scratch: &mut Scratch, + ) -> Self + where + Module: VmpPMatAlloc + VmpPMatPrepare, + { + let mut ksk_exec: LWEToGLWESwitchingKeyExec, 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 LWEToGLWESwitchingKeyExec { + pub fn prepare(&mut self, module: &Module, other: &LWEToGLWESwitchingKey, scratch: &mut Scratch) + where + DataOther: DataRef, + Module: VmpPMatPrepare, + { + self.0.prepare(module, &other.0, scratch); + } +} diff --git a/core/src/layouts/prepared/mod.rs b/core/src/layouts/prepared/mod.rs new file mode 100644 index 0000000..296144a --- /dev/null +++ b/core/src/layouts/prepared/mod.rs @@ -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::*; diff --git a/core/src/lib.rs b/core/src/lib.rs index 8e8389f..d06addc 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -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; diff --git a/core/src/lwe/conversion.rs b/core/src/lwe/conversion.rs deleted file mode 100644 index 1bcdd52..0000000 --- a/core/src/lwe/conversion.rs +++ /dev/null @@ -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> { - pub fn from_glwe_scratch_space( - module: &Module, - n: usize, - basek: usize, - k_lwe: usize, - k_glwe: usize, - k_ksk: usize, - rank: usize, - ) -> usize - where - Module: GLWEKeyswitchFamily, - { - 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( - module: &Module, - n: usize, - basek: usize, - k_lwe_out: usize, - k_lwe_in: usize, - k_ksk: usize, - ) -> usize - where - Module: GLWEKeyswitchFamily, - { - 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 LWECiphertext { - pub fn sample_extract(&mut self, a: &GLWECiphertext) { - #[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( - &mut self, - module: &Module, - a: &GLWECiphertext, - ks: &GLWEToLWESwitchingKeyExec, - scratch: &mut Scratch, - ) where - DGlwe: DataRef, - DKs: DataRef, - Module: GLWEKeyswitchFamily, - Scratch: TakeVecZnxDft + 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( - &mut self, - module: &Module, - a: &LWECiphertext, - ksk: &LWESwitchingKeyExec, - scratch: &mut Scratch, - ) where - A: DataRef, - DKs: DataRef, - Module: GLWEKeyswitchFamily, - Scratch: TakeVecZnxDft + 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> { - pub fn from_lwe_scratch_space( - module: &Module, - n: usize, - basek: usize, - k_lwe: usize, - k_glwe: usize, - k_ksk: usize, - rank: usize, - ) -> usize - where - Module: GLWEKeyswitchFamily, - { - 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 GLWECiphertext { - pub fn from_lwe( - &mut self, - module: &Module, - lwe: &LWECiphertext, - ksk: &LWEToGLWESwitchingKeyExec, - scratch: &mut Scratch, - ) where - DLwe: DataRef, - DKsk: DataRef, - Module: GLWEKeyswitchFamily, - Scratch: TakeVecZnxDft + 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); - } -} diff --git a/core/src/lwe/encryption.rs b/core/src/lwe/encryption.rs deleted file mode 100644 index 845b151..0000000 --- a/core/src/lwe/encryption.rs +++ /dev/null @@ -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 LWECiphertext { - pub fn encrypt_sk( - &mut self, - module: &Module, - pt: &LWEPlaintext, - sk: &LWESecret, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - ) where - DataPt: DataRef, - DataSk: DataRef, - Module: VecZnxFillUniform + VecZnxAddNormal + VecZnxNormalizeInplace, - B: ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl, - { - #[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> = 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::(); - }); - - (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::(); - }); - - 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::()).borrow(), - ); - - (0..self.size()).for_each(|i| { - self.data.at_mut(0, i)[0] = tmp_znx.at(0, i)[0]; - }); - } -} - -impl GLWEToLWESwitchingKey { - pub fn encrypt_sk( - &mut self, - module: &Module, - sk_lwe: &LWESecret, - sk_glwe: &GLWESecret, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) where - DLwe: DataRef, - DGlwe: DataRef, - Module: GGLWEEncryptSkFamily + VecZnxAutomorphismInplace + VecZnxSwithcDegree + VecZnxAddScalarInplace, - Scratch: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft + TakeGLWESecretExec + 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 LWEToGLWESwitchingKey { - pub fn encrypt_sk( - &mut self, - module: &Module, - sk_lwe: &LWESecret, - sk_glwe: &GLWESecret, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) where - DLwe: DataRef, - DGlwe: DataRef, - Module: GGLWEEncryptSkFamily + VecZnxAutomorphismInplace + VecZnxSwithcDegree + VecZnxAddScalarInplace, - Scratch: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft + TakeGLWESecretExec + 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 LWESwitchingKey { - pub fn encrypt_sk( - &mut self, - module: &Module, - sk_lwe_in: &LWESecret, - sk_lwe_out: &LWESecret, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) where - DIn: DataRef, - DOut: DataRef, - Module: GGLWEEncryptSkFamily + VecZnxAutomorphismInplace + VecZnxSwithcDegree + VecZnxAddScalarInplace, - Scratch: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft + TakeGLWESecretExec + 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, - ); - } -} diff --git a/core/src/lwe/keyswitch_layouts_exec.rs b/core/src/lwe/keyswitch_layouts_exec.rs deleted file mode 100644 index eb4faba..0000000 --- a/core/src/lwe/keyswitch_layouts_exec.rs +++ /dev/null @@ -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(pub(crate) GLWESwitchingKeyExec); - -impl Infos for GLWEToLWESwitchingKeyExec { - type Inner = VmpPMat; - - fn inner(&self) -> &Self::Inner { - &self.0.inner() - } - - fn basek(&self) -> usize { - self.0.basek() - } - - fn k(&self) -> usize { - self.0.k() - } -} - -impl GLWEToLWESwitchingKeyExec { - 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 GLWEToLWESwitchingKeyExec, B> { - pub fn alloc(module: &Module, n: usize, basek: usize, k: usize, rows: usize, rank_in: usize) -> Self - where - Module: GGLWEExecLayoutFamily, - { - Self(GLWESwitchingKeyExec::alloc( - module, n, basek, k, rows, 1, rank_in, 1, - )) - } - - pub fn bytes_of(module: &Module, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize) -> usize - where - Module: GGLWEExecLayoutFamily, - { - GLWESwitchingKeyExec::, B>::bytes_of(module, n, basek, k, rows, digits, rank_in, 1) - } - - pub fn from( - module: &Module, - other: &GLWEToLWESwitchingKey, - scratch: &mut Scratch, - ) -> Self - where - Module: GGLWEExecLayoutFamily, - { - let mut ksk_exec: GLWEToLWESwitchingKeyExec, 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 GLWEToLWESwitchingKeyExec { - pub fn prepare(&mut self, module: &Module, other: &GLWEToLWESwitchingKey, scratch: &mut Scratch) - where - DataOther: DataRef, - Module: GGLWEExecLayoutFamily, - { - 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(pub(crate) GLWESwitchingKeyExec); - -impl Infos for LWEToGLWESwitchingKeyExec { - type Inner = VmpPMat; - - fn inner(&self) -> &Self::Inner { - &self.0.inner() - } - - fn basek(&self) -> usize { - self.0.basek() - } - - fn k(&self) -> usize { - self.0.k() - } -} - -impl LWEToGLWESwitchingKeyExec { - 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 LWEToGLWESwitchingKeyExec, B> { - pub fn alloc(module: &Module, n: usize, basek: usize, k: usize, rows: usize, rank_out: usize) -> Self - where - Module: GGLWEExecLayoutFamily, - { - Self(GLWESwitchingKeyExec::alloc( - module, n, basek, k, rows, 1, 1, rank_out, - )) - } - - pub fn bytes_of(module: &Module, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_out: usize) -> usize - where - Module: GGLWEExecLayoutFamily, - { - GLWESwitchingKeyExec::, B>::bytes_of(module, n, basek, k, rows, digits, 1, rank_out) - } - - pub fn from( - module: &Module, - other: &LWEToGLWESwitchingKey, - scratch: &mut Scratch, - ) -> Self - where - Module: GGLWEExecLayoutFamily, - { - let mut ksk_exec: LWEToGLWESwitchingKeyExec, 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 LWEToGLWESwitchingKeyExec { - pub fn prepare(&mut self, module: &Module, other: &LWEToGLWESwitchingKey, scratch: &mut Scratch) - where - DataOther: DataRef, - Module: GGLWEExecLayoutFamily, - { - self.0.prepare(module, &other.0, scratch); - } -} - -#[derive(PartialEq, Eq)] -pub struct LWESwitchingKeyExec(pub(crate) GLWESwitchingKeyExec); - -impl Infos for LWESwitchingKeyExec { - type Inner = VmpPMat; - - fn inner(&self) -> &Self::Inner { - &self.0.inner() - } - - fn basek(&self) -> usize { - self.0.basek() - } - - fn k(&self) -> usize { - self.0.k() - } -} - -impl LWESwitchingKeyExec { - 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 LWESwitchingKeyExec, B> { - pub fn alloc(module: &Module, n: usize, basek: usize, k: usize, rows: usize) -> Self - where - Module: GGLWEExecLayoutFamily, - { - Self(GLWESwitchingKeyExec::alloc( - module, n, basek, k, rows, 1, 1, 1, - )) - } - - pub fn bytes_of(module: &Module, n: usize, basek: usize, k: usize, rows: usize, digits: usize) -> usize - where - Module: GGLWEExecLayoutFamily, - { - GLWESwitchingKeyExec::, B>::bytes_of(module, n, basek, k, rows, digits, 1, 1) - } - - pub fn from(module: &Module, other: &LWESwitchingKey, scratch: &mut Scratch) -> Self - where - Module: GGLWEExecLayoutFamily, - { - let mut ksk_exec: LWESwitchingKeyExec, 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 LWESwitchingKeyExec { - pub fn prepare(&mut self, module: &Module, other: &LWESwitchingKey, scratch: &mut Scratch) - where - DataOther: DataRef, - Module: GGLWEExecLayoutFamily, - { - self.0.prepare(module, &other.0, scratch); - } -} diff --git a/core/src/lwe/keyswtich_layouts.rs b/core/src/lwe/keyswtich_layouts.rs deleted file mode 100644 index c602097..0000000 --- a/core/src/lwe/keyswtich_layouts.rs +++ /dev/null @@ -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(pub(crate) GLWESwitchingKey); - -impl fmt::Debug for GLWEToLWESwitchingKey { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl FillUniform for GLWEToLWESwitchingKey { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.0.fill_uniform(source); - } -} - -impl Reset for GLWEToLWESwitchingKey { - fn reset(&mut self) { - self.0.reset(); - } -} - -impl fmt::Display for GLWEToLWESwitchingKey { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "(GLWEToLWESwitchingKey) {}", self.0) - } -} - -impl Infos for GLWEToLWESwitchingKey { - type Inner = MatZnx; - - fn inner(&self) -> &Self::Inner { - &self.0.inner() - } - - fn basek(&self) -> usize { - self.0.basek() - } - - fn k(&self) -> usize { - self.0.k() - } -} - -impl GLWEToLWESwitchingKey { - 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 ReaderFrom for GLWEToLWESwitchingKey { - fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { - self.0.read_from(reader) - } -} - -impl WriterTo for GLWEToLWESwitchingKey { - fn write_to(&self, writer: &mut W) -> std::io::Result<()> { - self.0.write_to(writer) - } -} - -impl GLWEToLWESwitchingKey> { - 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(module: &Module, n: usize, basek: usize, k: usize, rank_in: usize) -> usize - where - Module: GGLWEEncryptSkFamily, - { - 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(pub(crate) GLWESwitchingKey); - -impl fmt::Debug for LWEToGLWESwitchingKey { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl FillUniform for LWEToGLWESwitchingKey { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.0.fill_uniform(source); - } -} - -impl Reset for LWEToGLWESwitchingKey { - fn reset(&mut self) { - self.0.reset(); - } -} - -impl fmt::Display for LWEToGLWESwitchingKey { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "(LWEToGLWESwitchingKey) {}", self.0) - } -} - -impl Infos for LWEToGLWESwitchingKey { - type Inner = MatZnx; - - fn inner(&self) -> &Self::Inner { - &self.0.inner() - } - - fn basek(&self) -> usize { - self.0.basek() - } - - fn k(&self) -> usize { - self.0.k() - } -} - -impl LWEToGLWESwitchingKey { - 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 ReaderFrom for LWEToGLWESwitchingKey { - fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { - self.0.read_from(reader) - } -} - -impl WriterTo for LWEToGLWESwitchingKey { - fn write_to(&self, writer: &mut W) -> std::io::Result<()> { - self.0.write_to(writer) - } -} - -impl LWEToGLWESwitchingKey> { - 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(module: &Module, n: usize, basek: usize, k: usize, rank_out: usize) -> usize - where - Module: GGLWEEncryptSkFamily, - { - GLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, 1, rank_out) + GLWESecret::bytes_of(n, 1) - } -} - -#[derive(PartialEq, Eq, Clone)] -pub struct LWESwitchingKey(pub(crate) GLWESwitchingKey); - -impl fmt::Debug for LWESwitchingKey { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl FillUniform for LWESwitchingKey { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.0.fill_uniform(source); - } -} - -impl Reset for LWESwitchingKey { - fn reset(&mut self) { - self.0.reset(); - } -} - -impl fmt::Display for LWESwitchingKey { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "(LWESwitchingKey) {}", self.0) - } -} - -impl Infos for LWESwitchingKey { - type Inner = MatZnx; - - fn inner(&self) -> &Self::Inner { - &self.0.inner() - } - - fn basek(&self) -> usize { - self.0.basek() - } - - fn k(&self) -> usize { - self.0.k() - } -} - -impl LWESwitchingKey { - 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 ReaderFrom for LWESwitchingKey { - fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { - self.0.read_from(reader) - } -} - -impl WriterTo for LWESwitchingKey { - fn write_to(&self, writer: &mut W) -> std::io::Result<()> { - self.0.write_to(writer) - } -} - -impl LWESwitchingKey> { - 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(module: &Module, n: usize, basek: usize, k: usize) -> usize - where - Module: GGLWEEncryptSkFamily, - { - GLWESecret::bytes_of(n, 1) - + GLWESecretExec::bytes_of(module, n, 1) - + GLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, 1, 1) - } -} diff --git a/core/src/lwe/layouts_compressed.rs b/core/src/lwe/layouts_compressed.rs deleted file mode 100644 index 975d621..0000000 --- a/core/src/lwe/layouts_compressed.rs +++ /dev/null @@ -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 { - pub(crate) data: VecZnx, - pub(crate) k: usize, - pub(crate) basek: usize, - pub(crate) seed: [u8; 32], -} - -impl fmt::Debug for LWECiphertextCompressed { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl fmt::Display for LWECiphertextCompressed { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "LWECiphertextCompressed: basek={} k={} seed={:?}: {}", - self.basek(), - self.k(), - self.seed, - self.data - ) - } -} - -impl Reset for LWECiphertextCompressed -where - VecZnx: Reset, -{ - fn reset(&mut self) { - self.data.reset(); - self.basek = 0; - self.k = 0; - self.seed = [0u8; 32]; - } -} - -impl FillUniform for LWECiphertextCompressed { - fn fill_uniform(&mut self, source: &mut Source) { - self.data.fill_uniform(source); - } -} - -impl LWECiphertextCompressed> { - 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 Infos for LWECiphertextCompressed -where - VecZnx: ZnxInfos, -{ - type Inner = VecZnx; - - 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 SetMetaData for LWECiphertextCompressed { - 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 ReaderFrom for LWECiphertextCompressed { - fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { - self.k = reader.read_u64::()? as usize; - self.basek = reader.read_u64::()? as usize; - reader.read(&mut self.seed)?; - self.data.read_from(reader) - } -} - -impl WriterTo for LWECiphertextCompressed { - fn write_to(&self, writer: &mut W) -> std::io::Result<()> { - writer.write_u64::(self.k as u64)?; - writer.write_u64::(self.basek as u64)?; - writer.write_all(&self.seed)?; - self.data.write_to(writer) - } -} - -impl Decompress> for LWECiphertext { - fn decompress(&mut self, module: &Module, other: &LWECiphertextCompressed) - where - Module: 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(pub(crate) GLWESwitchingKeyCompressed); - -impl fmt::Debug for GLWEToLWESwitchingKeyCompressed { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl FillUniform for GLWEToLWESwitchingKeyCompressed { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.0.fill_uniform(source); - } -} - -impl Reset for GLWEToLWESwitchingKeyCompressed { - fn reset(&mut self) { - self.0.reset(); - } -} - -impl fmt::Display for GLWEToLWESwitchingKeyCompressed { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "(GLWEToLWESwitchingKeyCompressed) {}", self.0) - } -} - -impl Infos for GLWEToLWESwitchingKeyCompressed { - type Inner = MatZnx; - - fn inner(&self) -> &Self::Inner { - &self.0.inner() - } - - fn basek(&self) -> usize { - self.0.basek() - } - - fn k(&self) -> usize { - self.0.k() - } -} - -impl GLWEToLWESwitchingKeyCompressed { - 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 ReaderFrom for GLWEToLWESwitchingKeyCompressed { - fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { - self.0.read_from(reader) - } -} - -impl WriterTo for GLWEToLWESwitchingKeyCompressed { - fn write_to(&self, writer: &mut W) -> std::io::Result<()> { - self.0.write_to(writer) - } -} - -impl GLWEToLWESwitchingKeyCompressed> { - 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(module: &Module, n: usize, basek: usize, k: usize, rank_in: usize) -> usize - where - Module: GGLWEEncryptSkFamily, - { - GLWEToLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank_in) - } -} - -#[derive(PartialEq, Eq, Clone)] -pub struct LWEToGLWESwitchingKeyCompressed(pub(crate) GLWESwitchingKeyCompressed); - -impl fmt::Debug for LWEToGLWESwitchingKeyCompressed { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl FillUniform for LWEToGLWESwitchingKeyCompressed { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.0.fill_uniform(source); - } -} - -impl Reset for LWEToGLWESwitchingKeyCompressed { - fn reset(&mut self) { - self.0.reset(); - } -} - -impl fmt::Display for LWEToGLWESwitchingKeyCompressed { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "(LWEToGLWESwitchingKeyCompressed) {}", self.0) - } -} - -impl Infos for LWEToGLWESwitchingKeyCompressed { - type Inner = MatZnx; - - fn inner(&self) -> &Self::Inner { - &self.0.inner() - } - - fn basek(&self) -> usize { - self.0.basek() - } - - fn k(&self) -> usize { - self.0.k() - } -} - -impl LWEToGLWESwitchingKeyCompressed { - 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 ReaderFrom for LWEToGLWESwitchingKeyCompressed { - fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { - self.0.read_from(reader) - } -} - -impl WriterTo for LWEToGLWESwitchingKeyCompressed { - fn write_to(&self, writer: &mut W) -> std::io::Result<()> { - self.0.write_to(writer) - } -} - -impl LWEToGLWESwitchingKeyCompressed> { - 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(module: &Module, n: usize, basek: usize, k: usize, rank_out: usize) -> usize - where - Module: GGLWEEncryptSkFamily, - { - LWEToGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank_out) - } -} - -#[derive(PartialEq, Eq, Clone)] -pub struct LWESwitchingKeyCompressed(pub(crate) GLWESwitchingKeyCompressed); - -impl fmt::Debug for LWESwitchingKeyCompressed { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl FillUniform for LWESwitchingKeyCompressed { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.0.fill_uniform(source); - } -} - -impl Reset for LWESwitchingKeyCompressed { - fn reset(&mut self) { - self.0.reset(); - } -} - -impl fmt::Display for LWESwitchingKeyCompressed { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "(LWESwitchingKeyCompressed) {}", self.0) - } -} - -impl Infos for LWESwitchingKeyCompressed { - type Inner = MatZnx; - - fn inner(&self) -> &Self::Inner { - &self.0.inner() - } - - fn basek(&self) -> usize { - self.0.basek() - } - - fn k(&self) -> usize { - self.0.k() - } -} - -impl LWESwitchingKeyCompressed { - 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 ReaderFrom for LWESwitchingKeyCompressed { - fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { - self.0.read_from(reader) - } -} - -impl WriterTo for LWESwitchingKeyCompressed { - fn write_to(&self, writer: &mut W) -> std::io::Result<()> { - self.0.write_to(writer) - } -} - -impl LWESwitchingKeyCompressed> { - 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(module: &Module, n: usize, basek: usize, k: usize) -> usize - where - Module: GGLWEEncryptSkFamily, - { - LWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k) - } -} diff --git a/core/src/lwe/mod.rs b/core/src/lwe/mod.rs deleted file mode 100644 index 0f91f3c..0000000 --- a/core/src/lwe/mod.rs +++ /dev/null @@ -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; diff --git a/core/src/lwe/tests/cpu_spqlios/mod.rs b/core/src/lwe/tests/cpu_spqlios/mod.rs deleted file mode 100644 index aebaafb..0000000 --- a/core/src/lwe/tests/cpu_spqlios/mod.rs +++ /dev/null @@ -1 +0,0 @@ -mod fft64; diff --git a/core/src/lwe/tests/generic_serialization.rs b/core/src/lwe/tests/generic_serialization.rs deleted file mode 100644 index 74a7636..0000000 --- a/core/src/lwe/tests/generic_serialization.rs +++ /dev/null @@ -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> = LWECiphertext::alloc(771, 12, 54); - test_reader_writer_interface(original); -} - -#[test] -fn lwe_compressed_serialization() { - let original: LWECiphertextCompressed> = LWECiphertextCompressed::alloc(12, 54); - test_reader_writer_interface(original); -} - -#[test] -fn glwe_to_lwe_switching_key_serialization() { - let original: GLWEToLWESwitchingKey> = GLWEToLWESwitchingKey::alloc(1024, 12, 54, 2, 2); - test_reader_writer_interface(original); -} - -#[test] -fn glwe_to_lwe_switching_key_compressed_serialization() { - let original: GLWEToLWESwitchingKeyCompressed> = GLWEToLWESwitchingKeyCompressed::alloc(1024, 12, 54, 2, 2); - test_reader_writer_interface(original); -} - -#[test] -fn lwe_to_glwe_switching_key_serialization() { - let original: LWEToGLWESwitchingKey> = LWEToGLWESwitchingKey::alloc(1024, 12, 54, 2, 2); - test_reader_writer_interface(original); -} - -#[test] -fn lwe_to_glwe_switching_key_compressed_serialization() { - let original: LWEToGLWESwitchingKeyCompressed> = LWEToGLWESwitchingKeyCompressed::alloc(1024, 12, 54, 2, 2); - test_reader_writer_interface(original); -} - -#[test] -fn lwe_switching_key_serialization() { - let original: LWESwitchingKey> = LWESwitchingKey::alloc(1024, 12, 54, 2); - test_reader_writer_interface(original); -} - -#[test] -fn lwe_switching_key_compressed_serialization() { - let original: LWESwitchingKeyCompressed> = LWESwitchingKeyCompressed::alloc(1024, 12, 54, 2); - test_reader_writer_interface(original); -} diff --git a/core/src/lwe/tests/mod.rs b/core/src/lwe/tests/mod.rs deleted file mode 100644 index 465f959..0000000 --- a/core/src/lwe/tests/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -mod generic_conversion; -mod generic_serialization; - -mod cpu_spqlios; diff --git a/core/src/gglwe/noise.rs b/core/src/noise/gglwe_ct.rs similarity index 92% rename from core/src/gglwe/noise.rs rename to core/src/noise/gglwe_ct.rs index b46cca7..41ab645 100644 --- a/core/src/gglwe/noise.rs +++ b/core/src/noise/gglwe_ct.rs @@ -4,7 +4,10 @@ use backend::hal::{ 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 GGLWECiphertext { pub fn assert_noise( diff --git a/core/src/ggsw/noise.rs b/core/src/noise/ggsw_ct.rs similarity index 90% rename from core/src/ggsw/noise.rs rename to core/src/noise/ggsw_ct.rs index c8c7148..34526f5 100644 --- a/core/src/ggsw/noise.rs +++ b/core/src/noise/ggsw_ct.rs @@ -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 = GLWEDecryptFamily - + VecZnxBigAlloc - + VecZnxDftAlloc - + VecZnxBigNormalizeTmpBytes - + VecZnxBigNormalize - + VecZnxDftToVecZnxBigTmpA; +use crate::{ + layouts::{GGSWCiphertext, GLWECiphertext, GLWEPlaintext, Infos, prepared::GLWESecretExec}, + trait_families::GGSWAssertNoiseFamily, +}; impl GGSWCiphertext { pub fn assert_noise( diff --git a/core/src/glwe/noise.rs b/core/src/noise/glwe_ct.rs similarity index 90% rename from core/src/glwe/noise.rs rename to core/src/noise/glwe_ct.rs index d02c63a..8c97e06 100644 --- a/core/src/glwe/noise.rs +++ b/core/src/noise/glwe_ct.rs @@ -4,7 +4,12 @@ use backend::hal::{ 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 GLWECiphertext { pub fn assert_noise( diff --git a/core/src/noise.rs b/core/src/noise/mod.rs similarity index 98% rename from core/src/noise.rs rename to core/src/noise/mod.rs index e6901ac..54ffab0 100644 --- a/core/src/noise.rs +++ b/core/src/noise/mod.rs @@ -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, diff --git a/core/src/glwe/ops.rs b/core/src/operations/glwe.rs similarity index 95% rename from core/src/glwe/ops.rs rename to core/src/operations/glwe.rs index 89c833c..0c115b6 100644 --- a/core/src/glwe/ops.rs +++ b/core/src/operations/glwe.rs @@ -4,12 +4,21 @@ use backend::hal::{ 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}; -pub trait GLWEOps: GLWECiphertextToMut + SetMetaData + Sized { +impl GLWEOperations for GLWEPlaintext +where + D: DataMut, + GLWEPlaintext: GLWECiphertextToMut + Infos + SetMetaData, +{ +} + +impl GLWEOperations for GLWECiphertext where GLWECiphertext: GLWECiphertextToMut + Infos + SetMetaData {} + +pub trait GLWEOperations: GLWECiphertextToMut + SetMetaData + Sized { fn add(&mut self, module: &Module, a: &A, b: &B) where A: GLWECiphertextToRef, diff --git a/core/src/operations/mod.rs b/core/src/operations/mod.rs new file mode 100644 index 0000000..3b2432e --- /dev/null +++ b/core/src/operations/mod.rs @@ -0,0 +1,3 @@ +mod glwe; + +pub use glwe::*; diff --git a/core/src/scratch.rs b/core/src/scratch.rs index 12e42c0..47da6fb 100644 --- a/core/src/scratch.rs +++ b/core/src/scratch.rs @@ -5,9 +5,15 @@ use backend::hal::{ }; 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 @@ pub trait TakeGLWESwitchingKey { digits: usize, rank_in: usize, rank_out: usize, - ) -> (GLWESwitchingKey<&mut [u8]>, &mut Self); + ) -> (GGLWESwitchingKey<&mut [u8]>, &mut Self); } pub trait TakeGLWESwitchingKeyExec { @@ -129,7 +135,7 @@ pub trait TakeGLWESwitchingKeyExec { digits: usize, rank_in: usize, rank_out: usize, - ) -> (GLWESwitchingKeyExec<&mut [u8], B>, &mut Self); + ) -> (GGLWESwitchingKeyExec<&mut [u8], B>, &mut Self); } pub trait TakeTensorKey { @@ -141,7 +147,7 @@ pub trait TakeTensorKey { rows: usize, digits: usize, rank: usize, - ) -> (GLWETensorKey<&mut [u8]>, &mut Self); + ) -> (GGLWETensorKey<&mut [u8]>, &mut Self); } pub trait TakeTensorKeyExec { @@ -153,7 +159,7 @@ pub trait TakeTensorKeyExec { rows: usize, digits: usize, rank: usize, - ) -> (GLWETensorKeyExec<&mut [u8], B>, &mut Self); + ) -> (GGLWETensorKeyExec<&mut [u8], B>, &mut Self); } pub trait TakeAutomorphismKey { @@ -165,7 +171,7 @@ pub trait TakeAutomorphismKey { rows: usize, digits: usize, rank: usize, - ) -> (AutomorphismKey<&mut [u8]>, &mut Self); + ) -> (GGLWEAutomorphismKey<&mut [u8]>, &mut Self); } pub trait TakeAutomorphismKeyExec { @@ -177,7 +183,7 @@ pub trait TakeAutomorphismKeyExec { rows: usize, digits: usize, rank: usize, - ) -> (AutomorphismKeyExec<&mut [u8], B>, &mut Self); + ) -> (GGLWEAutomorphismKeyExec<&mut [u8], B>, &mut Self); } impl TakeGLWECt for Scratch @@ -672,10 +678,10 @@ where 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 @@ where } } -impl<'a, B, D> TakeLike<'a, B, GLWESwitchingKey> for Scratch +impl<'a, B, D> TakeLike<'a, B, GGLWESwitchingKey> for Scratch where Scratch: TakeLike<'a, B, GGLWECiphertext, Output = GGLWECiphertext<&'a mut [u8]>>, B: Backend + TakeMatZnxImpl, D: DataRef, { - type Output = GLWESwitchingKey<&'a mut [u8]>; + type Output = GGLWESwitchingKey<&'a mut [u8]>; - fn take_like(&'a mut self, template: &GLWESwitchingKey) -> (Self::Output, &'a mut Self) { + fn take_like(&'a mut self, template: &GGLWESwitchingKey) -> (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 @@ where 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 @@ where } } -impl<'a, B, D> TakeLike<'a, B, GLWESwitchingKeyExec> for Scratch +impl<'a, B, D> TakeLike<'a, B, GGLWESwitchingKeyExec> for Scratch where Scratch: TakeLike<'a, B, GGLWECiphertextExec, Output = GGLWECiphertextExec<&'a mut [u8], B>>, B: Backend + TakeMatZnxImpl, D: DataRef, { - type Output = GLWESwitchingKeyExec<&'a mut [u8], B>; + type Output = GGLWESwitchingKeyExec<&'a mut [u8], B>; - fn take_like(&'a mut self, template: &GLWESwitchingKeyExec) -> (Self::Output, &'a mut Self) { + fn take_like(&'a mut self, template: &GGLWESwitchingKeyExec) -> (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 @@ where 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> for Scratch +impl<'a, B, D> TakeLike<'a, B, GGLWEAutomorphismKey> for Scratch where - Scratch: TakeLike<'a, B, GLWESwitchingKey, Output = GLWESwitchingKey<&'a mut [u8]>>, + Scratch: TakeLike<'a, B, GGLWESwitchingKey, Output = GGLWESwitchingKey<&'a mut [u8]>>, B: Backend + TakeMatZnxImpl, D: DataRef, { - type Output = AutomorphismKey<&'a mut [u8]>; + type Output = GGLWEAutomorphismKey<&'a mut [u8]>; - fn take_like(&'a mut self, template: &AutomorphismKey) -> (Self::Output, &'a mut Self) { + fn take_like(&'a mut self, template: &GGLWEAutomorphismKey) -> (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 @@ where 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> for Scratch +impl<'a, B, D> TakeLike<'a, B, GGLWEAutomorphismKeyExec> for Scratch where - Scratch: TakeLike<'a, B, GLWESwitchingKeyExec, Output = GLWESwitchingKeyExec<&'a mut [u8], B>>, + Scratch: TakeLike<'a, B, GGLWESwitchingKeyExec, Output = GGLWESwitchingKeyExec<&'a mut [u8], B>>, B: Backend + TakeMatZnxImpl, D: DataRef, { - type Output = AutomorphismKeyExec<&'a mut [u8], B>; + type Output = GGLWEAutomorphismKeyExec<&'a mut [u8], B>; - fn take_like(&'a mut self, template: &AutomorphismKeyExec) -> (Self::Output, &'a mut Self) { + fn take_like(&'a mut self, template: &GGLWEAutomorphismKeyExec) -> (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 @@ where rows: usize, digits: usize, rank: usize, - ) -> (GLWETensorKey<&mut [u8]>, &mut Self) { - let mut keys: Vec> = Vec::new(); + ) -> (GGLWETensorKey<&mut [u8]>, &mut Self) { + let mut keys: Vec> = Vec::new(); let pairs: usize = (((rank + 1) * rank) >> 1).max(1); let mut scratch: &mut Scratch = self; @@ -845,20 +851,20 @@ where scratch = s; keys.push(gglwe); } - (GLWETensorKey { keys }, scratch) + (GGLWETensorKey { keys }, scratch) } } -impl<'a, B, D> TakeLike<'a, B, GLWETensorKey> for Scratch +impl<'a, B, D> TakeLike<'a, B, GGLWETensorKey> for Scratch where - Scratch: TakeLike<'a, B, GLWESwitchingKey, Output = GLWESwitchingKey<&'a mut [u8]>>, + Scratch: TakeLike<'a, B, GGLWESwitchingKey, Output = GGLWESwitchingKey<&'a mut [u8]>>, B: Backend + TakeMatZnxImpl, D: DataRef, { - type Output = GLWETensorKey<&'a mut [u8]>; + type Output = GGLWETensorKey<&'a mut [u8]>; - fn take_like(&'a mut self, template: &GLWETensorKey) -> (Self::Output, &'a mut Self) { - let mut keys: Vec> = Vec::new(); + fn take_like(&'a mut self, template: &GGLWETensorKey) -> (Self::Output, &'a mut Self) { + let mut keys: Vec> = Vec::new(); let pairs: usize = template.keys.len(); let mut scratch: &mut Scratch = self; @@ -874,7 +880,7 @@ where keys.push(gglwe); } - (GLWETensorKey { keys }, scratch) + (GGLWETensorKey { keys }, scratch) } } @@ -890,8 +896,8 @@ where rows: usize, digits: usize, rank: usize, - ) -> (GLWETensorKeyExec<&mut [u8], B>, &mut Self) { - let mut keys: Vec> = Vec::new(); + ) -> (GGLWETensorKeyExec<&mut [u8], B>, &mut Self) { + let mut keys: Vec> = Vec::new(); let pairs: usize = (((rank + 1) * rank) >> 1).max(1); let mut scratch: &mut Scratch = self; @@ -906,20 +912,20 @@ where scratch = s; keys.push(gglwe); } - (GLWETensorKeyExec { keys }, scratch) + (GGLWETensorKeyExec { keys }, scratch) } } -impl<'a, B, D> TakeLike<'a, B, GLWETensorKeyExec> for Scratch +impl<'a, B, D> TakeLike<'a, B, GGLWETensorKeyExec> for Scratch where - Scratch: TakeLike<'a, B, GLWESwitchingKeyExec, Output = GLWESwitchingKeyExec<&'a mut [u8], B>>, + Scratch: TakeLike<'a, B, GGLWESwitchingKeyExec, Output = GGLWESwitchingKeyExec<&'a mut [u8], B>>, B: Backend + TakeMatZnxImpl, D: DataRef, { - type Output = GLWETensorKeyExec<&'a mut [u8], B>; + type Output = GGLWETensorKeyExec<&'a mut [u8], B>; - fn take_like(&'a mut self, template: &GLWETensorKeyExec) -> (Self::Output, &'a mut Self) { - let mut keys: Vec> = Vec::new(); + fn take_like(&'a mut self, template: &GGLWETensorKeyExec) -> (Self::Output, &'a mut Self) { + let mut keys: Vec> = Vec::new(); let pairs: usize = template.keys.len(); let mut scratch: &mut Scratch = self; @@ -935,6 +941,6 @@ where keys.push(gglwe); } - (GLWETensorKeyExec { keys }, scratch) + (GGLWETensorKeyExec { keys }, scratch) } } diff --git a/core/src/gglwe/tests/generics_automorphism_key.rs b/core/src/tests/generics/automorphism/gglwe_atk.rs similarity index 52% rename from core/src/gglwe/tests/generics_automorphism_key.rs rename to core/src/tests/generics/automorphism/gglwe_atk.rs index 208d79b..7ebde3f 100644 --- a/core/src/gglwe/tests/generics_automorphism_key.rs +++ b/core/src/tests/generics/automorphism/gglwe_atk.rs @@ -1,7 +1,7 @@ use backend::hal::{ api::{ ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxCopy, - VecZnxStd, VecZnxSubScalarInplace, VecZnxSwithcDegree, + VecZnxStd, VecZnxSubScalarInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, }, layouts::{Backend, Module, ScratchOwned}, oep::{ @@ -12,150 +12,17 @@ use backend::hal::{ use sampling::source::Source; use crate::{ - AutomorphismKey, AutomorphismKeyCompressed, AutomorphismKeyEncryptSkFamily, AutomorphismKeyExec, GGLWEExecLayoutFamily, - GLWEDecryptFamily, GLWEKeyswitchFamily, GLWEPlaintext, GLWESecret, GLWESecretExec, Infos, + layouts::{ + GGLWEAutomorphismKey, GLWEPlaintext, GLWESecret, Infos, + prepared::{GGLWEAutomorphismKeyExec, GLWESecretExec}, + }, noise::log2_std_noise_gglwe_product, + trait_families::{GLWEDecryptFamily, GLWEKeyswitchFamily}, }; -pub(crate) trait AutomorphismTestModuleFamily = AutomorphismKeyEncryptSkFamily - + GLWEKeyswitchFamily - + VecZnxAutomorphism - + GGLWEExecLayoutFamily - + VecZnxSwithcDegree - + VecZnxAddScalarInplace - + VecZnxAutomorphism - + VecZnxAutomorphismInplace - + GLWEDecryptFamily - + VecZnxSubScalarInplace - + VecZnxStd - + VecZnxCopy; -pub(crate) trait AutomorphismTestScratchFamily = ScratchOwnedAllocImpl - + ScratchOwnedBorrowImpl - + ScratchAvailableImpl - + TakeScalarZnxImpl - + TakeVecZnxDftImpl - + TakeVecZnxImpl - + TakeSvpPPolImpl - + TakeVecZnxBigImpl; +use crate::trait_families::{GGLWEAutomorphismKeyEncryptSkFamily, GLWESecretExecModuleFamily}; -pub(crate) fn test_automorphisk_key_encrypt_sk( - module: &Module, - basek: usize, - k_ksk: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module: AutomorphismTestModuleFamily, - B: AutomorphismTestScratchFamily, -{ - let n: usize = module.n(); - let rows: usize = (k_ksk - digits * basek) / (digits * basek); - - let mut atk: AutomorphismKey> = 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 = ScratchOwned::alloc(AutomorphismKey::encrypt_sk_scratch_space( - module, n, basek, k_ksk, rank, - )); - - let mut sk: GLWESecret> = 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> = 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( - module: &Module, - basek: usize, - k_ksk: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module: AutomorphismTestModuleFamily, - B: AutomorphismTestScratchFamily, -{ - let n: usize = module.n(); - let rows: usize = (k_ksk - digits * basek) / (digits * basek); - - let mut atk_compressed: AutomorphismKeyCompressed> = - 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 = ScratchOwned::alloc(AutomorphismKey::encrypt_sk_scratch_space( - module, n, basek, k_ksk, rank, - )); - - let mut sk: GLWESecret> = 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> = 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> = 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( +pub fn test_gglwe_automorphism_key_automorphism( module: &Module, p0: i64, p1: i64, @@ -167,8 +34,28 @@ pub(crate) fn test_gglwe_automorphism( sigma: f64, rank: usize, ) where - Module: AutomorphismTestModuleFamily, - B: AutomorphismTestScratchFamily, + Module: GGLWEAutomorphismKeyEncryptSkFamily + + GLWESecretExecModuleFamily + + GLWEKeyswitchFamily + + VecZnxAutomorphism + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxAutomorphism + + VecZnxAutomorphismInplace + + GLWEDecryptFamily + + VecZnxSubScalarInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc + + VmpPMatPrepare, + B: ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxDftImpl + + TakeVecZnxImpl + + TakeSvpPPolImpl + + TakeVecZnxBigImpl, { let n: usize = module.n(); let digits_in: usize = 1; @@ -176,17 +63,18 @@ pub(crate) fn test_gglwe_automorphism( let rows_in: usize = k_in / (basek * digits); let rows_apply: usize = k_in.div_ceil(basek * digits); - let mut auto_key_in: AutomorphismKey> = AutomorphismKey::alloc(n, basek, k_in, rows_in, digits_in, rank); - let mut auto_key_out: AutomorphismKey> = AutomorphismKey::alloc(n, basek, k_out, rows_in, digits_in, rank); - let mut auto_key_apply: AutomorphismKey> = AutomorphismKey::alloc(n, basek, k_apply, rows_apply, digits, rank); + let mut auto_key_in: GGLWEAutomorphismKey> = GGLWEAutomorphismKey::alloc(n, basek, k_in, rows_in, digits_in, rank); + let mut auto_key_out: GGLWEAutomorphismKey> = GGLWEAutomorphismKey::alloc(n, basek, k_out, rows_in, digits_in, rank); + let mut auto_key_apply: GGLWEAutomorphismKey> = + 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 = 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), + 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> = GLWESecret::alloc(n, rank); @@ -214,8 +102,8 @@ pub(crate) fn test_gglwe_automorphism( scratch.borrow(), ); - let mut auto_key_apply_exec: AutomorphismKeyExec, B> = - AutomorphismKeyExec::alloc(module, n, basek, k_apply, rows_apply, digits, rank); + let mut auto_key_apply_exec: GGLWEAutomorphismKeyExec, B> = + GGLWEAutomorphismKeyExec::alloc(module, n, basek, k_apply, rows_apply, digits, rank); auto_key_apply_exec.prepare(module, &auto_key_apply, scratch.borrow()); @@ -276,7 +164,7 @@ pub(crate) fn test_gglwe_automorphism( }); } -pub(crate) fn test_gglwe_automorphism_inplace( +pub fn test_gglwe_automorphism_key_automorphism_inplace( module: &Module, p0: i64, p1: i64, @@ -287,8 +175,28 @@ pub(crate) fn test_gglwe_automorphism_inplace( sigma: f64, rank: usize, ) where - Module: AutomorphismTestModuleFamily, - B: AutomorphismTestScratchFamily, + Module: GGLWEAutomorphismKeyEncryptSkFamily + + GLWESecretExecModuleFamily + + GLWEKeyswitchFamily + + VecZnxAutomorphism + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxAutomorphism + + VecZnxAutomorphismInplace + + GLWEDecryptFamily + + VecZnxSubScalarInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc + + VmpPMatPrepare, + B: ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxDftImpl + + TakeVecZnxImpl + + TakeSvpPPolImpl + + TakeVecZnxBigImpl, { let n: usize = module.n(); let digits_in: usize = 1; @@ -296,16 +204,17 @@ pub(crate) fn test_gglwe_automorphism_inplace( let rows_in: usize = k_in / (basek * digits); let rows_apply: usize = k_in.div_ceil(basek * digits); - let mut auto_key: AutomorphismKey> = AutomorphismKey::alloc(n, basek, k_in, rows_in, digits_in, rank); - let mut auto_key_apply: AutomorphismKey> = AutomorphismKey::alloc(n, basek, k_apply, rows_apply, digits, rank); + let mut auto_key: GGLWEAutomorphismKey> = GGLWEAutomorphismKey::alloc(n, basek, k_in, rows_in, digits_in, rank); + let mut auto_key_apply: GGLWEAutomorphismKey> = + 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 = 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), + 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> = GLWESecret::alloc(n, rank); @@ -333,8 +242,8 @@ pub(crate) fn test_gglwe_automorphism_inplace( scratch.borrow(), ); - let mut auto_key_apply_exec: AutomorphismKeyExec, B> = - AutomorphismKeyExec::alloc(module, n, basek, k_apply, rows_apply, digits, rank); + let mut auto_key_apply_exec: GGLWEAutomorphismKeyExec, B> = + GGLWEAutomorphismKeyExec::alloc(module, n, basek, k_apply, rows_apply, digits, rank); auto_key_apply_exec.prepare(module, &auto_key_apply, scratch.borrow()); diff --git a/core/src/tests/generics/automorphism/ggsw_ct.rs b/core/src/tests/generics/automorphism/ggsw_ct.rs new file mode 100644 index 0000000..c1e3913 --- /dev/null +++ b/core/src/tests/generics/automorphism/ggsw_ct.rs @@ -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( + p: i64, + module: &Module, + basek: usize, + k_out: usize, + k_in: usize, + k_ksk: usize, + k_tsk: usize, + digits: usize, + rank: usize, + sigma: f64, +) where + Module: GGSWAssertNoiseFamily + + GLWESecretExecModuleFamily + + VecZnxAddScalarInplace + + VecZnxCopy + + VecZnxStd + + VecZnxSubABInplace + + VmpPMatAlloc + + VmpPMatPrepare + + GGSWKeySwitchFamily + + GGLWESwitchingKeyEncryptSkFamily + + GGLWETensorKeyEncryptSkFamily + + VecZnxSwithcDegree + + VecZnxAutomorphismInplace + + VecZnxAutomorphismInplace + + VecZnxAutomorphism, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl + + VecZnxDftAllocBytesImpl + + VecZnxBigAllocBytesImpl + + TakeSvpPPolImpl, +{ + 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> = GGSWCiphertext::alloc(n, basek, k_in, rows_in, digits_in, rank); + let mut ct_out: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k_out, rows_in, digits_in, rank); + let mut tensor_key: GGLWETensorKey> = GGLWETensorKey::alloc(n, basek, k_tsk, rows, digits, rank); + let mut auto_key: GGLWEAutomorphismKey> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); + let mut pt_scalar: ScalarZnx> = 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 = 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> = GLWESecret::alloc(n, rank); + sk.fill_ternary_prob(var_xs, &mut source_xs); + let sk_exec: GLWESecretExec, 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, 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, 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( + p: i64, + module: &Module, + basek: usize, + k_ct: usize, + k_ksk: usize, + k_tsk: usize, + digits: usize, + rank: usize, + sigma: f64, +) where + Module: GGSWAssertNoiseFamily + + GLWESecretExecModuleFamily + + VecZnxAddScalarInplace + + VecZnxCopy + + VecZnxStd + + VecZnxSubABInplace + + VmpPMatAlloc + + VmpPMatPrepare + + GGSWKeySwitchFamily + + GGLWESwitchingKeyEncryptSkFamily + + GGLWETensorKeyEncryptSkFamily + + VecZnxSwithcDegree + + VecZnxAutomorphismInplace + + VecZnxAutomorphismInplace + + VecZnxAutomorphism, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl + + VecZnxDftAllocBytesImpl + + VecZnxBigAllocBytesImpl + + TakeSvpPPolImpl, +{ + 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> = GGSWCiphertext::alloc(n, basek, k_ct, rows_in, digits_in, rank); + let mut tensor_key: GGLWETensorKey> = GGLWETensorKey::alloc(n, basek, k_tsk, rows, digits, rank); + let mut auto_key: GGLWEAutomorphismKey> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); + let mut pt_scalar: ScalarZnx> = 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 = 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> = GLWESecret::alloc(n, rank); + sk.fill_ternary_prob(var_xs, &mut source_xs); + let sk_exec: GLWESecretExec, 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, 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, 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); +} diff --git a/core/src/glwe/tests/generic_automorphism.rs b/core/src/tests/generics/automorphism/glwe_ct.rs similarity index 66% rename from core/src/glwe/tests/generic_automorphism.rs rename to core/src/tests/generics/automorphism/glwe_ct.rs index 0ffb9bb..edf5f3c 100644 --- a/core/src/glwe/tests/generic_automorphism.rs +++ b/core/src/tests/generics/automorphism/glwe_ct.rs @@ -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 backend::hal::{ 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 = AutomorphismKeyEncryptSkFamily - + GLWEDecryptFamily - + GGLWEExecLayoutFamily - + GLWEKeyswitchFamily - + VecZnxAutomorphism - + VecZnxSwithcDegree - + VecZnxAddScalarInplace - + VecZnxAutomorphismInplace - + VecZnxStd; -pub(crate) trait AutomorphismTestScratchFamily = TakeVecZnxDftImpl - + TakeVecZnxBigImpl - + TakeSvpPPolImpl - + ScratchOwnedAllocImpl - + ScratchOwnedBorrowImpl - + ScratchAvailableImpl - + TakeScalarZnxImpl - + TakeVecZnxImpl; +use crate::trait_families::{GGLWEAutomorphismKeyEncryptSkFamily, GLWESecretExecModuleFamily}; -pub(crate) fn test_automorphism( +pub fn test_glwe_automorphism( module: &Module, basek: usize, p: i64, @@ -46,13 +33,30 @@ pub(crate) fn test_automorphism( rank: usize, sigma: f64, ) where - Module: AutomorphismTestModuleFamily, - B: AutomorphismTestScratchFamily, + Module: GGLWEAutomorphismKeyEncryptSkFamily + + GLWESecretExecModuleFamily + + GLWEDecryptFamily + + GLWEKeyswitchFamily + + VecZnxAutomorphism + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxAutomorphismInplace + + VecZnxStd + + VmpPMatAlloc + + VmpPMatPrepare, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl, { let n: usize = module.n(); let rows: usize = k_in.div_ceil(basek * digits); - let mut autokey: AutomorphismKey> = AutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); + let mut autokey: GGLWEAutomorphismKey> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); let mut ct_in: GLWECiphertext> = GLWECiphertext::alloc(n, basek, k_in, rank); let mut ct_out: GLWECiphertext> = GLWECiphertext::alloc(n, basek, k_out, rank); let mut pt_want: GLWEPlaintext> = GLWEPlaintext::alloc(n, basek, k_in); @@ -64,7 +68,7 @@ pub(crate) fn test_automorphism( module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_in, &mut source_xa); let mut scratch: ScratchOwned = 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 @@ pub(crate) fn test_automorphism( scratch.borrow(), ); - let mut autokey_exec: AutomorphismKeyExec, B> = - AutomorphismKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); + let mut autokey_exec: GGLWEAutomorphismKeyExec, 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 @@ pub(crate) fn test_automorphism( ct_out.assert_noise(module, &sk_exec, &pt_want, max_noise + 1.0); } -pub(crate) fn test_automorphism_inplace( +pub fn test_glwe_automorphism_inplace( module: &Module, basek: usize, p: i64, @@ -137,13 +141,30 @@ pub(crate) fn test_automorphism_inplace( rank: usize, sigma: f64, ) where - Module: AutomorphismTestModuleFamily, - B: AutomorphismTestScratchFamily, + Module: GGLWEAutomorphismKeyEncryptSkFamily + + GLWESecretExecModuleFamily + + GLWEDecryptFamily + + GLWEKeyswitchFamily + + VecZnxAutomorphism + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxAutomorphismInplace + + VecZnxStd + + VmpPMatAlloc + + VmpPMatPrepare, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl, { let n: usize = module.n(); let rows: usize = k_ct.div_ceil(basek * digits); - let mut autokey: AutomorphismKey> = AutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); + let mut autokey: GGLWEAutomorphismKey> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); let mut ct: GLWECiphertext> = GLWECiphertext::alloc(n, basek, k_ct, rank); let mut pt_want: GLWEPlaintext> = GLWEPlaintext::alloc(n, basek, k_ct); @@ -154,7 +175,7 @@ pub(crate) fn test_automorphism_inplace( module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_ct, &mut source_xa); let mut scratch: ScratchOwned = 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 @@ pub(crate) fn test_automorphism_inplace( scratch.borrow(), ); - let mut autokey_exec: AutomorphismKeyExec, B> = - AutomorphismKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); + let mut autokey_exec: GGLWEAutomorphismKeyExec, 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()); diff --git a/core/src/tests/generics/automorphism/mod.rs b/core/src/tests/generics/automorphism/mod.rs new file mode 100644 index 0000000..fd10f33 --- /dev/null +++ b/core/src/tests/generics/automorphism/mod.rs @@ -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::*; diff --git a/core/src/lwe/tests/generic_conversion.rs b/core/src/tests/generics/conversion.rs similarity index 59% rename from core/src/lwe/tests/generic_conversion.rs rename to core/src/tests/generics/conversion.rs index a54f521..6547cc1 100644 --- a/core/src/lwe/tests/generic_conversion.rs +++ b/core/src/tests/generics/conversion.rs @@ -1,7 +1,7 @@ use backend::hal::{ api::{ ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxEncodeCoeffsi64, - VecZnxSwithcDegree, ZnxView, + VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, ZnxView, }, layouts::{Backend, Module, ScratchOwned}, oep::{ @@ -11,34 +11,34 @@ use backend::hal::{ }; use sampling::source::Source; -use crate::{ - GGLWEEncryptSkFamily, GGLWEExecLayoutFamily, GLWECiphertext, GLWEDecryptFamily, GLWEKeyswitchFamily, GLWEPlaintext, - GLWESecret, GLWESecretExec, GLWEToLWESwitchingKey, GLWEToLWESwitchingKeyExec, Infos, LWECiphertext, LWEPlaintext, LWESecret, - LWESwitchingKey, LWESwitchingKeyExec, LWEToGLWESwitchingKey, LWEToGLWESwitchingKeyExec, +use crate::layouts::{ + GLWECiphertext, GLWEPlaintext, GLWESecret, GLWEToLWESwitchingKey, Infos, LWECiphertext, LWEPlaintext, LWESecret, + LWEToGLWESwitchingKey, + prepared::{GLWESecretExec, GLWEToLWESwitchingKeyExec, LWEToGLWESwitchingKeyExec}, }; -pub(crate) trait LWETestModuleFamily = GGLWEEncryptSkFamily - + GLWEDecryptFamily - + VecZnxSwithcDegree - + VecZnxAddScalarInplace - + GGLWEExecLayoutFamily - + GLWEKeyswitchFamily - + VecZnxEncodeCoeffsi64 - + VecZnxAutomorphismInplace; +use crate::trait_families::{GGLWEEncryptSkFamily, GLWEDecryptFamily, GLWEKeyswitchFamily, GLWESecretExecModuleFamily}; -pub(crate) trait LWETestScratchFamily = TakeScalarZnxImpl - + TakeVecZnxDftImpl - + ScratchAvailableImpl - + TakeVecZnxImpl - + TakeVecZnxBigImpl - + TakeSvpPPolImpl - + ScratchOwnedAllocImpl - + ScratchOwnedBorrowImpl; - -pub(crate) fn test_lwe_to_glwe(module: &Module) +pub fn test_lwe_to_glwe(module: &Module) where - Module: LWETestModuleFamily, - B: LWETestScratchFamily, + Module: GGLWEEncryptSkFamily + + GLWEDecryptFamily + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + GLWEKeyswitchFamily + + VecZnxEncodeCoeffsi64 + + VecZnxAutomorphismInplace + + VmpPMatAlloc + + VmpPMatPrepare + + GLWESecretExecModuleFamily, + B: TakeScalarZnxImpl + + TakeVecZnxDftImpl + + ScratchAvailableImpl + + TakeVecZnxImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl, { let n: usize = module.n(); let basek: usize = 17; @@ -111,10 +111,26 @@ where assert_eq!(glwe_pt.data.at(0, 0)[0], lwe_pt.data.at(0, 0)[0]); } -pub(crate) fn test_glwe_to_lwe(module: &Module) +pub fn test_glwe_to_lwe(module: &Module) where - Module: LWETestModuleFamily, - B: LWETestScratchFamily, + Module: GGLWEEncryptSkFamily + + GLWEDecryptFamily + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + GLWEKeyswitchFamily + + VecZnxEncodeCoeffsi64 + + VecZnxAutomorphismInplace + + VmpPMatAlloc + + VmpPMatPrepare + + GLWESecretExecModuleFamily, + B: TakeScalarZnxImpl + + TakeVecZnxDftImpl + + ScratchAvailableImpl + + TakeVecZnxImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl, { let n: usize = module.n(); let basek: usize = 17; @@ -186,73 +202,3 @@ where assert_eq!(glwe_pt.data.at(0, 0)[0], lwe_pt.data.at(0, 0)[0]); } - -pub(crate) fn test_keyswitch(module: &Module) -where - Module: LWETestModuleFamily, - B: LWETestScratchFamily, -{ - 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 = 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> = LWESecret::alloc(n_lwe_in); - sk_lwe_in.fill_ternary_prob(0.5, &mut source_xs); - - let mut sk_lwe_out: LWESecret> = 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> = 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> = 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> = 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> = LWECiphertext::alloc(n_lwe_out, basek, k_lwe_ct); - - let ksk_exec: LWESwitchingKeyExec, 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> = 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]); -} diff --git a/core/src/tests/generics/encryption/gglwe_atk.rs b/core/src/tests/generics/encryption/gglwe_atk.rs new file mode 100644 index 0000000..3564b5e --- /dev/null +++ b/core/src/tests/generics/encryption/gglwe_atk.rs @@ -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( + module: &Module, + basek: usize, + k_ksk: usize, + digits: usize, + rank: usize, + sigma: f64, +) where + Module: GGLWEAutomorphismKeyEncryptSkFamily + + GLWESecretExecModuleFamily + + GLWEKeyswitchFamily + + VecZnxAutomorphism + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxAutomorphism + + VecZnxAutomorphismInplace + + GLWEDecryptFamily + + VecZnxSubScalarInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc + + VmpPMatPrepare, + B: ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxDftImpl + + TakeVecZnxImpl + + TakeSvpPPolImpl + + TakeVecZnxBigImpl, +{ + let n: usize = module.n(); + let rows: usize = (k_ksk - digits * basek) / (digits * basek); + + let mut atk: GGLWEAutomorphismKey> = 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 = ScratchOwned::alloc(GGLWEAutomorphismKey::encrypt_sk_scratch_space( + module, n, basek, k_ksk, rank, + )); + + let mut sk: GLWESecret> = 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> = 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, 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( + module: &Module, + basek: usize, + k_ksk: usize, + digits: usize, + rank: usize, + sigma: f64, +) where + Module: GGLWEAutomorphismKeyEncryptSkFamily + + GLWESecretExecModuleFamily + + GLWEKeyswitchFamily + + VecZnxAutomorphism + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxAutomorphism + + VecZnxAutomorphismInplace + + GLWEDecryptFamily + + VecZnxSubScalarInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc + + VmpPMatPrepare, + B: ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxDftImpl + + TakeVecZnxImpl + + TakeSvpPPolImpl + + TakeVecZnxBigImpl, +{ + let n: usize = module.n(); + let rows: usize = (k_ksk - digits * basek) / (digits * basek); + + let mut atk_compressed: GGLWEAutomorphismKeyCompressed> = + 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 = ScratchOwned::alloc(GGLWEAutomorphismKey::encrypt_sk_scratch_space( + module, n, basek, k_ksk, rank, + )); + + let mut sk: GLWESecret> = 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> = 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> = 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); +} diff --git a/core/src/tests/generics/encryption/gglwe_ct.rs b/core/src/tests/generics/encryption/gglwe_ct.rs new file mode 100644 index 0000000..169a323 --- /dev/null +++ b/core/src/tests/generics/encryption/gglwe_ct.rs @@ -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( + module: &Module, + basek: usize, + k_ksk: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + sigma: f64, +) where + Module: GGLWEEncryptSkFamily + + GLWESecretExecModuleFamily + + GLWEDecryptFamily + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxStd + + VecZnxSubScalarInplace + + VecZnxCopy + + VmpPMatAlloc + + VmpPMatPrepare, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl + + VecZnxDftAllocBytesImpl + + VecZnxBigAllocBytesImpl + + TakeSvpPPolImpl, +{ + let n: usize = module.n(); + let rows: usize = (k_ksk - digits * basek) / (digits * basek); + + let mut ksk: GGLWESwitchingKey> = 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 = ScratchOwned::alloc(GGLWESwitchingKey::encrypt_sk_scratch_space( + module, n, basek, k_ksk, rank_in, rank_out, + )); + + let mut sk_in: GLWESecret> = GLWESecret::alloc(n, rank_in); + sk_in.fill_ternary_prob(0.5, &mut source_xs); + + let mut sk_out: GLWESecret> = GLWESecret::alloc(n, rank_out); + sk_out.fill_ternary_prob(0.5, &mut source_xs); + let sk_out_exec: GLWESecretExec, 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( + module: &Module, + basek: usize, + k_ksk: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + sigma: f64, +) where + Module: GGLWEEncryptSkFamily + + GLWESecretExecModuleFamily + + GLWEDecryptFamily + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxStd + + VecZnxSubScalarInplace + + VecZnxCopy + + VmpPMatAlloc + + VmpPMatPrepare, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl + + VecZnxDftAllocBytesImpl + + VecZnxBigAllocBytesImpl + + TakeSvpPPolImpl, +{ + let n: usize = module.n(); + let rows: usize = (k_ksk - digits * basek) / (digits * basek); + + let mut ksk_compressed: GGLWESwitchingKeyCompressed> = + 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 = ScratchOwned::alloc(GGLWESwitchingKeyCompressed::encrypt_sk_scratch_space( + module, n, basek, k_ksk, rank_in, rank_out, + )); + + let mut sk_in: GLWESecret> = GLWESecret::alloc(n, rank_in); + sk_in.fill_ternary_prob(0.5, &mut source_xs); + + let mut sk_out: GLWESecret> = GLWESecret::alloc(n, rank_out); + sk_out.fill_ternary_prob(0.5, &mut source_xs); + let sk_out_exec: GLWESecretExec, 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> = 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); +} diff --git a/core/src/tests/generics/encryption/ggsw_ct.rs b/core/src/tests/generics/encryption/ggsw_ct.rs new file mode 100644 index 0000000..fb16a03 --- /dev/null +++ b/core/src/tests/generics/encryption/ggsw_ct.rs @@ -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(module: &Module, basek: usize, k: usize, digits: usize, rank: usize, sigma: f64) +where + Module: GLWESecretExecModuleFamily + + GGSWEncryptSkFamily + + GGSWAssertNoiseFamily + + VecZnxAddScalarInplace + + VecZnxSubABInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc + + VmpPMatPrepare, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl + + VecZnxDftAllocBytesImpl + + VecZnxBigAllocBytesImpl + + TakeSvpPPolImpl, +{ + let n: usize = module.n(); + let rows: usize = (k - digits * basek) / (digits * basek); + + let mut ct: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k, rows, digits, rank); + + let mut pt_scalar: ScalarZnx> = 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 = ScratchOwned::alloc(GGSWCiphertext::encrypt_sk_scratch_space( + module, n, basek, k, rank, + )); + + let mut sk: GLWESecret> = GLWESecret::alloc(n, rank); + sk.fill_ternary_prob(0.5, &mut source_xs); + let mut sk_exec: GLWESecretExec, 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( + module: &Module, + basek: usize, + k: usize, + digits: usize, + rank: usize, + sigma: f64, +) where + Module: GLWESecretExecModuleFamily + + GGSWEncryptSkFamily + + GGSWAssertNoiseFamily + + VecZnxAddScalarInplace + + VecZnxSubABInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc + + VmpPMatPrepare, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl + + VecZnxDftAllocBytesImpl + + VecZnxBigAllocBytesImpl + + TakeSvpPPolImpl, +{ + let n: usize = module.n(); + let rows: usize = (k - digits * basek) / (digits * basek); + + let mut ct_compressed: GGSWCiphertextCompressed> = GGSWCiphertextCompressed::alloc(n, basek, k, rows, digits, rank); + + let mut pt_scalar: ScalarZnx> = 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 = ScratchOwned::alloc(GGSWCiphertextCompressed::encrypt_sk_scratch_space( + module, n, basek, k, rank, + )); + + let mut sk: GLWESecret> = GLWESecret::alloc(n, rank); + sk.fill_ternary_prob(0.5, &mut source_xs); + let mut sk_exec: GLWESecretExec, 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> = GGSWCiphertext::alloc(n, basek, k, rows, digits, rank); + ct.decompress(module, &ct_compressed); + + ct.assert_noise(module, &sk_exec, &pt_scalar, &noise_f); +} diff --git a/core/src/glwe/tests/generic_encryption.rs b/core/src/tests/generics/encryption/glwe_ct.rs similarity index 76% rename from core/src/glwe/tests/generic_encryption.rs rename to core/src/tests/generics/encryption/glwe_ct.rs index 32a1fd6..bd15a9f 100644 --- a/core/src/glwe/tests/generic_encryption.rs +++ b/core/src/tests/generics/encryption/glwe_ct.rs @@ -9,25 +9,31 @@ use backend::hal::{ 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 = GLWEDecryptFamily + GLWESecretFamily + VecZnxStd; +use crate::trait_families::{GLWEDecryptFamily, GLWEEncryptPkFamily, GLWEEncryptSkFamily, GLWESecretExecModuleFamily}; -pub(crate) trait EncryptionTestScratchFamily = TakeVecZnxDftImpl - + TakeVecZnxBigImpl - + TakeSvpPPolImpl - + ScratchOwnedAllocImpl - + ScratchOwnedBorrowImpl - + ScratchAvailableImpl - + TakeScalarZnxImpl - + TakeVecZnxImpl; +pub trait EncryptionTestModuleFamily = + GLWEDecryptFamily + VecZnxStd + GLWESecretExecModuleFamily + GLWEEncryptPkFamily; -pub(crate) fn test_encrypt_sk(module: &Module, basek: usize, k_ct: usize, k_pt: usize, sigma: f64, rank: usize) +pub fn test_glwe_encrypt_sk(module: &Module, basek: usize, k_ct: usize, k_pt: usize, sigma: f64, rank: usize) where Module: EncryptionTestModuleFamily + GLWEEncryptSkFamily, - B: EncryptionTestScratchFamily, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl, { let n = module.n(); let mut ct: GLWECiphertext> = GLWECiphertext::alloc(n, basek, k_ct, rank); @@ -69,7 +75,7 @@ where assert!(noise_have <= noise_want + 0.2); } -pub(crate) fn test_encrypt_sk_compressed( +pub fn test_glwe_compressed_encrypt_sk( module: &Module, basek: usize, k_ct: usize, @@ -78,7 +84,14 @@ pub(crate) fn test_encrypt_sk_compressed( rank: usize, ) where Module: EncryptionTestModuleFamily + GLWEEncryptSkFamily + VecZnxCopy, - B: EncryptionTestScratchFamily, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl, { let n = module.n(); let mut ct_compressed: GLWECiphertextCompressed> = GLWECiphertextCompressed::alloc(n, basek, k_ct, rank); @@ -131,10 +144,17 @@ pub(crate) fn test_encrypt_sk_compressed( ); } -pub(crate) fn test_encrypt_zero_sk(module: &Module, basek: usize, k_ct: usize, sigma: f64, rank: usize) +pub fn test_glwe_encrypt_zero_sk(module: &Module, basek: usize, k_ct: usize, sigma: f64, rank: usize) where Module: EncryptionTestModuleFamily + GLWEEncryptSkFamily, - B: EncryptionTestScratchFamily, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl, { let n = module.n(); let mut pt: GLWEPlaintext> = GLWEPlaintext::alloc(n, basek, k_ct); @@ -167,15 +187,18 @@ where assert!((sigma - module.vec_znx_std(basek, &pt.data, 0) * (k_ct as f64).exp2()) <= 0.2); } -pub(crate) fn test_encrypt_pk(module: &Module, basek: usize, k_ct: usize, k_pk: usize, sigma: f64, rank: usize) +pub fn test_glwe_encrypt_pk(module: &Module, basek: usize, k_ct: usize, k_pk: usize, sigma: f64, rank: usize) where - Module: EncryptionTestModuleFamily - + GLWEEncryptPkFamily - + GLWEEncryptSkFamily - + VecZnxDftAlloc - + VecZnxFillUniform - + VecZnxSubABInplace, - B: EncryptionTestScratchFamily, + Module: + EncryptionTestModuleFamily + GLWEEncryptSkFamily + VecZnxDftAlloc + VecZnxFillUniform + VecZnxSubABInplace, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl, { let n: usize = module.n(); let mut ct: GLWECiphertext> = GLWECiphertext::alloc(n, basek, k_ct, rank); diff --git a/core/src/gglwe/tests/generics_tensor_key.rs b/core/src/tests/generics/encryption/glwe_tsk.rs similarity index 67% rename from core/src/gglwe/tests/generics_tensor_key.rs rename to core/src/tests/generics/encryption/glwe_tsk.rs index 962abec..3b7137b 100644 --- a/core/src/gglwe/tests/generics_tensor_key.rs +++ b/core/src/tests/generics/encryption/glwe_tsk.rs @@ -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 backend::hal::{ 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 = GGLWEEncryptSkFamily - + GLWEDecryptFamily - + VecZnxSwithcDegree - + VecZnxAddScalarInplace - + VecZnxStd - + VecZnxSubScalarInplace; +use crate::trait_families::{GGLWEEncryptSkFamily, GGLWETensorKeyEncryptSkFamily, GLWESecretExecModuleFamily}; -pub(crate) trait TestScratchFamily = TakeVecZnxDftImpl - + TakeVecZnxBigImpl - + TakeSvpPPolImpl - + ScratchOwnedAllocImpl - + ScratchOwnedBorrowImpl - + ScratchAvailableImpl - + TakeScalarZnxImpl - + TakeVecZnxImpl - + VecZnxDftAllocBytesImpl - + VecZnxBigAllocBytesImpl - + TakeSvpPPolImpl; - -pub(crate) fn test_tensor_key_encrypt_sk(module: &Module, basek: usize, k: usize, sigma: f64, rank: usize) +pub fn test_glwe_tensor_key_encrypt_sk(module: &Module, basek: usize, k: usize, sigma: f64, rank: usize) where - Module: TestModuleFamily - + GGLWEExecLayoutFamily - + GLWETensorKeyEncryptSkFamily + Module: GGLWEEncryptSkFamily + + GLWESecretExecModuleFamily + + GLWEDecryptFamily + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxStd + + VecZnxSubScalarInplace + + VmpPMatAlloc + + VmpPMatPrepare + + GGLWETensorKeyEncryptSkFamily + GLWEDecryptFamily + VecZnxDftAlloc + VecZnxBigAlloc, - B: TestScratchFamily, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl + + VecZnxDftAllocBytesImpl + + VecZnxBigAllocBytesImpl + + TakeSvpPPolImpl, { let n: usize = module.n(); let rows: usize = k / basek; - let mut tensor_key: GLWETensorKey> = GLWETensorKey::alloc(n, basek, k, rows, 1, rank); + let mut tensor_key: GGLWETensorKey> = 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 = ScratchOwned::alloc(GLWETensorKey::encrypt_sk_scratch_space( + let mut scratch: ScratchOwned = ScratchOwned::alloc(GGLWETensorKey::encrypt_sk_scratch_space( module, n, basek, @@ -116,31 +116,43 @@ where }) } -pub(crate) fn test_tensor_key_encrypt_sk_compressed( - module: &Module, - basek: usize, - k: usize, - sigma: f64, - rank: usize, -) where - Module: TestModuleFamily - + GGLWEExecLayoutFamily - + GLWETensorKeyEncryptSkFamily +pub fn test_glwe_tensor_key_compressed_encrypt_sk(module: &Module, basek: usize, k: usize, sigma: f64, rank: usize) +where + Module: GGLWEEncryptSkFamily + + GLWESecretExecModuleFamily + + GLWEDecryptFamily + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxStd + + VecZnxSubScalarInplace + + VmpPMatAlloc + + VmpPMatPrepare + + GGLWETensorKeyEncryptSkFamily + GLWEDecryptFamily + VecZnxDftAlloc + VecZnxBigAlloc + VecZnxCopy, - B: TestScratchFamily, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl + + VecZnxDftAllocBytesImpl + + VecZnxBigAllocBytesImpl + + TakeSvpPPolImpl, { let n: usize = module.n(); let rows: usize = k / basek; - let mut tensor_key_compressed: GLWETensorKeyCompressed> = GLWETensorKeyCompressed::alloc(n, basek, k, rows, 1, rank); + let mut tensor_key_compressed: GGLWETensorKeyCompressed> = 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 = ScratchOwned::alloc(GLWETensorKeyCompressed::encrypt_sk_scratch_space( + let mut scratch: ScratchOwned = ScratchOwned::alloc(GGLWETensorKeyCompressed::encrypt_sk_scratch_space( module, n, basek, @@ -164,7 +176,7 @@ pub(crate) fn test_tensor_key_encrypt_sk_compressed( scratch.borrow(), ); - let mut tensor_key: GLWETensorKey> = GLWETensorKey::alloc(n, basek, k, rows, 1, rank); + let mut tensor_key: GGLWETensorKey> = GGLWETensorKey::alloc(n, basek, k, rows, 1, rank); tensor_key.decompress(module, &tensor_key_compressed); let mut pt: GLWEPlaintext> = GLWEPlaintext::alloc(n, basek, k); diff --git a/core/src/tests/generics/encryption/mod.rs b/core/src/tests/generics/encryption/mod.rs new file mode 100644 index 0000000..d871177 --- /dev/null +++ b/core/src/tests/generics/encryption/mod.rs @@ -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::*; diff --git a/core/src/tests/generics/external_product/gglwe_ksk.rs b/core/src/tests/generics/external_product/gglwe_ksk.rs new file mode 100644 index 0000000..4c5bb03 --- /dev/null +++ b/core/src/tests/generics/external_product/gglwe_ksk.rs @@ -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( + module: &Module, + basek: usize, + k_out: usize, + k_in: usize, + k_ggsw: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + sigma: f64, +) where + Module: GGLWEEncryptSkFamily + + GLWESecretExecModuleFamily + + GLWEDecryptFamily + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxStd + + VecZnxSubScalarInplace + + VecZnxCopy + + VmpPMatAlloc + + VmpPMatPrepare + + GGLWESwitchingKeyEncryptSkFamily + + GLWEExternalProductFamily + + GLWEDecryptFamily + + VecZnxRotateInplace, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl + + VecZnxDftAllocBytesImpl + + VecZnxBigAllocBytesImpl + + TakeSvpPPolImpl, +{ + 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> = GGLWESwitchingKey::alloc(n, basek, k_in, rows, digits_in, rank_in, rank_out); + let mut ct_gglwe_out: GGLWESwitchingKey> = + GGLWESwitchingKey::alloc(n, basek, k_out, rows, digits_in, rank_in, rank_out); + let mut ct_rgsw: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank_out); + + let mut pt_rgsw: ScalarZnx> = 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 = 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> = GLWESecret::alloc(n, rank_in); + sk_in.fill_ternary_prob(var_xs, &mut source_xs); + + let mut sk_out: GLWESecret> = GLWESecret::alloc(n, rank_out); + sk_out.fill_ternary_prob(var_xs, &mut source_xs); + let sk_out_exec: GLWESecretExec, 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, 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( + module: &Module, + basek: usize, + k_ct: usize, + k_ggsw: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + sigma: f64, +) where + Module: GGLWEEncryptSkFamily + + GLWESecretExecModuleFamily + + GLWEDecryptFamily + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxStd + + VecZnxSubScalarInplace + + VecZnxCopy + + VmpPMatAlloc + + VmpPMatPrepare + + GGLWESwitchingKeyEncryptSkFamily + + GLWEExternalProductFamily + + GLWEDecryptFamily + + VecZnxRotateInplace, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl + + VecZnxDftAllocBytesImpl + + VecZnxBigAllocBytesImpl + + TakeSvpPPolImpl, +{ + let n: usize = module.n(); + let rows: usize = k_ct.div_ceil(basek * digits); + + let digits_in: usize = 1; + + let mut ct_gglwe: GGLWESwitchingKey> = GGLWESwitchingKey::alloc(n, basek, k_ct, rows, digits_in, rank_in, rank_out); + let mut ct_rgsw: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank_out); + + let mut pt_rgsw: ScalarZnx> = 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 = 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> = GLWESecret::alloc(n, rank_in); + sk_in.fill_ternary_prob(var_xs, &mut source_xs); + + let mut sk_out: GLWESecret> = GLWESecret::alloc(n, rank_out); + sk_out.fill_ternary_prob(var_xs, &mut source_xs); + let sk_out_exec: GLWESecretExec, 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, 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); +} diff --git a/core/src/tests/generics/external_product/ggsw_ct.rs b/core/src/tests/generics/external_product/ggsw_ct.rs new file mode 100644 index 0000000..14cb8e4 --- /dev/null +++ b/core/src/tests/generics/external_product/ggsw_ct.rs @@ -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( + module: &Module, + basek: usize, + k_in: usize, + k_out: usize, + k_ggsw: usize, + digits: usize, + rank: usize, + sigma: f64, +) where + Module: GLWESecretExecModuleFamily + + GGSWEncryptSkFamily + + GGSWAssertNoiseFamily + + VecZnxAddScalarInplace + + VecZnxSubABInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc + + VmpPMatPrepare + + GGSWAssertNoiseFamily + + GGSWKeySwitchFamily + + GGLWESwitchingKeyEncryptSkFamily + + GGLWETensorKeyEncryptSkFamily + + VecZnxRotateInplace, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl + + VecZnxDftAllocBytesImpl + + VecZnxBigAllocBytesImpl + + TakeSvpPPolImpl, +{ + 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> = GGSWCiphertext::alloc(n, basek, k_in, rows_in, digits_in, rank); + let mut ct_ggsw_lhs_out: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k_out, rows_in, digits_in, rank); + let mut ct_ggsw_rhs: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank); + let mut pt_ggsw_lhs: ScalarZnx> = ScalarZnx::alloc(n, 1); + let mut pt_ggsw_rhs: ScalarZnx> = 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 = 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> = GLWESecret::alloc(n, rank); + sk.fill_ternary_prob(0.5, &mut source_xs); + let sk_exec: GLWESecretExec, 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, 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( + module: &Module, + basek: usize, + k_ct: usize, + k_ggsw: usize, + digits: usize, + rank: usize, + sigma: f64, +) where + Module: GLWESecretExecModuleFamily + + GGSWEncryptSkFamily + + GGSWAssertNoiseFamily + + VecZnxAddScalarInplace + + VecZnxSubABInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc + + VmpPMatPrepare + + GGSWAssertNoiseFamily + + GGSWKeySwitchFamily + + GGLWESwitchingKeyEncryptSkFamily + + GGLWETensorKeyEncryptSkFamily + + VecZnxRotateInplace, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl + + VecZnxDftAllocBytesImpl + + VecZnxBigAllocBytesImpl + + TakeSvpPPolImpl, +{ + 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> = GGSWCiphertext::alloc(n, basek, k_ct, rows_in, digits_in, rank); + let mut ct_ggsw_rhs: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank); + + let mut pt_ggsw_lhs: ScalarZnx> = ScalarZnx::alloc(n, 1); + let mut pt_ggsw_rhs: ScalarZnx> = 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 = 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> = GLWESecret::alloc(n, rank); + sk.fill_ternary_prob(0.5, &mut source_xs); + let sk_exec: GLWESecretExec, 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, 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); +} diff --git a/core/src/glwe/tests/generic_external_product.rs b/core/src/tests/generics/external_product/glwe_ct.rs similarity index 79% rename from core/src/glwe/tests/generic_external_product.rs rename to core/src/tests/generics/external_product/glwe_ct.rs index 4150261..bdb5797 100644 --- a/core/src/glwe/tests/generic_external_product.rs +++ b/core/src/tests/generics/external_product/glwe_ct.rs @@ -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 backend::hal::{ 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 = GLWEEncryptSkFamily - + GLWEDecryptFamily - + GLWESecretFamily - + GLWEExternalProductFamily - + GGSWLayoutFamily - + VecZnxAddScalarInplace - + VecZnxRotateInplace - + VecZnxStd; +use crate::trait_families::{GLWEDecryptFamily, GLWEEncryptSkFamily, GLWEExternalProductFamily, GLWESecretExecModuleFamily}; -pub(crate) trait ExternalProductTestScratchFamily = TakeVecZnxDftImpl - + TakeVecZnxBigImpl - + TakeSvpPPolImpl - + ScratchOwnedAllocImpl - + ScratchOwnedBorrowImpl - + ScratchAvailableImpl - + TakeScalarZnxImpl - + TakeVecZnxImpl; - -pub(crate) fn test_external_product( +pub fn test_glwe_external_product( module: &Module, basek: usize, k_out: usize, @@ -44,8 +31,23 @@ pub(crate) fn test_external_product( rank: usize, sigma: f64, ) where - Module: ExternalProductTestModuleFamily, - B: ExternalProductTestScratchFamily, + Module: GLWEEncryptSkFamily + + GLWESecretExecModuleFamily + + GLWEDecryptFamily + + GLWEExternalProductFamily + + VecZnxAddScalarInplace + + VecZnxRotateInplace + + VecZnxStd + + VmpPMatAlloc + + VmpPMatPrepare, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl, { let n: usize = module.n(); let rows: usize = k_in.div_ceil(basek * digits); @@ -138,7 +140,7 @@ pub(crate) fn test_external_product( ct_glwe_out.assert_noise(module, &sk_exec, &pt_want, max_noise + 0.5); } -pub(crate) fn test_external_product_inplace( +pub fn test_glwe_external_product_inplace( module: &Module, basek: usize, k_ct: usize, @@ -147,8 +149,23 @@ pub(crate) fn test_external_product_inplace( rank: usize, sigma: f64, ) where - Module: ExternalProductTestModuleFamily, - B: ExternalProductTestScratchFamily, + Module: GLWEEncryptSkFamily + + GLWESecretExecModuleFamily + + GLWEDecryptFamily + + GLWEExternalProductFamily + + VecZnxAddScalarInplace + + VecZnxRotateInplace + + VecZnxStd + + VmpPMatAlloc + + VmpPMatPrepare, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl, { let n: usize = module.n(); let rows: usize = k_ct.div_ceil(basek * digits); diff --git a/core/src/tests/generics/external_product/mod.rs b/core/src/tests/generics/external_product/mod.rs new file mode 100644 index 0000000..52b7dc2 --- /dev/null +++ b/core/src/tests/generics/external_product/mod.rs @@ -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::*; diff --git a/core/src/tests/generics/keyswitch/gglwe_ct.rs b/core/src/tests/generics/keyswitch/gglwe_ct.rs new file mode 100644 index 0000000..4b674d2 --- /dev/null +++ b/core/src/tests/generics/keyswitch/gglwe_ct.rs @@ -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( + module: &Module, + 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: GGLWEEncryptSkFamily + + GLWESecretExecModuleFamily + + GLWEDecryptFamily + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxStd + + VecZnxSubScalarInplace + + VecZnxCopy + + VmpPMatAlloc + + VmpPMatPrepare + + GGLWEEncryptSkFamily + + GLWEDecryptFamily + + GLWEKeyswitchFamily, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl + + VecZnxDftAllocBytesImpl + + VecZnxBigAllocBytesImpl + + TakeSvpPPolImpl, +{ + 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> = + GGLWESwitchingKey::alloc(n, basek, k_in, rows, digits_in, rank_in_s0s1, rank_out_s0s1); + let mut ct_gglwe_s1s2: GGLWESwitchingKey> = + GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_out_s0s1, rank_out_s1s2); + let mut ct_gglwe_s0s2: GGLWESwitchingKey> = 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 = 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 = 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> = GLWESecret::alloc(n, rank_in_s0s1); + sk0.fill_ternary_prob(0.5, &mut source_xs); + + let mut sk1: GLWESecret> = GLWESecret::alloc(n, rank_out_s0s1); + sk1.fill_ternary_prob(0.5, &mut source_xs); + + let mut sk2: GLWESecret> = GLWESecret::alloc(n, rank_out_s1s2); + sk2.fill_ternary_prob(0.5, &mut source_xs); + let sk2_exec: GLWESecretExec, 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, 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( + module: &Module, + basek: usize, + k_ct: usize, + k_ksk: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + sigma: f64, +) where + Module: GGLWEEncryptSkFamily + + GLWESecretExecModuleFamily + + GLWEDecryptFamily + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VecZnxStd + + VecZnxSubScalarInplace + + VecZnxCopy + + VmpPMatAlloc + + VmpPMatPrepare + + GGLWESwitchingKeyEncryptSkFamily + + GLWEKeyswitchFamily + + GLWEDecryptFamily, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl + + VecZnxDftAllocBytesImpl + + VecZnxBigAllocBytesImpl + + TakeSvpPPolImpl, +{ + 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> = + GGLWESwitchingKey::alloc(n, basek, k_ct, rows, digits_in, rank_in, rank_out); + let mut ct_gglwe_s1s2: GGLWESwitchingKey> = 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 = ScratchOwned::alloc(GGLWESwitchingKey::encrypt_sk_scratch_space( + module, + n, + basek, + k_ksk, + rank_in | rank_out, + rank_out, + )); + let mut scratch_apply: ScratchOwned = 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> = GLWESecret::alloc(n, rank_in); + sk0.fill_ternary_prob(var_xs, &mut source_xs); + + let mut sk1: GLWESecret> = GLWESecret::alloc(n, rank_out); + sk1.fill_ternary_prob(var_xs, &mut source_xs); + + let mut sk2: GLWESecret> = GLWESecret::alloc(n, rank_out); + sk2.fill_ternary_prob(var_xs, &mut source_xs); + let sk2_exec: GLWESecretExec, 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, 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> = 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); +} diff --git a/core/src/tests/generics/keyswitch/ggsw_ct.rs b/core/src/tests/generics/keyswitch/ggsw_ct.rs new file mode 100644 index 0000000..9c26f93 --- /dev/null +++ b/core/src/tests/generics/keyswitch/ggsw_ct.rs @@ -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( + module: &Module, + basek: usize, + k_out: usize, + k_in: usize, + k_ksk: usize, + k_tsk: usize, + digits: usize, + rank: usize, + sigma: f64, +) where + Module: GLWESecretExecModuleFamily + + GGSWEncryptSkFamily + + GGSWAssertNoiseFamily + + VecZnxAddScalarInplace + + VecZnxSubABInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc + + VmpPMatPrepare + + GGSWAssertNoiseFamily + + GGSWKeySwitchFamily + + GGLWESwitchingKeyEncryptSkFamily + + GGLWETensorKeyEncryptSkFamily + + VecZnxSwithcDegree, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl + + VecZnxDftAllocBytesImpl + + VecZnxBigAllocBytesImpl + + TakeSvpPPolImpl + + VecZnxDftAllocBytesImpl + + VecZnxBigAllocBytesImpl + + TakeSvpPPolImpl, +{ + let n: usize = module.n(); + let rows: usize = k_in.div_ceil(digits * basek); + + let digits_in: usize = 1; + + let mut ct_in: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k_in, rows, digits_in, rank); + let mut ct_out: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k_out, rows, digits_in, rank); + let mut tsk: GGLWETensorKey> = GGLWETensorKey::alloc(n, basek, k_ksk, rows, digits, rank); + let mut ksk: GGLWESwitchingKey> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank, rank); + let mut pt_scalar: ScalarZnx> = 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 = 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> = GLWESecret::alloc(n, rank); + sk_in.fill_ternary_prob(var_xs, &mut source_xs); + let sk_in_dft: GLWESecretExec, B> = GLWESecretExec::from(module, &sk_in); + + let mut sk_out: GLWESecret> = GLWESecret::alloc(n, rank); + sk_out.fill_ternary_prob(var_xs, &mut source_xs); + let sk_out_exec: GLWESecretExec, 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, B> = + GGLWESwitchingKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank, rank); + let mut tsk_exec: GGLWETensorKeyExec, 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( + module: &Module, + basek: usize, + k_ct: usize, + k_ksk: usize, + k_tsk: usize, + digits: usize, + rank: usize, + sigma: f64, +) where + Module: GLWESecretExecModuleFamily + + GGSWEncryptSkFamily + + GGSWAssertNoiseFamily + + VecZnxAddScalarInplace + + VecZnxSubABInplace + + VecZnxStd + + VecZnxCopy + + VmpPMatAlloc + + VmpPMatPrepare + + GGSWAssertNoiseFamily + + GGSWKeySwitchFamily + + GGLWESwitchingKeyEncryptSkFamily + + GGLWETensorKeyEncryptSkFamily + + VecZnxSwithcDegree, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl + + VecZnxDftAllocBytesImpl + + VecZnxBigAllocBytesImpl + + TakeSvpPPolImpl, +{ + let n: usize = module.n(); + let rows: usize = k_ct.div_ceil(digits * basek); + + let digits_in: usize = 1; + + let mut ct: GGSWCiphertext> = GGSWCiphertext::alloc(n, basek, k_ct, rows, digits_in, rank); + let mut tsk: GGLWETensorKey> = GGLWETensorKey::alloc(n, basek, k_tsk, rows, digits, rank); + let mut ksk: GGLWESwitchingKey> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank, rank); + let mut pt_scalar: ScalarZnx> = 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 = 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> = GLWESecret::alloc(n, rank); + sk_in.fill_ternary_prob(var_xs, &mut source_xs); + let sk_in_dft: GLWESecretExec, B> = GLWESecretExec::from(module, &sk_in); + + let mut sk_out: GLWESecret> = GLWESecret::alloc(n, rank); + sk_out.fill_ternary_prob(var_xs, &mut source_xs); + let sk_out_exec: GLWESecretExec, 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, B> = + GGLWESwitchingKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank, rank); + let mut tsk_exec: GGLWETensorKeyExec, 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); +} diff --git a/core/src/glwe/tests/generic_keyswitch.rs b/core/src/tests/generics/keyswitch/glwe_ct.rs similarity index 67% rename from core/src/glwe/tests/generic_keyswitch.rs rename to core/src/tests/generics/keyswitch/glwe_ct.rs index 733b940..a764274 100644 --- a/core/src/glwe/tests/generic_keyswitch.rs +++ b/core/src/tests/generics/keyswitch/glwe_ct.rs @@ -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 backend::hal::{ 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 = GLWESecretFamily - + GLWESwitchingKeyEncryptSkFamily - + GLWEKeyswitchFamily - + GLWEDecryptFamily - + GGLWEExecLayoutFamily - + VecZnxStd - + VecZnxSwithcDegree - + VecZnxAddScalarInplace; +use crate::trait_families::{GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; -pub(crate) trait KeySwitchTestScratchFamily = TakeVecZnxDftImpl - + TakeVecZnxBigImpl - + TakeSvpPPolImpl - + ScratchOwnedAllocImpl - + ScratchOwnedBorrowImpl - + ScratchAvailableImpl - + TakeScalarZnxImpl - + TakeVecZnxImpl; - -pub(crate) fn test_keyswitch( +pub fn test_glwe_keyswitch( module: &Module, basek: usize, k_out: usize, @@ -43,13 +33,28 @@ pub(crate) fn test_keyswitch( rank_out: usize, sigma: f64, ) where - Module: KeySwitchTestModuleFamily, - B: KeySwitchTestScratchFamily, + Module: GGLWESwitchingKeyEncryptSkFamily + + GLWESecretExecModuleFamily + + GLWEKeyswitchFamily + + GLWEDecryptFamily + + VecZnxStd + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VmpPMatAlloc + + VmpPMatPrepare, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl, { let n = module.n(); let rows: usize = k_in.div_ceil(basek * digits); - let mut ksk: GLWESwitchingKey> = GLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_in, rank_out); + let mut ksk: GGLWESwitchingKey> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_in, rank_out); let mut ct_in: GLWECiphertext> = GLWECiphertext::alloc(n, basek, k_in, rank_in); let mut ct_out: GLWECiphertext> = GLWECiphertext::alloc(n, basek, k_out, rank_out); let mut pt_want: GLWEPlaintext> = GLWEPlaintext::alloc(n, basek, k_in); @@ -61,7 +66,7 @@ pub(crate) fn test_keyswitch( module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_in, &mut source_xa); let mut scratch: ScratchOwned = 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 @@ pub(crate) fn test_keyswitch( scratch.borrow(), ); - let ksk_exec: GLWESwitchingKeyExec, B> = GLWESwitchingKeyExec::from(module, &ksk, scratch.borrow()); + let ksk_exec: GGLWESwitchingKeyExec, B> = GGLWESwitchingKeyExec::from(module, &ksk, scratch.borrow()); ct_out.keyswitch(module, &ct_in, &ksk_exec, scratch.borrow()); @@ -124,7 +129,7 @@ pub(crate) fn test_keyswitch( ct_out.assert_noise(module, &sk_out_exec, &pt_want, max_noise + 0.5); } -pub(crate) fn test_keyswitch_inplace( +pub fn test_glwe_keyswitch_inplace( module: &Module, basek: usize, k_ct: usize, @@ -133,13 +138,28 @@ pub(crate) fn test_keyswitch_inplace( rank: usize, sigma: f64, ) where - Module: KeySwitchTestModuleFamily, - B: KeySwitchTestScratchFamily, + Module: GGLWESwitchingKeyEncryptSkFamily + + GLWESecretExecModuleFamily + + GLWEKeyswitchFamily + + GLWEDecryptFamily + + VecZnxStd + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + VmpPMatAlloc + + VmpPMatPrepare, + B: TakeVecZnxDftImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl + + ScratchAvailableImpl + + TakeScalarZnxImpl + + TakeVecZnxImpl, { let n: usize = module.n(); let rows: usize = k_ct.div_ceil(basek * digits); - let mut ksk: GLWESwitchingKey> = GLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank, rank); + let mut ksk: GGLWESwitchingKey> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank, rank); let mut ct_glwe: GLWECiphertext> = GLWECiphertext::alloc(n, basek, k_ct, rank); let mut pt_want: GLWEPlaintext> = GLWEPlaintext::alloc(n, basek, k_ct); @@ -150,7 +170,7 @@ pub(crate) fn test_keyswitch_inplace( module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_ct, &mut source_xa); let mut scratch: ScratchOwned = 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 @@ pub(crate) fn test_keyswitch_inplace( scratch.borrow(), ); - let ksk_exec: GLWESwitchingKeyExec, B> = GLWESwitchingKeyExec::from(module, &ksk, scratch.borrow()); + let ksk_exec: GGLWESwitchingKeyExec, B> = GGLWESwitchingKeyExec::from(module, &ksk, scratch.borrow()); ct_glwe.keyswitch_inplace(module, &ksk_exec, scratch.borrow()); diff --git a/core/src/tests/generics/keyswitch/lwe_ct.rs b/core/src/tests/generics/keyswitch/lwe_ct.rs new file mode 100644 index 0000000..a8c0f97 --- /dev/null +++ b/core/src/tests/generics/keyswitch/lwe_ct.rs @@ -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(module: &Module) +where + Module: GGLWEEncryptSkFamily + + GLWEDecryptFamily + + VecZnxSwithcDegree + + VecZnxAddScalarInplace + + GLWEKeyswitchFamily + + VecZnxEncodeCoeffsi64 + + VecZnxAutomorphismInplace + + VmpPMatAlloc + + VmpPMatPrepare + + GLWESecretExecModuleFamily, + B: TakeScalarZnxImpl + + TakeVecZnxDftImpl + + ScratchAvailableImpl + + TakeVecZnxImpl + + TakeVecZnxBigImpl + + TakeSvpPPolImpl + + ScratchOwnedAllocImpl + + ScratchOwnedBorrowImpl, +{ + 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 = 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> = LWESecret::alloc(n_lwe_in); + sk_lwe_in.fill_ternary_prob(0.5, &mut source_xs); + + let mut sk_lwe_out: LWESecret> = 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> = 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> = 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> = 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> = LWECiphertext::alloc(n_lwe_out, basek, k_lwe_ct); + + let ksk_exec: LWESwitchingKeyExec, 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> = 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]); +} diff --git a/core/src/tests/generics/keyswitch/mod.rs b/core/src/tests/generics/keyswitch/mod.rs new file mode 100644 index 0000000..d7621db --- /dev/null +++ b/core/src/tests/generics/keyswitch/mod.rs @@ -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::*; diff --git a/core/src/tests/generics/mod.rs b/core/src/tests/generics/mod.rs new file mode 100644 index 0000000..624b9c3 --- /dev/null +++ b/core/src/tests/generics/mod.rs @@ -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::*; diff --git a/core/src/glwe/tests/packing.rs b/core/src/tests/generics/packing.rs similarity index 79% rename from core/src/glwe/tests/packing.rs rename to core/src/tests/generics/packing.rs index 806fb4f..cde7548 100644 --- a/core/src/glwe/tests/packing.rs +++ b/core/src/tests/generics/packing.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; 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 backend::hal::{ 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 = GLWEPackingFamily - + GLWESecretFamily - + GLWESwitchingKeyEncryptSkFamily +use crate::trait_families::{GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; + +pub trait PackingTestModuleFamily = GLWEPackingFamily + + GLWESecretExecModuleFamily + + GGLWESwitchingKeyEncryptSkFamily + GLWEKeyswitchFamily + GLWEDecryptFamily - + GGLWEExecLayoutFamily + VecZnxStd + VecZnxSwithcDegree + VecZnxAddScalarInplace + VecZnxEncodeVeci64 + VecZnxRotateInplace + VecZnxAutomorphism - + VecZnxBigSubSmallBInplace; + + VecZnxBigSubSmallBInplace + + VmpPMatAlloc + + VmpPMatPrepare; -pub(crate) trait PackingTestScratchFamily = TakeVecZnxDftImpl +pub trait PackingTestScratchFamily = TakeVecZnxDftImpl + TakeVecZnxBigImpl + TakeSvpPPolImpl + ScratchOwnedAllocImpl @@ -41,7 +48,7 @@ pub(crate) trait PackingTestScratchFamily = TakeVecZnxDftImpl + TakeScalarZnxImpl + TakeVecZnxImpl; -pub(crate) fn test_packing(module: &Module) +pub fn test_glwe_packing(module: &Module) where Module: PackingTestModuleFamily, B: PackingTestScratchFamily, @@ -63,7 +70,7 @@ where let mut scratch: ScratchOwned = 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 @@ where let gal_els: Vec = GLWEPacker::galois_elements(module); - let mut auto_keys: HashMap, B>> = HashMap::new(); - let mut tmp: AutomorphismKey> = AutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); + let mut auto_keys: HashMap, B>> = HashMap::new(); + let mut tmp: GGLWEAutomorphismKey> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); gal_els.iter().for_each(|gal_el| { tmp.encrypt_sk( module, @@ -93,7 +100,7 @@ where sigma, scratch.borrow(), ); - let atk_exec: AutomorphismKeyExec, B> = AutomorphismKeyExec::from(module, &tmp, scratch.borrow()); + let atk_exec: GGLWEAutomorphismKeyExec, B> = GGLWEAutomorphismKeyExec::from(module, &tmp, scratch.borrow()); auto_keys.insert(*gal_el, atk_exec); }); diff --git a/core/src/glwe/tests/trace.rs b/core/src/tests/generics/trace.rs similarity index 77% rename from core/src/glwe/tests/trace.rs rename to core/src/tests/generics/trace.rs index 7465a07..3e3ba32 100644 --- a/core/src/glwe/tests/trace.rs +++ b/core/src/tests/generics/trace.rs @@ -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 backend::hal::{ 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 = GLWESecretFamily - + GLWESwitchingKeyEncryptSkFamily +use crate::trait_families::{GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; + +pub trait TraceTestModuleFamily = GGLWESwitchingKeyEncryptSkFamily + + GLWESecretExecModuleFamily + GLWEKeyswitchFamily + GLWEDecryptFamily - + GGLWEExecLayoutFamily + VecZnxStd + VecZnxSwithcDegree + VecZnxAddScalarInplace @@ -34,9 +39,11 @@ pub(crate) trait TraceTestModuleFamily = GLWESecretFamily + VecZnxBigAutomorphismInplace + VecZnxCopy + VecZnxAutomorphism - + VecZnxRshInplace; + + VecZnxRshInplace + + VmpPMatAlloc + + VmpPMatPrepare; -pub(crate) trait TraceTestScratchFamily = TakeVecZnxDftImpl +pub trait TraceTestScratchFamily = TakeVecZnxDftImpl + TakeVecZnxBigImpl + TakeSvpPPolImpl + ScratchOwnedAllocImpl @@ -45,7 +52,7 @@ pub(crate) trait TraceTestScratchFamily = TakeVecZnxDftImpl + TakeScalarZnxImpl + TakeVecZnxImpl; -pub(crate) fn test_trace_inplace(module: &Module, basek: usize, k: usize, sigma: f64, rank: usize) +pub fn test_glwe_trace_inplace(module: &Module, basek: usize, k: usize, sigma: f64, rank: usize) where Module: TraceTestModuleFamily, B: TraceTestScratchFamily, @@ -67,7 +74,7 @@ where let mut scratch: ScratchOwned = 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 @@ where scratch.borrow(), ); - let mut auto_keys: HashMap, B>> = HashMap::new(); + let mut auto_keys: HashMap, B>> = HashMap::new(); let gal_els: Vec = GLWECiphertext::trace_galois_elements(module); - let mut tmp: AutomorphismKey> = AutomorphismKey::alloc(n, basek, k_autokey, rows, digits, rank); + let mut tmp: GGLWEAutomorphismKey> = GGLWEAutomorphismKey::alloc(n, basek, k_autokey, rows, digits, rank); gal_els.iter().for_each(|gal_el| { tmp.encrypt_sk( module, @@ -106,7 +113,7 @@ where sigma, scratch.borrow(), ); - let atk_exec: AutomorphismKeyExec, B> = AutomorphismKeyExec::from(module, &tmp, scratch.borrow()); + let atk_exec: GGLWEAutomorphismKeyExec, B> = GGLWEAutomorphismKeyExec::from(module, &tmp, scratch.borrow()); auto_keys.insert(*gal_el, atk_exec); }); diff --git a/core/src/gglwe/tests/cpu_spqlios/fft64.rs b/core/src/tests/implementation/cpu_spqlios/fft64/gglwe.rs similarity index 62% rename from core/src/gglwe/tests/cpu_spqlios/fft64.rs rename to core/src/tests/implementation/cpu_spqlios/fft64/gglwe.rs index 2ea3465..ee6a3ab 100644 --- a/core/src/gglwe/tests/cpu_spqlios/fft64.rs +++ b/core/src/tests/implementation/cpu_spqlios/fft64/gglwe.rs @@ -3,20 +3,19 @@ use backend::{ 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, +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_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, - }, - 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 = Module::::new(1 << log_n); let basek: usize = 12; @@ -26,17 +25,17 @@ fn gglwe_encrypt_sk() { (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 = Module::::new(1 << log_n); let basek: usize = 12; @@ -46,17 +45,17 @@ fn gglwe_encrypt_sk_compressed() { (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 = Module::::new(1 << log_n); let basek: usize = 12; @@ -68,11 +67,11 @@ fn gglwe_keyswitch() { (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 @@ fn gglwe_keyswitch() { } #[test] -fn gglwe_keyswitch_inplace() { +fn gglwe_switching_key_keyswitch_inplace() { let log_n: usize = 8; let module: Module = Module::::new(1 << log_n); let basek: usize = 12; @@ -102,10 +101,10 @@ fn gglwe_keyswitch_inplace() { (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 @@ fn gglwe_keyswitch_inplace() { } #[test] -fn gglwe_external_product() { +fn gglwe_switching_key_external_product() { let log_n: usize = 8; let module: Module = Module::::new(1 << log_n); let basek: usize = 12; @@ -132,11 +131,11 @@ fn gglwe_external_product() { (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 @@ fn gglwe_external_product() { } #[test] -fn gglwe_external_product_inplace() { +fn gglwe_switching_key_external_product_inplace() { let log_n: usize = 5; let module: Module = Module::::new(1 << log_n); let basek: usize = 12; @@ -156,17 +155,17 @@ fn gglwe_external_product_inplace() { (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 = Module::::new(1 << log_n); let basek: usize = 12; @@ -176,16 +175,16 @@ fn automorphism_key_encrypt_sk() { (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 = Module::::new(1 << log_n); let basek: usize = 12; @@ -195,16 +194,16 @@ fn automorphism_key_encrypt_sk_compressed() { (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 = Module::::new(1 << log_n); let basek: usize = 12; @@ -214,15 +213,18 @@ fn gglwe_automorphism() { 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 = Module::::new(1 << log_n); let basek: usize = 12; @@ -231,29 +233,32 @@ fn gglwe_automorphism_inplace() { 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 = Module::::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 = Module::::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); }); } diff --git a/core/src/ggsw/test/cpu_spqlios/fft64.rs b/core/src/tests/implementation/cpu_spqlios/fft64/ggws.rs similarity index 62% rename from core/src/ggsw/test/cpu_spqlios/fft64.rs rename to core/src/tests/implementation/cpu_spqlios/fft64/ggws.rs index f18815c..9dcb11b 100644 --- a/core/src/ggsw/test/cpu_spqlios/fft64.rs +++ b/core/src/tests/implementation/cpu_spqlios/fft64/ggws.rs @@ -3,13 +3,15 @@ use backend::{ 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 = Module::::new(1 << log_n); let basek: usize = 12; @@ -17,14 +19,14 @@ fn encrypt_sk() { 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 = Module::::new(1 << log_n); let basek: usize = 12; @@ -32,14 +34,17 @@ fn encrypt_sk_compressed() { 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 = Module::::new(1 << log_n); let basek: usize = 12; @@ -49,15 +54,15 @@ fn keyswitch() { (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 = Module::::new(1 << log_n); let basek: usize = 12; @@ -67,14 +72,14 @@ fn keyswitch_inplace() { (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 = Module::::new(1 << log_n); let basek: usize = 12; @@ -84,15 +89,15 @@ fn automorphism() { (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 = Module::::new(1 << log_n); let basek: usize = 12; @@ -102,14 +107,14 @@ fn automorphism_inplace() { (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 = Module::::new(1 << log_n); let basek: usize = 12; @@ -120,13 +125,13 @@ fn external_product() { 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 = Module::::new(1 << log_n); let basek: usize = 12; @@ -135,8 +140,11 @@ fn external_product_inplace() { (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); }); }); } diff --git a/core/src/glwe/tests/cpu_spqlios/fft64.rs b/core/src/tests/implementation/cpu_spqlios/fft64/glwe.rs similarity index 57% rename from core/src/glwe/tests/cpu_spqlios/fft64.rs rename to core/src/tests/implementation/cpu_spqlios/fft64/glwe.rs index 5f7135f..1a8b399 100644 --- a/core/src/glwe/tests/cpu_spqlios/fft64.rs +++ b/core/src/tests/implementation/cpu_spqlios/fft64/glwe.rs @@ -3,57 +3,56 @@ use backend::{ 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, +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 encrypt_sk() { +fn glwe_encrypt_sk() { let log_n: usize = 8; let module: Module = Module::::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); + println!("test_glwe_encrypt_sk rank: {}", rank); + test_glwe_encrypt_sk(&module, 8, 54, 30, 3.2, rank); }); } #[test] -fn encrypt_sk_compressed() { +fn glwe_compressed_encrypt_sk() { let log_n: usize = 8; let module: Module = Module::::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); + println!("test_glwe_compressed_encrypt_sk rank: {}", rank); + test_glwe_compressed_encrypt_sk(&module, 8, 54, 30, 3.2, rank); }); } #[test] -fn encrypt_zero_sk() { +fn glwe_encrypt_zero_sk() { let log_n: usize = 8; let module: Module = Module::::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); + println!("test_glwe_encrypt_zero_sk rank: {}", rank); + test_glwe_encrypt_zero_sk(&module, 8, 64, 3.2, rank); }); } #[test] -fn encrypt_pk() { +fn glwe_encrypt_pk() { let log_n: usize = 8; let module: Module = Module::::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) + println!("test_glwe_encrypt_pk rank: {}", rank); + test_glwe_encrypt_pk(&module, 8, 64, 64, 3.2, rank) }); } #[test] -fn apply() { +fn glwe_keyswitch() { let log_n: usize = 8; let module: Module = Module::::new(1 << log_n); let basek: usize = 12; @@ -65,10 +64,10 @@ fn apply() { 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: {}", + "test_glwe_keyswitch digits: {} rank_in: {} rank_out: {}", di, rank_in, rank_out ); - test_keyswitch( + test_glwe_keyswitch( &module, basek, k_out, k_in, k_ksk, di, rank_in, rank_out, 3.2, ); }) @@ -77,7 +76,7 @@ fn apply() { } #[test] -fn apply_inplace() { +fn glwe_keyswitch_inplace() { let log_n: usize = 8; let module: Module = Module::::new(1 << log_n); let basek: usize = 12; @@ -86,30 +85,14 @@ fn apply_inplace() { (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); + 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 automorphism_inplace() { - let log_n: usize = 8; - let module: Module = Module::::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() { +fn glwe_automorphism() { let log_n: usize = 8; let module: Module = Module::::new(1 << log_n); let basek: usize = 12; @@ -119,14 +102,33 @@ fn automorphism() { (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); + 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 external_product() { +fn glwe_automorphism_inplace() { + let log_n: usize = 8; + let module: Module = Module::::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 = Module::::new(1 << log_n); let basek: usize = 12; @@ -136,14 +138,14 @@ fn external_product() { (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); + 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 external_product_inplace() { +fn glwe_external_product_inplace() { let log_n: usize = 8; let module: Module = Module::::new(1 << log_n); let basek: usize = 12; @@ -152,25 +154,28 @@ fn external_product_inplace() { (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); + 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 trace_inplace() { +fn glwe_trace_inplace() { let log_n: usize = 8; let module: Module = Module::::new(1 << log_n); (1..4).for_each(|rank| { - println!("test trace_inplace rank: {}", rank); - test_trace_inplace(&module, 8, 54, 3.2, rank); + println!("test_glwe_trace_inplace rank: {}", rank); + test_glwe_trace_inplace(&module, 8, 54, 3.2, rank); }); } #[test] -fn packing() { +fn glwe_packing() { let log_n: usize = 5; let module: Module = Module::::new(1 << log_n); - test_packing(&module); + test_glwe_packing(&module); } diff --git a/core/src/lwe/tests/cpu_spqlios/fft64.rs b/core/src/tests/implementation/cpu_spqlios/fft64/lwe.rs similarity index 77% rename from core/src/lwe/tests/cpu_spqlios/fft64.rs rename to core/src/tests/implementation/cpu_spqlios/fft64/lwe.rs index 0620b5a..c1ea6d5 100644 --- a/core/src/lwe/tests/cpu_spqlios/fft64.rs +++ b/core/src/tests/implementation/cpu_spqlios/fft64/lwe.rs @@ -3,7 +3,7 @@ use backend::{ 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 @@ fn glwe_to_lwe() { } #[test] -fn keyswitch() { +fn lwe_keyswitch() { let log_n: usize = 5; let module: Module = Module::::new(1 << log_n); - test_keyswitch(&module) + test_lwe_keyswitch(&module) } diff --git a/core/src/tests/implementation/cpu_spqlios/fft64/mod.rs b/core/src/tests/implementation/cpu_spqlios/fft64/mod.rs new file mode 100644 index 0000000..444225a --- /dev/null +++ b/core/src/tests/implementation/cpu_spqlios/fft64/mod.rs @@ -0,0 +1,4 @@ +mod gglwe; +mod ggws; +mod glwe; +mod lwe; diff --git a/core/src/gglwe/tests/cpu_spqlios/mod.rs b/core/src/tests/implementation/cpu_spqlios/mod.rs similarity index 100% rename from core/src/gglwe/tests/cpu_spqlios/mod.rs rename to core/src/tests/implementation/cpu_spqlios/mod.rs diff --git a/core/src/tests/implementation/mod.rs b/core/src/tests/implementation/mod.rs new file mode 100644 index 0000000..f2bc1d4 --- /dev/null +++ b/core/src/tests/implementation/mod.rs @@ -0,0 +1 @@ +mod cpu_spqlios; diff --git a/core/src/tests/mod.rs b/core/src/tests/mod.rs new file mode 100644 index 0000000..4120448 --- /dev/null +++ b/core/src/tests/mod.rs @@ -0,0 +1,7 @@ +pub mod generics; + +#[cfg(test)] +mod implementation; + +#[cfg(test)] +mod serialization; diff --git a/core/src/tests/serialization.rs b/core/src/tests/serialization.rs new file mode 100644 index 0000000..8199723 --- /dev/null +++ b/core/src/tests/serialization.rs @@ -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> = GLWECiphertext::alloc(N_GLWE, BASEK, K, RANK); + backend::hal::tests::serialization::test_reader_writer_interface(original); +} + +#[test] +fn glwe_compressed_serialization() { + let original: GLWECiphertextCompressed> = GLWECiphertextCompressed::alloc(N_GLWE, BASEK, K, RANK); + test_reader_writer_interface(original); +} + +#[test] +fn lwe_serialization() { + let original: LWECiphertext> = LWECiphertext::alloc(N_LWE, BASEK, K); + test_reader_writer_interface(original); +} + +#[test] +fn lwe_compressed_serialization() { + let original: LWECiphertextCompressed> = LWECiphertextCompressed::alloc(BASEK, K); + test_reader_writer_interface(original); +} + +#[test] +fn test_gglwe_serialization() { + let original: GGLWECiphertext> = GGLWECiphertext::alloc(1024, 12, 54, 3, 1, 2, 2); + test_reader_writer_interface(original); +} + +#[test] +fn test_gglwe_compressed_serialization() { + let original: GGLWECiphertextCompressed> = GGLWECiphertextCompressed::alloc(1024, 12, 54, 3, 1, 2, 2); + test_reader_writer_interface(original); +} + +#[test] +fn test_glwe_switching_key_serialization() { + let original: GGLWESwitchingKey> = 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> = GGLWESwitchingKeyCompressed::alloc(1024, 12, 54, 3, 1, 2, 2); + test_reader_writer_interface(original); +} + +#[test] +fn test_automorphism_key_serialization() { + let original: GGLWEAutomorphismKey> = GGLWEAutomorphismKey::alloc(1024, 12, 54, 3, 1, 2); + test_reader_writer_interface(original); +} + +#[test] +fn test_automorphism_key_compressed_serialization() { + let original: GGLWEAutomorphismKeyCompressed> = GGLWEAutomorphismKeyCompressed::alloc(1024, 12, 54, 3, 1, 2); + test_reader_writer_interface(original); +} + +#[test] +fn test_tensor_key_serialization() { + let original: GGLWETensorKey> = GGLWETensorKey::alloc(1024, 12, 54, 3, 1, 2); + test_reader_writer_interface(original); +} + +#[test] +fn test_tensor_key_compressed_serialization() { + let original: GGLWETensorKeyCompressed> = GGLWETensorKeyCompressed::alloc(1024, 12, 54, 3, 1, 2); + test_reader_writer_interface(original); +} + +#[test] +fn glwe_to_lwe_switching_key_serialization() { + let original: GLWEToLWESwitchingKey> = 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> = GLWEToLWESwitchingKeyCompressed::alloc(N_GLWE, BASEK, K, ROWS, RANK); + test_reader_writer_interface(original); +} + +#[test] +fn lwe_to_glwe_switching_key_serialization() { + let original: LWEToGLWESwitchingKey> = 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> = LWEToGLWESwitchingKeyCompressed::alloc(N_GLWE, BASEK, K, ROWS, RANK); + test_reader_writer_interface(original); +} + +#[test] +fn lwe_switching_key_serialization() { + let original: LWESwitchingKey> = LWESwitchingKey::alloc(N_GLWE, BASEK, K, ROWS); + test_reader_writer_interface(original); +} + +#[test] +fn lwe_switching_key_compressed_serialization() { + let original: LWESwitchingKeyCompressed> = LWESwitchingKeyCompressed::alloc(N_GLWE, BASEK, K, ROWS); + test_reader_writer_interface(original); +} + +#[test] +fn ggsw_serialization() { + let original: GGSWCiphertext> = GGSWCiphertext::alloc(N_GLWE, BASEK, K, ROWS, DIGITS, RANK); + test_reader_writer_interface(original); +} + +#[test] +fn ggsw_compressed_serialization() { + let original: GGSWCiphertextCompressed> = GGSWCiphertextCompressed::alloc(N_GLWE, BASEK, K, ROWS, DIGITS, RANK); + test_reader_writer_interface(original); +} diff --git a/core/src/trait_families.rs b/core/src/trait_families.rs new file mode 100644 index 0000000..0c14696 --- /dev/null +++ b/core/src/trait_families.rs @@ -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 = + GLWEKeyswitchFamily + VecZnxBigAllocBytes + VecZnxDftCopy + VecZnxDftAddInplace + VecZnxDftToVecZnxBigTmpA; +pub trait GGLWEEncryptSkFamily = GLWEEncryptSkFamily; +pub trait GGLWESwitchingKeyEncryptSkFamily = GGLWEEncryptSkFamily; +pub trait GGLWEAutomorphismKeyEncryptSkFamily = GGLWEEncryptSkFamily; +pub trait GGLWETensorKeyEncryptSkFamily = + GGLWEEncryptSkFamily + VecZnxBigAllocBytes + VecZnxDftToVecZnxBigTmpA + SvpApply; +pub trait GGSWEncryptSkFamily = GLWEEncryptSkFamily; +pub trait GGSWAssertNoiseFamily = GLWEDecryptFamily + + VecZnxBigAlloc + + VecZnxDftAlloc + + VecZnxBigNormalizeTmpBytes + + VecZnxBigNormalize + + VecZnxDftToVecZnxBigTmpA; +pub trait GLWEDecryptFamily = VecZnxDftAllocBytes + + VecZnxBigAllocBytes + + VecZnxDftFromVecZnx + + SvpApplyInplace + + VecZnxDftToVecZnxBigConsume + + VecZnxBigAddInplace + + VecZnxBigAddSmallInplace + + VecZnxBigNormalize + + VecZnxNormalizeTmpBytes; +pub trait GLWEEncryptSkFamily = VecZnxDftAllocBytes + + VecZnxBigNormalize + + VecZnxDftFromVecZnx + + SvpApplyInplace + + VecZnxDftToVecZnxBigConsume + + VecZnxNormalizeTmpBytes + + VecZnxFillUniform + + VecZnxSubABInplace + + VecZnxAddInplace + + VecZnxNormalizeInplace + + VecZnxAddNormal + + VecZnxNormalize + + VecZnxSub; +pub trait GLWEEncryptPkFamily = VecZnxDftAllocBytes + + VecZnxBigAllocBytes + + SvpPPolAllocBytes + + SvpPrepare + + SvpApply + + VecZnxDftToVecZnxBigConsume + + VecZnxBigAddNormal + + VecZnxBigAddSmallInplace + + VecZnxBigNormalize + + VecZnxNormalizeTmpBytes; +pub trait GLWEExternalProductFamily = VecZnxDftAllocBytes + + VmpApplyTmpBytes + + VmpApply + + VmpApplyAdd + + VecZnxDftFromVecZnx + + VecZnxDftToVecZnxBigConsume + + VecZnxBigNormalize + + VecZnxNormalizeTmpBytes; +pub trait GLWEKeyswitchFamily = VecZnxDftAllocBytes + + VmpApplyTmpBytes + + VecZnxBigNormalizeTmpBytes + + VmpApplyTmpBytes + + VmpApply + + VmpApplyAdd + + VecZnxDftFromVecZnx + + VecZnxDftToVecZnxBigConsume + + VecZnxBigAddSmallInplace + + VecZnxBigNormalize; +pub trait GLWEPackingFamily = GLWEKeyswitchFamily + + VecZnxCopy + + VecZnxRotateInplace + + VecZnxSub + + VecZnxNegateInplace + + VecZnxRshInplace + + VecZnxAddInplace + + VecZnxNormalizeInplace + + VecZnxSubABInplace + + VecZnxRotate + + VecZnxAutomorphismInplace + + VecZnxBigSubSmallBInplace + + VecZnxBigAutomorphismInplace; +pub trait GLWESecretExecModuleFamily = SvpPrepare + SvpPPolAllocBytes + SvpPPolAlloc; +pub trait GGLWEExecLayoutFamily = VmpPMatAlloc + VmpPMatAllocBytes + VmpPMatPrepare; +pub trait GLWETraceModuleFamily = + GLWEKeyswitchFamily + VecZnxCopy + VecZnxRshInplace + VecZnxBigAutomorphismInplace; +pub trait GLWETraceScratchFamily = TakeVecZnxDft + ScratchAvailable; +pub trait GGSWLayoutFamily = VmpPMatAlloc + VmpPMatAllocBytes + VmpPMatPrepare; + +pub trait DecompressFamily = VecZnxFillUniform + VecZnxCopy; +pub trait Decompress { + fn decompress(&mut self, module: &Module, other: &C) + where + Module: DecompressFamily; +}