diff --git a/core/src/automorphism.rs b/core/src/automorphism.rs index f91ba41..3032532 100644 --- a/core/src/automorphism.rs +++ b/core/src/automorphism.rs @@ -2,7 +2,7 @@ use backend::{Backend, FFT64, MatZnxDft, MatZnxDftOps, Module, ScalarZnxOps, Scr use sampling::source::Source; use crate::{ - GGLWECiphertext, GGSWCiphertext, GLWECiphertext, GLWECiphertextFourier, GLWESecret, GLWESwitchingKey, GetRow, Infos, + FourierGLWECiphertext, GGLWECiphertext, GGSWCiphertext, GLWECiphertext, GLWESecret, GLWESwitchingKey, GetRow, Infos, ScratchCore, SetRow, }; @@ -68,7 +68,7 @@ impl> GetRow for AutomorphismKey { module: &Module, row_i: usize, col_j: usize, - res: &mut GLWECiphertextFourier, + res: &mut FourierGLWECiphertext, ) { module.mat_znx_dft_get_row(&mut res.data, &self.key.0.data, row_i, col_j); } @@ -80,7 +80,7 @@ impl + AsRef<[u8]>> SetRow for AutomorphismKey { module: &Module, row_i: usize, col_j: usize, - a: &GLWECiphertextFourier, + a: &FourierGLWECiphertext, ) { module.mat_znx_dft_set_row(&mut self.key.0.data, row_i, col_j, &a.data); } @@ -127,8 +127,8 @@ impl AutomorphismKey, FFT64> { digits: usize, rank: usize, ) -> usize { - let tmp_dft: usize = GLWECiphertextFourier::bytes_of(module, basek, k_in, rank); - let tmp_idft: usize = GLWECiphertextFourier::bytes_of(module, basek, k_out, rank); + let tmp_dft: usize = FourierGLWECiphertext::bytes_of(module, basek, k_in, rank); + let tmp_idft: usize = FourierGLWECiphertext::bytes_of(module, basek, k_out, rank); let idft: usize = module.vec_znx_idft_tmp_bytes(); let keyswitch: usize = GLWECiphertext::keyswitch_inplace_scratch_space(module, basek, k_out, k_ksk, digits, rank); tmp_dft + tmp_idft + idft + keyswitch diff --git a/core/src/blind_rotation/key.rs b/core/src/blind_rotation/key.rs index b4c5d40..ff4a887 100644 --- a/core/src/blind_rotation/key.rs +++ b/core/src/blind_rotation/key.rs @@ -23,6 +23,10 @@ impl BlindRotationKeyCGGI { } } + pub fn generate_from_sk_scratch_space(module: &Module, basek: usize, k: usize, rank: usize) -> usize { + GGSWCiphertext::encrypt_sk_scratch_space(module, basek, k, rank) + } + pub fn generate_from_sk( &mut self, module: &Module, diff --git a/core/src/elem.rs b/core/src/elem.rs index ae7e5f7..e659e1e 100644 --- a/core/src/elem.rs +++ b/core/src/elem.rs @@ -1,6 +1,6 @@ use backend::{Backend, Module, ZnxInfos}; -use crate::GLWECiphertextFourier; +use crate::{FourierGLWECiphertext, div_ceil}; pub trait Infos { type Inner: ZnxInfos; @@ -56,13 +56,13 @@ pub trait SetMetaData { } pub trait GetRow { - fn get_row(&self, module: &Module, row_i: usize, col_j: usize, res: &mut GLWECiphertextFourier) + fn get_row(&self, module: &Module, row_i: usize, col_j: usize, res: &mut FourierGLWECiphertext) where R: AsMut<[u8]> + AsRef<[u8]>; } pub trait SetRow { - fn set_row(&mut self, module: &Module, row_i: usize, col_j: usize, a: &GLWECiphertextFourier) + fn set_row(&mut self, module: &Module, row_i: usize, col_j: usize, a: &FourierGLWECiphertext) where R: AsRef<[u8]>; } diff --git a/core/src/glwe_ciphertext_fourier.rs b/core/src/fourier_glwe.rs similarity index 93% rename from core/src/glwe_ciphertext_fourier.rs rename to core/src/fourier_glwe.rs index 19582f6..0e024a9 100644 --- a/core/src/glwe_ciphertext_fourier.rs +++ b/core/src/fourier_glwe.rs @@ -6,13 +6,13 @@ use sampling::source::Source; use crate::{GGSWCiphertext, GLWECiphertext, GLWEPlaintext, GLWESecret, GLWESwitchingKey, Infos, ScratchCore}; -pub struct GLWECiphertextFourier { +pub struct FourierGLWECiphertext { pub data: VecZnxDft, pub basek: usize, pub k: usize, } -impl GLWECiphertextFourier, B> { +impl FourierGLWECiphertext, B> { pub fn alloc(module: &Module, basek: usize, k: usize, rank: usize) -> Self { Self { data: module.new_vec_znx_dft(rank + 1, k.div_ceil(basek)), @@ -26,7 +26,7 @@ impl GLWECiphertextFourier, B> { } } -impl Infos for GLWECiphertextFourier { +impl Infos for FourierGLWECiphertext { type Inner = VecZnxDft; fn inner(&self) -> &Self::Inner { @@ -42,13 +42,13 @@ impl Infos for GLWECiphertextFourier { } } -impl GLWECiphertextFourier { +impl FourierGLWECiphertext { pub fn rank(&self) -> usize { self.cols() - 1 } } -impl GLWECiphertextFourier, FFT64> { +impl FourierGLWECiphertext, FFT64> { #[allow(dead_code)] pub(crate) fn idft_scratch_space(module: &Module, basek: usize, k: usize) -> usize { module.bytes_of_vec_znx(1, k.div_ceil(basek)) @@ -125,7 +125,7 @@ impl GLWECiphertextFourier, FFT64> { } } -impl + AsRef<[u8]>> GLWECiphertextFourier { +impl + AsRef<[u8]>> FourierGLWECiphertext { pub fn encrypt_zero_sk>( &mut self, module: &Module, @@ -143,7 +143,7 @@ impl + AsRef<[u8]>> GLWECiphertextFourier pub fn keyswitch, DataRhs: AsRef<[u8]>>( &mut self, module: &Module, - lhs: &GLWECiphertextFourier, + lhs: &FourierGLWECiphertext, rhs: &GLWESwitchingKey, scratch: &mut Scratch, ) { @@ -159,7 +159,7 @@ impl + AsRef<[u8]>> GLWECiphertextFourier scratch: &mut Scratch, ) { unsafe { - let self_ptr: *mut GLWECiphertextFourier = self as *mut GLWECiphertextFourier; + let self_ptr: *mut FourierGLWECiphertext = self as *mut FourierGLWECiphertext; self.keyswitch(&module, &*self_ptr, rhs, scratch); } } @@ -167,7 +167,7 @@ impl + AsRef<[u8]>> GLWECiphertextFourier pub fn external_product, DataRhs: AsRef<[u8]>>( &mut self, module: &Module, - lhs: &GLWECiphertextFourier, + lhs: &FourierGLWECiphertext, rhs: &GGSWCiphertext, scratch: &mut Scratch, ) { @@ -184,7 +184,7 @@ impl + AsRef<[u8]>> GLWECiphertextFourier assert_eq!(lhs.n(), module.n()); assert!( scratch.available() - >= GLWECiphertextFourier::external_product_scratch_space( + >= FourierGLWECiphertext::external_product_scratch_space( module, self.basek(), self.k(), @@ -246,13 +246,13 @@ impl + AsRef<[u8]>> GLWECiphertextFourier scratch: &mut Scratch, ) { unsafe { - let self_ptr: *mut GLWECiphertextFourier = self as *mut GLWECiphertextFourier; + let self_ptr: *mut FourierGLWECiphertext = self as *mut FourierGLWECiphertext; self.external_product(&module, &*self_ptr, rhs, scratch); } } } -impl> GLWECiphertextFourier { +impl> FourierGLWECiphertext { pub fn decrypt + AsMut<[u8]>, DataSk: AsRef<[u8]>>( &self, module: &Module, diff --git a/core/src/gglwe_ciphertext.rs b/core/src/gglwe.rs similarity index 97% rename from core/src/gglwe_ciphertext.rs rename to core/src/gglwe.rs index e9f9684..66a5238 100644 --- a/core/src/gglwe_ciphertext.rs +++ b/core/src/gglwe.rs @@ -4,7 +4,7 @@ use backend::{ }; use sampling::source::Source; -use crate::{GLWECiphertext, GLWECiphertextFourier, GLWESecret, GetRow, Infos, ScratchCore, SetRow}; +use crate::{FourierGLWECiphertext, GLWECiphertext, GLWESecret, GetRow, Infos, ScratchCore, SetRow, div_ceil}; pub struct GGLWECiphertext { pub(crate) data: MatZnxDft, @@ -217,7 +217,7 @@ impl> GetRow for GGLWECiphertext { module: &Module, row_i: usize, col_j: usize, - res: &mut GLWECiphertextFourier, + res: &mut FourierGLWECiphertext, ) { module.mat_znx_dft_get_row(&mut res.data, &self.data, row_i, col_j); } @@ -229,7 +229,7 @@ impl + AsRef<[u8]>> SetRow for GGLWECiphertext { module: &Module, row_i: usize, col_j: usize, - a: &GLWECiphertextFourier, + a: &FourierGLWECiphertext, ) { module.mat_znx_dft_set_row(&mut self.data, row_i, col_j, &a.data); } diff --git a/core/src/ggsw_ciphertext.rs b/core/src/ggsw.rs similarity index 98% rename from core/src/ggsw_ciphertext.rs rename to core/src/ggsw.rs index ff1f1e7..38842df 100644 --- a/core/src/ggsw_ciphertext.rs +++ b/core/src/ggsw.rs @@ -6,8 +6,8 @@ use backend::{ use sampling::source::Source; use crate::{ - AutomorphismKey, GLWECiphertext, GLWECiphertextFourier, GLWESecret, GLWESwitchingKey, GetRow, Infos, ScratchCore, SetRow, - TensorKey, + AutomorphismKey, FourierGLWECiphertext, GLWECiphertext, GLWESecret, GLWESwitchingKey, GetRow, Infos, ScratchCore, SetRow, + TensorKey, div_ceil, }; pub struct GGSWCiphertext { @@ -220,9 +220,9 @@ impl GGSWCiphertext, FFT64> { digits: usize, rank: usize, ) -> usize { - let tmp_in: usize = GLWECiphertextFourier::bytes_of(module, basek, k_in, rank); - let tmp_out: usize = GLWECiphertextFourier::bytes_of(module, basek, k_out, rank); - let ggsw: usize = GLWECiphertextFourier::external_product_scratch_space(module, basek, k_out, k_in, k_ggsw, digits, rank); + let tmp_in: usize = FourierGLWECiphertext::bytes_of(module, basek, k_in, rank); + let tmp_out: usize = FourierGLWECiphertext::bytes_of(module, basek, k_out, rank); + let ggsw: usize = FourierGLWECiphertext::external_product_scratch_space(module, basek, k_out, k_in, k_ggsw, digits, rank); tmp_in + tmp_out + ggsw } @@ -234,9 +234,9 @@ impl GGSWCiphertext, FFT64> { digits: usize, rank: usize, ) -> usize { - let tmp: usize = GLWECiphertextFourier::bytes_of(module, basek, k_out, rank); + let tmp: usize = FourierGLWECiphertext::bytes_of(module, basek, k_out, rank); let ggsw: usize = - GLWECiphertextFourier::external_product_inplace_scratch_space(module, basek, k_out, k_ggsw, digits, rank); + FourierGLWECiphertext::external_product_inplace_scratch_space(module, basek, k_out, k_ggsw, digits, rank); tmp + ggsw } } @@ -686,7 +686,7 @@ impl> GetRow for GGSWCiphertext { module: &Module, row_i: usize, col_j: usize, - res: &mut GLWECiphertextFourier, + res: &mut FourierGLWECiphertext, ) { module.mat_znx_dft_get_row(&mut res.data, &self.data, row_i, col_j); } @@ -698,7 +698,7 @@ impl + AsRef<[u8]>> SetRow for GGSWCiphertext, row_i: usize, col_j: usize, - a: &GLWECiphertextFourier, + a: &FourierGLWECiphertext, ) { module.mat_znx_dft_set_row(&mut self.data, row_i, col_j, &a.data); } diff --git a/core/src/glwe/automorphism.rs b/core/src/glwe/automorphism.rs new file mode 100644 index 0000000..a4165aa --- /dev/null +++ b/core/src/glwe/automorphism.rs @@ -0,0 +1,121 @@ +use backend::{FFT64, Module, Scratch, VecZnxOps}; + +use crate::{AutomorphismKey, GLWECiphertext}; + +impl GLWECiphertext> { + pub fn automorphism_scratch_space( + module: &Module, + basek: usize, + k_out: usize, + k_in: usize, + k_ksk: usize, + digits: usize, + rank: usize, + ) -> usize { + Self::keyswitch_scratch_space(module, basek, k_out, k_in, k_ksk, digits, rank, rank) + } + + pub fn automorphism_inplace_scratch_space( + module: &Module, + basek: usize, + k_out: usize, + k_ksk: usize, + digits: usize, + rank: usize, + ) -> usize { + Self::keyswitch_inplace_scratch_space(module, basek, k_out, k_ksk, digits, rank) + } +} + +impl + AsMut<[u8]>> GLWECiphertext { + pub fn automorphism, DataRhs: AsRef<[u8]>>( + &mut self, + module: &Module, + lhs: &GLWECiphertext, + rhs: &AutomorphismKey, + scratch: &mut Scratch, + ) { + self.keyswitch(module, lhs, &rhs.key, scratch); + (0..self.rank() + 1).for_each(|i| { + module.vec_znx_automorphism_inplace(rhs.p(), &mut self.data, i); + }) + } + + pub fn automorphism_inplace>( + &mut self, + module: &Module, + rhs: &AutomorphismKey, + scratch: &mut Scratch, + ) { + self.keyswitch_inplace(module, &rhs.key, scratch); + (0..self.rank() + 1).for_each(|i| { + module.vec_znx_automorphism_inplace(rhs.p(), &mut self.data, i); + }) + } + + pub fn automorphism_add, DataRhs: AsRef<[u8]>>( + &mut self, + module: &Module, + lhs: &GLWECiphertext, + rhs: &AutomorphismKey, + scratch: &mut Scratch, + ) { + Self::keyswitch_private::<_, _, 1>(self, rhs.p(), module, lhs, &rhs.key, scratch); + } + + pub fn automorphism_add_inplace>( + &mut self, + module: &Module, + rhs: &AutomorphismKey, + scratch: &mut Scratch, + ) { + unsafe { + let self_ptr: *mut GLWECiphertext = self as *mut GLWECiphertext; + Self::keyswitch_private::<_, _, 1>(self, rhs.p(), module, &*self_ptr, &rhs.key, scratch); + } + } + + pub fn automorphism_sub_ab, DataRhs: AsRef<[u8]>>( + &mut self, + module: &Module, + lhs: &GLWECiphertext, + rhs: &AutomorphismKey, + scratch: &mut Scratch, + ) { + Self::keyswitch_private::<_, _, 2>(self, rhs.p(), module, lhs, &rhs.key, scratch); + } + + pub fn automorphism_sub_ab_inplace>( + &mut self, + module: &Module, + rhs: &AutomorphismKey, + scratch: &mut Scratch, + ) { + unsafe { + let self_ptr: *mut GLWECiphertext = self as *mut GLWECiphertext; + Self::keyswitch_private::<_, _, 2>(self, rhs.p(), module, &*self_ptr, &rhs.key, scratch); + } + } + + pub fn automorphism_sub_ba, DataRhs: AsRef<[u8]>>( + &mut self, + module: &Module, + lhs: &GLWECiphertext, + rhs: &AutomorphismKey, + scratch: &mut Scratch, + ) { + Self::keyswitch_private::<_, _, 3>(self, rhs.p(), module, lhs, &rhs.key, scratch); + } + + pub fn automorphism_sub_ba_inplace>( + &mut self, + module: &Module, + rhs: &AutomorphismKey, + scratch: &mut Scratch, + ) { + unsafe { + let self_ptr: *mut GLWECiphertext = self as *mut GLWECiphertext; + Self::keyswitch_private::<_, _, 3>(self, rhs.p(), module, &*self_ptr, &rhs.key, scratch); + } + } +} diff --git a/core/src/glwe/ciphertext.rs b/core/src/glwe/ciphertext.rs new file mode 100644 index 0000000..ff634bd --- /dev/null +++ b/core/src/glwe/ciphertext.rs @@ -0,0 +1,115 @@ +use backend::{ + Backend, FFT64, Module, VecZnx, VecZnxAlloc, VecZnxBigAlloc, VecZnxBigScratch, VecZnxDftAlloc, VecZnxDftOps, VecZnxToMut, + VecZnxToRef, +}; + +use crate::{FourierGLWECiphertext, GLWEOps, Infos, SetMetaData, div_ceil}; + +pub struct GLWECiphertext { + pub data: VecZnx, + pub basek: usize, + pub k: usize, +} + +impl GLWECiphertext> { + pub fn alloc(module: &Module, basek: usize, k: usize, rank: usize) -> Self { + Self { + data: module.new_vec_znx(rank + 1, div_ceil(k, basek)), + basek, + k, + } + } + + pub fn bytes_of(module: &Module, basek: usize, k: usize, rank: usize) -> usize { + module.bytes_of_vec_znx(rank + 1, div_ceil(k, 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 { + #[allow(dead_code)] + pub(crate) fn dft + AsRef<[u8]>>(&self, module: &Module, res: &mut FourierGLWECiphertext) { + #[cfg(debug_assertions)] + { + assert_eq!(self.rank(), res.rank()); + assert_eq!(self.basek(), res.basek()) + } + + (0..self.rank() + 1).for_each(|i| { + module.vec_znx_dft(1, 0, &mut res.data, i, &self.data, i); + }) + } +} + +impl GLWECiphertext> { + pub fn decrypt_scratch_space(module: &Module, basek: usize, k: usize) -> usize { + let size: usize = div_ceil(k, basek); + (module.vec_znx_big_normalize_tmp_bytes() | module.bytes_of_vec_znx_dft(1, size)) + module.bytes_of_vec_znx_big(1, size) + } +} + +impl + AsRef<[u8]>> 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 { + 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 { + fn to_mut(&mut self) -> GLWECiphertext<&mut [u8]>; +} + +impl + AsRef<[u8]>> 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 + D: AsRef<[u8]> + AsMut<[u8]>, + GLWECiphertext: GLWECiphertextToMut + Infos + SetMetaData, +{ +} diff --git a/core/src/glwe/decryption.rs b/core/src/glwe/decryption.rs new file mode 100644 index 0000000..dd6428d --- /dev/null +++ b/core/src/glwe/decryption.rs @@ -0,0 +1,56 @@ +use backend::{FFT64, Module, ScalarZnxDftOps, Scratch, VecZnxBigOps, VecZnxDftOps, ZnxZero}; + +use crate::{GLWECiphertext, GLWEPlaintext, GLWESecret, Infos}; + +impl> GLWECiphertext { + pub fn clone(&self) -> GLWECiphertext> { + GLWECiphertext { + data: self.data.clone(), + basek: self.basek(), + k: self.k(), + } + } + + pub fn decrypt + AsRef<[u8]>, DataSk: AsRef<[u8]>>( + &self, + module: &Module, + pt: &mut GLWEPlaintext, + sk: &GLWESecret, + scratch: &mut Scratch, + ) { + #[cfg(debug_assertions)] + { + assert_eq!(self.rank(), sk.rank()); + assert_eq!(self.n(), module.n()); + assert_eq!(pt.n(), module.n()); + assert_eq!(sk.n(), module.n()); + } + + let cols: usize = self.rank() + 1; + + let (mut c0_big, scratch_1) = scratch.tmp_vec_znx_big(module, 1, self.size()); // TODO optimize size when pt << ct + c0_big.zero(); + + { + (1..cols).for_each(|i| { + // ci_dft = DFT(a[i]) * DFT(s[i]) + let (mut ci_dft, _) = scratch_1.tmp_vec_znx_dft(module, 1, self.size()); // TODO optimize size when pt << ct + module.vec_znx_dft(1, 0, &mut ci_dft, 0, &self.data, i); + module.svp_apply_inplace(&mut ci_dft, 0, &sk.data_fourier, i - 1); + let ci_big = module.vec_znx_idft_consume(ci_dft); + + // c0_big += a[i] * s[i] + module.vec_znx_big_add_inplace(&mut c0_big, 0, &ci_big, 0); + }); + } + + // c0_big = (a * s) + (-a * s + m + e) = BIG(m + e) + module.vec_znx_big_add_small_inplace(&mut c0_big, 0, &self.data, 0); + + // pt = norm(BIG(m + e)) + module.vec_znx_big_normalize(self.basek(), &mut pt.data, 0, &mut c0_big, 0, scratch_1); + + pt.basek = self.basek(); + pt.k = pt.k().min(self.k()); + } +} diff --git a/core/src/glwe/encryption.rs b/core/src/glwe/encryption.rs new file mode 100644 index 0000000..1910f98 --- /dev/null +++ b/core/src/glwe/encryption.rs @@ -0,0 +1,254 @@ +use backend::{ + AddNormal, FFT64, FillUniform, Module, ScalarZnxAlloc, ScalarZnxDftAlloc, ScalarZnxDftOps, Scratch, VecZnxAlloc, VecZnxBig, + VecZnxBigAlloc, VecZnxBigOps, VecZnxBigScratch, VecZnxDftAlloc, VecZnxDftOps, VecZnxOps, ZnxZero, +}; +use sampling::source::Source; + +use crate::{GLWECiphertext, GLWEPlaintext, GLWEPublicKey, GLWESecret, Infos, SIX_SIGMA, div_ceil, keys::SecretDistribution}; + +impl GLWECiphertext> { + pub fn encrypt_sk_scratch_space(module: &Module, basek: usize, k: usize) -> usize { + let size: usize = div_ceil(k, basek); + module.vec_znx_big_normalize_tmp_bytes() + module.bytes_of_vec_znx_dft(1, size) + module.bytes_of_vec_znx(1, size) + } + pub fn encrypt_pk_scratch_space(module: &Module, basek: usize, k: usize) -> usize { + let size: usize = div_ceil(k, basek); + ((module.bytes_of_vec_znx_dft(1, size) + module.bytes_of_vec_znx_big(1, size)) | module.bytes_of_scalar_znx(1)) + + module.bytes_of_scalar_znx_dft(1) + + module.vec_znx_big_normalize_tmp_bytes() + } +} + +impl + AsMut<[u8]>> GLWECiphertext { + pub fn encrypt_sk, DataSk: AsRef<[u8]>>( + &mut self, + module: &Module, + pt: &GLWEPlaintext, + sk: &GLWESecret, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) { + self.encrypt_sk_private( + module, + Some((pt, 0)), + sk, + source_xa, + source_xe, + sigma, + scratch, + ); + } + + pub fn encrypt_zero_sk>( + &mut self, + module: &Module, + sk: &GLWESecret, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) { + self.encrypt_sk_private( + module, + None::<(&GLWEPlaintext>, usize)>, + sk, + source_xa, + source_xe, + sigma, + scratch, + ); + } + + pub fn encrypt_pk, DataPk: AsRef<[u8]>>( + &mut self, + module: &Module, + pt: &GLWEPlaintext, + pk: &GLWEPublicKey, + source_xu: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) { + self.encrypt_pk_private( + module, + Some((pt, 0)), + pk, + source_xu, + source_xe, + sigma, + scratch, + ); + } + + pub fn encrypt_zero_pk>( + &mut self, + module: &Module, + pk: &GLWEPublicKey, + source_xu: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) { + self.encrypt_pk_private( + module, + None::<(&GLWEPlaintext>, usize)>, + pk, + source_xu, + source_xe, + sigma, + scratch, + ); + } + + pub(crate) fn encrypt_sk_private, DataSk: AsRef<[u8]>>( + &mut self, + module: &Module, + pt: Option<(&GLWEPlaintext, usize)>, + sk: &GLWESecret, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) { + #[cfg(debug_assertions)] + { + assert_eq!(self.rank(), sk.rank()); + assert_eq!(sk.n(), module.n()); + assert_eq!(self.n(), module.n()); + if let Some((pt, col)) = pt { + assert_eq!(pt.n(), module.n()); + assert!(col < self.rank() + 1); + } + assert!( + scratch.available() >= GLWECiphertext::encrypt_sk_scratch_space(module, self.basek(), self.k()), + "scratch.available(): {} < GLWECiphertext::encrypt_sk_scratch_space: {}", + scratch.available(), + GLWECiphertext::encrypt_sk_scratch_space(module, self.basek(), self.k()) + ) + } + + let basek: usize = self.basek(); + let k: usize = self.k(); + let size: usize = self.size(); + let cols: usize = self.rank() + 1; + + let (mut c0_big, scratch_1) = scratch.tmp_vec_znx(module, 1, size); + c0_big.zero(); + + { + // c[i] = uniform + // c[0] -= c[i] * s[i], + (1..cols).for_each(|i| { + let (mut ci_dft, scratch_2) = scratch_1.tmp_vec_znx_dft(module, 1, size); + + // c[i] = uniform + self.data.fill_uniform(basek, i, size, source_xa); + + // c[i] = norm(IDFT(DFT(c[i]) * DFT(s[i]))) + module.vec_znx_dft(1, 0, &mut ci_dft, 0, &self.data, i); + module.svp_apply_inplace(&mut ci_dft, 0, &sk.data_fourier, i - 1); + let ci_big: VecZnxBig<&mut [u8], FFT64> = module.vec_znx_idft_consume(ci_dft); + + // use c[0] as buffer, which is overwritten later by the normalization step + module.vec_znx_big_normalize(basek, &mut self.data, 0, &ci_big, 0, scratch_2); + + // c0_tmp = -c[i] * s[i] (use c[0] as buffer) + module.vec_znx_sub_ab_inplace(&mut c0_big, 0, &self.data, 0); + + // c[i] += m if col = i + if let Some((pt, col)) = pt { + if i == col { + module.vec_znx_add_inplace(&mut self.data, i, &pt.data, 0); + module.vec_znx_normalize_inplace(basek, &mut self.data, i, scratch_2); + } + } + }); + } + + // c[0] += e + c0_big.add_normal(basek, 0, k, source_xe, sigma, sigma * SIX_SIGMA); + + // c[0] += m if col = 0 + if let Some((pt, col)) = pt { + if col == 0 { + module.vec_znx_add_inplace(&mut c0_big, 0, &pt.data, 0); + } + } + + // c[0] = norm(c[0]) + module.vec_znx_normalize(basek, &mut self.data, 0, &c0_big, 0, scratch_1); + } + + pub(crate) fn encrypt_pk_private, DataPk: AsRef<[u8]>>( + &mut self, + module: &Module, + pt: Option<(&GLWEPlaintext, usize)>, + pk: &GLWEPublicKey, + source_xu: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch, + ) { + #[cfg(debug_assertions)] + { + assert_eq!(self.basek(), pk.basek()); + assert_eq!(self.n(), module.n()); + assert_eq!(pk.n(), module.n()); + assert_eq!(self.rank(), pk.rank()); + if let Some((pt, _)) = pt { + assert_eq!(pt.basek(), pk.basek()); + assert_eq!(pt.n(), module.n()); + } + } + + let basek: usize = pk.basek(); + let size_pk: usize = pk.size(); + let cols: usize = self.rank() + 1; + + // Generates u according to the underlying secret distribution. + let (mut u_dft, scratch_1) = scratch.tmp_scalar_znx_dft(module, 1); + + { + let (mut u, _) = scratch_1.tmp_scalar_znx(module, 1); + match pk.dist { + SecretDistribution::NONE => panic!( + "invalid public key: SecretDistribution::NONE, ensure it has been correctly intialized through \ + Self::generate" + ), + SecretDistribution::TernaryFixed(hw) => u.fill_ternary_hw(0, hw, source_xu), + SecretDistribution::TernaryProb(prob) => u.fill_ternary_prob(0, prob, source_xu), + SecretDistribution::BinaryFixed(hw) => u.fill_binary_hw(0, hw, source_xu), + SecretDistribution::BinaryProb(prob) => u.fill_binary_prob(0, prob, source_xu), + SecretDistribution::BinaryBlock(block_size) => u.fill_binary_block(0, block_size, source_xu), + SecretDistribution::ZERO => {} + } + + module.svp_prepare(&mut u_dft, 0, &u, 0); + } + + // ct[i] = pk[i] * u + ei (+ m if col = i) + (0..cols).for_each(|i| { + let (mut ci_dft, scratch_2) = scratch_1.tmp_vec_znx_dft(module, 1, size_pk); + // ci_dft = DFT(u) * DFT(pk[i]) + module.svp_apply(&mut ci_dft, 0, &u_dft, 0, &pk.data.data, i); + + // ci_big = u * p[i] + let mut ci_big = module.vec_znx_idft_consume(ci_dft); + + // ci_big = u * pk[i] + e + ci_big.add_normal(basek, 0, pk.k(), source_xe, sigma, sigma * SIX_SIGMA); + + // ci_big = u * pk[i] + e + m (if col = i) + if let Some((pt, col)) = pt { + if col == i { + module.vec_znx_big_add_small_inplace(&mut ci_big, 0, &pt.data, 0); + } + } + + // ct[i] = norm(ci_big) + module.vec_znx_big_normalize(basek, &mut self.data, i, &ci_big, 0, scratch_2); + }); + } +} diff --git a/core/src/glwe/external_product.rs b/core/src/glwe/external_product.rs new file mode 100644 index 0000000..c44ab75 --- /dev/null +++ b/core/src/glwe/external_product.rs @@ -0,0 +1,129 @@ +use backend::{ + FFT64, MatZnxDftOps, MatZnxDftScratch, Module, Scratch, VecZnxBig, VecZnxBigOps, VecZnxDftAlloc, VecZnxDftOps, VecZnxScratch, +}; + +use crate::{FourierGLWECiphertext, GGSWCiphertext, GLWECiphertext, Infos, div_ceil}; + +impl GLWECiphertext> { + pub fn external_product_scratch_space( + module: &Module, + basek: usize, + k_out: usize, + k_in: usize, + ggsw_k: usize, + digits: usize, + rank: usize, + ) -> usize { + let res_dft: usize = FourierGLWECiphertext::bytes_of(module, basek, k_out, rank); + let in_size: usize = div_ceil(div_ceil(k_in, basek), digits); + let out_size: usize = div_ceil(k_out, basek); + let ggsw_size: usize = div_ceil(ggsw_k, basek); + let vmp: usize = module.bytes_of_vec_znx_dft(rank + 1, in_size) + + module.vmp_apply_tmp_bytes( + out_size, + in_size, + in_size, // rows + rank + 1, // cols in + rank + 1, // cols out + ggsw_size, + ); + let normalize: usize = module.vec_znx_normalize_tmp_bytes(); + res_dft + (vmp | normalize) + } + + pub fn external_product_inplace_scratch_space( + module: &Module, + basek: usize, + k_out: usize, + ggsw_k: usize, + digits: usize, + rank: usize, + ) -> usize { + Self::external_product_scratch_space(module, basek, k_out, k_out, ggsw_k, digits, rank) + } +} + +impl + AsMut<[u8]>> GLWECiphertext { + pub fn external_product, DataRhs: AsRef<[u8]>>( + &mut self, + module: &Module, + lhs: &GLWECiphertext, + rhs: &GGSWCiphertext, + scratch: &mut Scratch, + ) { + let basek: usize = self.basek(); + + #[cfg(debug_assertions)] + { + assert_eq!(rhs.rank(), lhs.rank()); + assert_eq!(rhs.rank(), self.rank()); + assert_eq!(self.basek(), basek); + assert_eq!(lhs.basek(), basek); + assert_eq!(rhs.n(), module.n()); + assert_eq!(self.n(), module.n()); + assert_eq!(lhs.n(), module.n()); + assert!( + scratch.available() + >= GLWECiphertext::external_product_scratch_space( + module, + self.basek(), + self.k(), + lhs.k(), + rhs.k(), + rhs.digits(), + rhs.rank(), + ) + ); + } + + let cols: usize = rhs.rank() + 1; + let digits: usize = rhs.digits(); + + let (mut res_dft, scratch1) = scratch.tmp_vec_znx_dft(module, cols, rhs.size()); // Todo optimise + let (mut a_dft, scratch2) = scratch1.tmp_vec_znx_dft(module, cols, (lhs.size() + digits - 1) / digits); + + { + (0..digits).for_each(|di| { + // (lhs.size() + di) / digits = (a - (digit - di - 1) + digit - 1) / digits + a_dft.set_size((lhs.size() + di) / digits); + + // Small optimization for digits > 2 + // VMP produce some error e, and since we aggregate vmp * 2^{di * B}, then + // we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(digits-1) * B}. + // As such we can ignore the last digits-2 limbs safely of the sum of vmp products. + // It is possible to further ignore the last digits-1 limbs, but this introduce + // ~0.5 to 1 bit of additional noise, and thus not chosen here to ensure that the same + // noise is kept with respect to the ideal functionality. + res_dft.set_size(rhs.size() - ((digits - di) as isize - 2).max(0) as usize); + + (0..cols).for_each(|col_i| { + module.vec_znx_dft(digits, digits - 1 - di, &mut a_dft, col_i, &lhs.data, col_i); + }); + + if di == 0 { + module.vmp_apply(&mut res_dft, &a_dft, &rhs.data, scratch2); + } else { + module.vmp_apply_add(&mut res_dft, &a_dft, &rhs.data, di, scratch2); + } + }); + } + + let res_big: VecZnxBig<&mut [u8], FFT64> = module.vec_znx_idft_consume(res_dft); + + (0..cols).for_each(|i| { + module.vec_znx_big_normalize(basek, &mut self.data, i, &res_big, i, scratch1); + }); + } + + pub fn external_product_inplace>( + &mut self, + module: &Module, + rhs: &GGSWCiphertext, + scratch: &mut Scratch, + ) { + unsafe { + let self_ptr: *mut GLWECiphertext = self as *mut GLWECiphertext; + self.external_product(&module, &*self_ptr, rhs, scratch); + } + } +} diff --git a/core/src/glwe/keyswitch.rs b/core/src/glwe/keyswitch.rs new file mode 100644 index 0000000..eace187 --- /dev/null +++ b/core/src/glwe/keyswitch.rs @@ -0,0 +1,244 @@ +use backend::{ + FFT64, MatZnxDftOps, MatZnxDftScratch, Module, Scratch, VecZnxBig, VecZnxBigOps, VecZnxBigScratch, VecZnxDftAlloc, + VecZnxDftOps, ZnxZero, +}; + +use crate::{FourierGLWECiphertext, GLWECiphertext, GLWESwitchingKey, Infos, div_ceil}; + +impl GLWECiphertext> { + pub fn keyswitch_scratch_space( + module: &Module, + basek: usize, + k_out: usize, + k_in: usize, + k_ksk: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + ) -> usize { + let res_dft: usize = FourierGLWECiphertext::bytes_of(module, basek, k_out, rank_out + 1); + let in_size: usize = div_ceil(div_ceil(k_in, basek), digits); + let out_size: usize = div_ceil(k_out, basek); + let ksk_size: usize = div_ceil(k_ksk, basek); + let ai_dft: usize = module.bytes_of_vec_znx_dft(rank_in, in_size); + let vmp: usize = module.vmp_apply_tmp_bytes(out_size, in_size, in_size, rank_in, rank_out + 1, ksk_size) + + module.bytes_of_vec_znx_dft(rank_in, in_size); + let normalize: usize = module.vec_znx_big_normalize_tmp_bytes(); + return res_dft + ((ai_dft + vmp) | normalize); + } + + pub fn keyswitch_from_fourier_scratch_space( + module: &Module, + basek: usize, + k_out: usize, + k_in: usize, + k_ksk: usize, + digits: usize, + rank_in: usize, + rank_out: usize, + ) -> usize { + Self::keyswitch_scratch_space(module, basek, k_out, k_in, k_ksk, digits, rank_in, rank_out) + } + + pub fn keyswitch_inplace_scratch_space( + module: &Module, + basek: usize, + k_out: usize, + k_ksk: usize, + digits: usize, + rank: usize, + ) -> usize { + Self::keyswitch_scratch_space(module, basek, k_out, k_out, k_ksk, digits, rank, rank) + } +} + +impl + AsMut<[u8]>> GLWECiphertext { + pub fn keyswitch, DataRhs: AsRef<[u8]>>( + &mut self, + module: &Module, + lhs: &GLWECiphertext, + rhs: &GLWESwitchingKey, + scratch: &mut Scratch, + ) { + Self::keyswitch_private::<_, _, 0>(self, 0, module, lhs, rhs, scratch); + } + + pub fn keyswitch_inplace>( + &mut self, + module: &Module, + rhs: &GLWESwitchingKey, + scratch: &mut Scratch, + ) { + unsafe { + let self_ptr: *mut GLWECiphertext = self as *mut GLWECiphertext; + self.keyswitch(&module, &*self_ptr, rhs, scratch); + } + } + + pub(crate) fn keyswitch_private, DataRhs: AsRef<[u8]>, const OP: u8>( + &mut self, + apply_auto: i64, + module: &Module, + lhs: &GLWECiphertext, + rhs: &GLWESwitchingKey, + scratch: &mut Scratch, + ) { + let basek: usize = self.basek(); + + #[cfg(debug_assertions)] + { + assert_eq!(lhs.rank(), rhs.rank_in()); + assert_eq!(self.rank(), rhs.rank_out()); + assert_eq!(self.basek(), basek); + assert_eq!(lhs.basek(), basek); + assert_eq!(rhs.n(), module.n()); + assert_eq!(self.n(), module.n()); + assert_eq!(lhs.n(), module.n()); + assert!( + scratch.available() + >= GLWECiphertext::keyswitch_scratch_space( + module, + self.basek(), + self.k(), + lhs.k(), + rhs.k(), + rhs.digits(), + rhs.rank_in(), + rhs.rank_out(), + ) + ); + } + + let cols_in: usize = rhs.rank_in(); + let cols_out: usize = rhs.rank_out() + 1; + let digits: usize = rhs.digits(); + + let (mut res_dft, scratch1) = scratch.tmp_vec_znx_dft(module, cols_out, rhs.size()); // Todo optimise + let (mut ai_dft, scratch2) = scratch1.tmp_vec_znx_dft(module, cols_in, (lhs.size() + digits - 1) / digits); + ai_dft.zero(); + { + (0..digits).for_each(|di| { + ai_dft.set_size((lhs.size() + di) / digits); + + // Small optimization for digits > 2 + // VMP produce some error e, and since we aggregate vmp * 2^{di * B}, then + // we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(digits-1) * B}. + // As such we can ignore the last digits-2 limbs safely of the sum of vmp products. + // It is possible to further ignore the last digits-1 limbs, but this introduce + // ~0.5 to 1 bit of additional noise, and thus not chosen here to ensure that the same + // noise is kept with respect to the ideal functionality. + res_dft.set_size(rhs.size() - ((digits - di) as isize - 2).max(0) as usize); + + (0..cols_in).for_each(|col_i| { + module.vec_znx_dft( + digits, + digits - di - 1, + &mut ai_dft, + col_i, + &lhs.data, + col_i + 1, + ); + }); + + if di == 0 { + module.vmp_apply(&mut res_dft, &ai_dft, &rhs.0.data, scratch2); + } else { + module.vmp_apply_add(&mut res_dft, &ai_dft, &rhs.0.data, di, scratch2); + } + }); + } + + let mut res_big: VecZnxBig<&mut [u8], FFT64> = module.vec_znx_idft_consume(res_dft); + + module.vec_znx_big_add_small_inplace(&mut res_big, 0, &lhs.data, 0); + + (0..cols_out).for_each(|i| { + if apply_auto != 0 { + module.vec_znx_big_automorphism_inplace(apply_auto, &mut res_big, i); + } + + match OP { + 1 => module.vec_znx_big_add_small_inplace(&mut res_big, i, &lhs.data, i), + 2 => module.vec_znx_big_sub_small_a_inplace(&mut res_big, i, &lhs.data, i), + 3 => module.vec_znx_big_sub_small_b_inplace(&mut res_big, i, &lhs.data, i), + _ => {} + } + module.vec_znx_big_normalize(basek, &mut self.data, i, &res_big, i, scratch1); + }); + } + + pub(crate) fn keyswitch_from_fourier, DataRhs: AsRef<[u8]>>( + &mut self, + module: &Module, + lhs: &FourierGLWECiphertext, + rhs: &GLWESwitchingKey, + scratch: &mut Scratch, + ) { + let basek: usize = self.basek(); + + #[cfg(debug_assertions)] + { + assert_eq!(lhs.rank(), rhs.rank_in()); + assert_eq!(self.rank(), rhs.rank_out()); + assert_eq!(self.basek(), basek); + assert_eq!(lhs.basek(), basek); + assert_eq!(rhs.n(), module.n()); + assert_eq!(self.n(), module.n()); + assert_eq!(lhs.n(), module.n()); + assert!( + scratch.available() + >= GLWECiphertext::keyswitch_from_fourier_scratch_space( + module, + self.basek(), + self.k(), + lhs.k(), + rhs.k(), + rhs.digits(), + rhs.rank_in(), + rhs.rank_out(), + ) + ); + } + + let cols_in: usize = rhs.rank_in(); + let cols_out: usize = rhs.rank_out() + 1; + + // Buffer of the result of VMP in DFT + let (mut res_dft, scratch1) = scratch.tmp_vec_znx_dft(module, cols_out, rhs.size()); // Todo optimise + + { + let digits = rhs.digits(); + + (0..digits).for_each(|di| { + // (lhs.size() + di) / digits = (a - (digit - di - 1) + digit - 1) / digits + let (mut ai_dft, scratch2) = scratch1.tmp_vec_znx_dft(module, cols_in, (lhs.size() + di) / digits); + + (0..cols_in).for_each(|col_i| { + module.vec_znx_dft_copy( + digits, + digits - 1 - di, + &mut ai_dft, + col_i, + &lhs.data, + col_i + 1, + ); + }); + + if di == 0 { + module.vmp_apply(&mut res_dft, &ai_dft, &rhs.0.data, scratch2); + } else { + module.vmp_apply_add(&mut res_dft, &ai_dft, &rhs.0.data, di, scratch2); + } + }); + } + + module.vec_znx_dft_add_inplace(&mut res_dft, 0, &lhs.data, 0); + + // Switches result of VMP outside of DFT + let res_big: VecZnxBig<&mut [u8], FFT64> = module.vec_znx_idft_consume::<&mut [u8]>(res_dft); + + (0..cols_out).for_each(|i| { + module.vec_znx_big_normalize(basek, &mut self.data, i, &res_big, i, scratch1); + }); + } +} diff --git a/core/src/glwe/mod.rs b/core/src/glwe/mod.rs new file mode 100644 index 0000000..ed3395d --- /dev/null +++ b/core/src/glwe/mod.rs @@ -0,0 +1,31 @@ +pub mod automorphism; +pub mod ciphertext; +pub mod decryption; +pub mod encryption; +pub mod external_product; +pub mod keyswitch; +pub mod ops; +pub mod packing; +pub mod plaintext; +pub mod public_key; +pub mod secret; +pub mod trace; + +#[allow(unused_imports)] +pub use automorphism::*; +pub use ciphertext::*; +#[allow(unused_imports)] +pub use decryption::*; +#[allow(unused_imports)] +pub use encryption::*; +#[allow(unused_imports)] +pub use external_product::*; +#[allow(unused_imports)] +pub use keyswitch::*; +pub use ops::*; +pub use packing::*; +pub use plaintext::*; +pub use public_key::*; +pub use secret::*; +#[allow(unused_imports)] +pub use trace::*; diff --git a/core/src/glwe_ops.rs b/core/src/glwe/ops.rs similarity index 100% rename from core/src/glwe_ops.rs rename to core/src/glwe/ops.rs diff --git a/core/src/glwe_packing.rs b/core/src/glwe/packing.rs similarity index 100% rename from core/src/glwe_packing.rs rename to core/src/glwe/packing.rs diff --git a/core/src/glwe_plaintext.rs b/core/src/glwe/plaintext.rs similarity index 92% rename from core/src/glwe_plaintext.rs rename to core/src/glwe/plaintext.rs index 5bebc68..c1e9175 100644 --- a/core/src/glwe_plaintext.rs +++ b/core/src/glwe/plaintext.rs @@ -1,6 +1,10 @@ use backend::{Backend, FFT64, Module, VecZnx, VecZnxAlloc, VecZnxToMut, VecZnxToRef}; -use crate::{GLWECiphertext, GLWECiphertextToMut, GLWECiphertextToRef, GLWEOps, Infos, SetMetaData}; +use crate::{ + GLWEOps, Infos, SetMetaData, + ciphertext::{GLWECiphertext, GLWECiphertextToMut, GLWECiphertextToRef}, + div_ceil, +}; pub struct GLWEPlaintext { pub data: VecZnx, diff --git a/core/src/glwe/public_key.rs b/core/src/glwe/public_key.rs new file mode 100644 index 0000000..4a1ed15 --- /dev/null +++ b/core/src/glwe/public_key.rs @@ -0,0 +1,75 @@ +use backend::{Backend, FFT64, Module, ScratchOwned, VecZnxDft}; +use sampling::source::Source; + +use crate::{FourierGLWECiphertext, GLWESecret, Infos, keys::SecretDistribution}; + +pub struct GLWEPublicKey { + pub(crate) data: FourierGLWECiphertext, + pub(crate) dist: SecretDistribution, +} + +impl GLWEPublicKey, B> { + pub fn alloc(module: &Module, basek: usize, k: usize, rank: usize) -> Self { + Self { + data: FourierGLWECiphertext::alloc(module, basek, k, rank), + dist: SecretDistribution::NONE, + } + } + + pub fn bytes_of(module: &Module, basek: usize, k: usize, rank: usize) -> usize { + FourierGLWECiphertext::, B>::bytes_of(module, basek, k, rank) + } +} + +impl Infos for GLWEPublicKey { + type Inner = VecZnxDft; + + fn inner(&self) -> &Self::Inner { + &self.data.data + } + + fn basek(&self) -> usize { + self.data.basek + } + + fn k(&self) -> usize { + self.data.k + } +} + +impl GLWEPublicKey { + pub fn rank(&self) -> usize { + self.cols() - 1 + } +} + +impl + AsMut<[u8]>> GLWEPublicKey { + pub fn generate_from_sk>( + &mut self, + module: &Module, + sk: &GLWESecret, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + ) { + #[cfg(debug_assertions)] + { + match sk.dist { + SecretDistribution::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::new(FourierGLWECiphertext::encrypt_sk_scratch_space( + module, + self.basek(), + self.k(), + self.rank(), + )); + + self.data + .encrypt_zero_sk(module, sk, source_xa, source_xe, sigma, scratch.borrow()); + self.dist = sk.dist; + } +} diff --git a/core/src/glwe/secret.rs b/core/src/glwe/secret.rs new file mode 100644 index 0000000..b704365 --- /dev/null +++ b/core/src/glwe/secret.rs @@ -0,0 +1,93 @@ +use backend::{ + Backend, FFT64, Module, ScalarZnx, ScalarZnxAlloc, ScalarZnxDft, ScalarZnxDftAlloc, ScalarZnxDftOps, ZnxInfos, ZnxZero, +}; +use sampling::source::Source; + +use crate::keys::SecretDistribution; + +pub struct GLWESecret { + pub(crate) data: ScalarZnx, + pub(crate) data_fourier: ScalarZnxDft, + pub(crate) dist: SecretDistribution, +} + +impl GLWESecret, B> { + pub fn alloc(module: &Module, rank: usize) -> Self { + Self { + data: module.new_scalar_znx(rank), + data_fourier: module.new_scalar_znx_dft(rank), + dist: SecretDistribution::NONE, + } + } + + pub fn bytes_of(module: &Module, rank: usize) -> usize { + module.bytes_of_scalar_znx(rank) + module.bytes_of_scalar_znx_dft(rank) + } +} + +impl GLWESecret { + 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 + AsRef<[u8]>> GLWESecret { + pub fn fill_ternary_prob(&mut self, module: &Module, prob: f64, source: &mut Source) { + (0..self.rank()).for_each(|i| { + self.data.fill_ternary_prob(i, prob, source); + }); + self.prep_fourier(module); + self.dist = SecretDistribution::TernaryProb(prob); + } + + pub fn fill_ternary_hw(&mut self, module: &Module, hw: usize, source: &mut Source) { + (0..self.rank()).for_each(|i| { + self.data.fill_ternary_hw(i, hw, source); + }); + self.prep_fourier(module); + self.dist = SecretDistribution::TernaryFixed(hw); + } + + pub fn fill_binary_prob(&mut self, module: &Module, prob: f64, source: &mut Source) { + (0..self.rank()).for_each(|i| { + self.data.fill_binary_prob(i, prob, source); + }); + self.prep_fourier(module); + self.dist = SecretDistribution::BinaryProb(prob); + } + + pub fn fill_binary_hw(&mut self, module: &Module, hw: usize, source: &mut Source) { + (0..self.rank()).for_each(|i| { + self.data.fill_binary_hw(i, hw, source); + }); + self.prep_fourier(module); + self.dist = SecretDistribution::BinaryFixed(hw); + } + + pub fn fill_binary_block(&mut self, module: &Module, block_size: usize, source: &mut Source) { + (0..self.rank()).for_each(|i| { + self.data.fill_binary_block(i, block_size, source); + }); + self.prep_fourier(module); + self.dist = SecretDistribution::BinaryBlock(block_size); + } + + pub fn fill_zero(&mut self) { + self.data.zero(); + self.dist = SecretDistribution::ZERO; + } + + pub(crate) fn prep_fourier(&mut self, module: &Module) { + (0..self.rank()).for_each(|i| { + module.svp_prepare(&mut self.data_fourier, i, &self.data, i); + }); + } +} diff --git a/core/src/trace.rs b/core/src/glwe/trace.rs similarity index 100% rename from core/src/trace.rs rename to core/src/glwe/trace.rs diff --git a/core/src/glwe_ciphertext.rs b/core/src/glwe_ciphertext.rs deleted file mode 100644 index cd85f0c..0000000 --- a/core/src/glwe_ciphertext.rs +++ /dev/null @@ -1,886 +0,0 @@ -use backend::{ - AddNormal, Backend, FFT64, FillUniform, MatZnxDftOps, MatZnxDftScratch, Module, ScalarZnxAlloc, ScalarZnxDftAlloc, - ScalarZnxDftOps, Scratch, VecZnx, VecZnxAlloc, VecZnxBig, VecZnxBigAlloc, VecZnxBigOps, VecZnxBigScratch, VecZnxDftAlloc, - VecZnxDftOps, VecZnxOps, VecZnxToMut, VecZnxToRef, ZnxZero, -}; -use sampling::source::Source; - -use crate::{ - AutomorphismKey, GGSWCiphertext, GLWECiphertextFourier, GLWEOps, GLWEPlaintext, GLWEPublicKey, GLWESecret, GLWESwitchingKey, - Infos, SIX_SIGMA, SecretDistribution, SetMetaData, -}; - -pub struct GLWECiphertext { - pub data: VecZnx, - pub basek: usize, - pub k: usize, -} - -impl GLWECiphertext> { - pub fn alloc(module: &Module, basek: usize, k: usize, rank: usize) -> Self { - Self { - data: module.new_vec_znx(rank + 1, k.div_ceil(basek)), - basek, - k, - } - } - - pub fn bytes_of(module: &Module, basek: usize, k: usize, rank: usize) -> usize { - module.bytes_of_vec_znx(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 { - #[allow(dead_code)] - pub(crate) fn dft + AsRef<[u8]>>(&self, module: &Module, res: &mut GLWECiphertextFourier) { - #[cfg(debug_assertions)] - { - assert_eq!(self.rank(), res.rank()); - assert_eq!(self.basek(), res.basek()) - } - - (0..self.rank() + 1).for_each(|i| { - module.vec_znx_dft(1, 0, &mut res.data, i, &self.data, i); - }) - } -} - -impl GLWECiphertext> { - pub fn encrypt_sk_scratch_space(module: &Module, basek: usize, k: usize) -> usize { - let size: usize = k.div_ceil(basek); - module.vec_znx_big_normalize_tmp_bytes() + module.bytes_of_vec_znx_dft(1, size) + module.bytes_of_vec_znx(1, size) - } - pub fn encrypt_pk_scratch_space(module: &Module, basek: usize, k: usize) -> usize { - let size: usize = k.div_ceil(basek); - ((module.bytes_of_vec_znx_dft(1, size) + module.bytes_of_vec_znx_big(1, size)) | module.bytes_of_scalar_znx(1)) - + module.bytes_of_scalar_znx_dft(1) - + module.vec_znx_big_normalize_tmp_bytes() - } - - pub fn decrypt_scratch_space(module: &Module, basek: usize, k: usize) -> usize { - let size: usize = k.div_ceil(basek); - (module.vec_znx_big_normalize_tmp_bytes() | module.bytes_of_vec_znx_dft(1, size)) + module.bytes_of_vec_znx_big(1, size) - } - - pub fn keyswitch_scratch_space( - module: &Module, - basek: usize, - k_out: usize, - k_in: usize, - k_ksk: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - ) -> usize { - let res_dft: usize = GLWECiphertextFourier::bytes_of(module, basek, k_out, rank_out + 1); - let in_size: usize = k_in.div_ceil(basek).div_ceil(digits); - let out_size: usize = k_out.div_ceil(basek); - let ksk_size: usize = k_ksk.div_ceil(basek); - let ai_dft: usize = module.bytes_of_vec_znx_dft(rank_in, in_size); - let vmp: usize = module.vmp_apply_tmp_bytes(out_size, in_size, in_size, rank_in, rank_out + 1, ksk_size) - + module.bytes_of_vec_znx_dft(rank_in, in_size); - let normalize: usize = module.vec_znx_big_normalize_tmp_bytes(); - return res_dft + ((ai_dft + vmp) | normalize); - } - - pub fn keyswitch_from_fourier_scratch_space( - module: &Module, - basek: usize, - k_out: usize, - k_in: usize, - k_ksk: usize, - digits: usize, - rank_in: usize, - rank_out: usize, - ) -> usize { - Self::keyswitch_scratch_space(module, basek, k_out, k_in, k_ksk, digits, rank_in, rank_out) - } - - pub fn keyswitch_inplace_scratch_space( - module: &Module, - basek: usize, - k_out: usize, - k_ksk: usize, - digits: usize, - rank: usize, - ) -> usize { - Self::keyswitch_scratch_space(module, basek, k_out, k_out, k_ksk, digits, rank, rank) - } - - pub fn automorphism_scratch_space( - module: &Module, - basek: usize, - k_out: usize, - k_in: usize, - k_ksk: usize, - digits: usize, - rank: usize, - ) -> usize { - Self::keyswitch_scratch_space(module, basek, k_out, k_in, k_ksk, digits, rank, rank) - } - - pub fn automorphism_inplace_scratch_space( - module: &Module, - basek: usize, - k_out: usize, - k_ksk: usize, - digits: usize, - rank: usize, - ) -> usize { - Self::keyswitch_inplace_scratch_space(module, basek, k_out, k_ksk, digits, rank) - } - - pub fn external_product_scratch_space( - module: &Module, - basek: usize, - k_out: usize, - k_in: usize, - ggsw_k: usize, - digits: usize, - rank: usize, - ) -> usize { - let res_dft: usize = GLWECiphertextFourier::bytes_of(module, basek, k_out, rank); - let in_size: usize = k_in.div_ceil(basek).div_ceil(digits); - let out_size: usize = k_out.div_ceil(basek); - let ggsw_size: usize = ggsw_k.div_ceil(basek); - let vmp: usize = module.bytes_of_vec_znx_dft(rank + 1, in_size) - + module.vmp_apply_tmp_bytes( - out_size, - in_size, - in_size, // rows - rank + 1, // cols in - rank + 1, // cols out - ggsw_size, - ); - let normalize: usize = module.vec_znx_big_normalize_tmp_bytes(); - res_dft + (vmp | normalize) - } - - pub fn external_product_inplace_scratch_space( - module: &Module, - basek: usize, - k_out: usize, - ggsw_k: usize, - digits: usize, - rank: usize, - ) -> usize { - Self::external_product_scratch_space(module, basek, k_out, k_out, ggsw_k, digits, rank) - } -} - -impl + AsRef<[u8]>> SetMetaData for GLWECiphertext { - fn set_k(&mut self, k: usize) { - self.k = k - } - - fn set_basek(&mut self, basek: usize) { - self.basek = basek - } -} - -impl + AsMut<[u8]>> GLWECiphertext { - pub fn encrypt_sk, DataSk: AsRef<[u8]>>( - &mut self, - module: &Module, - pt: &GLWEPlaintext, - sk: &GLWESecret, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) { - self.encrypt_sk_private( - module, - Some((pt, 0)), - sk, - source_xa, - source_xe, - sigma, - scratch, - ); - } - - pub fn encrypt_zero_sk>( - &mut self, - module: &Module, - sk: &GLWESecret, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) { - self.encrypt_sk_private( - module, - None::<(&GLWEPlaintext>, usize)>, - sk, - source_xa, - source_xe, - sigma, - scratch, - ); - } - - pub fn encrypt_pk, DataPk: AsRef<[u8]>>( - &mut self, - module: &Module, - pt: &GLWEPlaintext, - pk: &GLWEPublicKey, - source_xu: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) { - self.encrypt_pk_private( - module, - Some((pt, 0)), - pk, - source_xu, - source_xe, - sigma, - scratch, - ); - } - - pub fn encrypt_zero_pk>( - &mut self, - module: &Module, - pk: &GLWEPublicKey, - source_xu: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) { - self.encrypt_pk_private( - module, - None::<(&GLWEPlaintext>, usize)>, - pk, - source_xu, - source_xe, - sigma, - scratch, - ); - } - - pub fn automorphism, DataRhs: AsRef<[u8]>>( - &mut self, - module: &Module, - lhs: &GLWECiphertext, - rhs: &AutomorphismKey, - scratch: &mut Scratch, - ) { - self.keyswitch(module, lhs, &rhs.key, scratch); - (0..self.rank() + 1).for_each(|i| { - module.vec_znx_automorphism_inplace(rhs.p(), &mut self.data, i); - }) - } - - pub fn automorphism_inplace>( - &mut self, - module: &Module, - rhs: &AutomorphismKey, - scratch: &mut Scratch, - ) { - self.keyswitch_inplace(module, &rhs.key, scratch); - (0..self.rank() + 1).for_each(|i| { - module.vec_znx_automorphism_inplace(rhs.p(), &mut self.data, i); - }) - } - - pub fn automorphism_add, DataRhs: AsRef<[u8]>>( - &mut self, - module: &Module, - lhs: &GLWECiphertext, - rhs: &AutomorphismKey, - scratch: &mut Scratch, - ) { - Self::keyswitch_private::<_, _, 1>(self, rhs.p(), module, lhs, &rhs.key, scratch); - } - - pub fn automorphism_add_inplace>( - &mut self, - module: &Module, - rhs: &AutomorphismKey, - scratch: &mut Scratch, - ) { - unsafe { - let self_ptr: *mut GLWECiphertext = self as *mut GLWECiphertext; - Self::keyswitch_private::<_, _, 1>(self, rhs.p(), module, &*self_ptr, &rhs.key, scratch); - } - } - - pub fn automorphism_sub_ab, DataRhs: AsRef<[u8]>>( - &mut self, - module: &Module, - lhs: &GLWECiphertext, - rhs: &AutomorphismKey, - scratch: &mut Scratch, - ) { - Self::keyswitch_private::<_, _, 2>(self, rhs.p(), module, lhs, &rhs.key, scratch); - } - - pub fn automorphism_sub_ab_inplace>( - &mut self, - module: &Module, - rhs: &AutomorphismKey, - scratch: &mut Scratch, - ) { - unsafe { - let self_ptr: *mut GLWECiphertext = self as *mut GLWECiphertext; - Self::keyswitch_private::<_, _, 2>(self, rhs.p(), module, &*self_ptr, &rhs.key, scratch); - } - } - - pub fn automorphism_sub_ba, DataRhs: AsRef<[u8]>>( - &mut self, - module: &Module, - lhs: &GLWECiphertext, - rhs: &AutomorphismKey, - scratch: &mut Scratch, - ) { - Self::keyswitch_private::<_, _, 3>(self, rhs.p(), module, lhs, &rhs.key, scratch); - } - - pub fn automorphism_sub_ba_inplace>( - &mut self, - module: &Module, - rhs: &AutomorphismKey, - scratch: &mut Scratch, - ) { - unsafe { - let self_ptr: *mut GLWECiphertext = self as *mut GLWECiphertext; - Self::keyswitch_private::<_, _, 3>(self, rhs.p(), module, &*self_ptr, &rhs.key, scratch); - } - } - - pub(crate) fn keyswitch_from_fourier, DataRhs: AsRef<[u8]>>( - &mut self, - module: &Module, - lhs: &GLWECiphertextFourier, - rhs: &GLWESwitchingKey, - scratch: &mut Scratch, - ) { - let basek: usize = self.basek(); - - #[cfg(debug_assertions)] - { - assert_eq!(lhs.rank(), rhs.rank_in()); - assert_eq!(self.rank(), rhs.rank_out()); - assert_eq!(self.basek(), basek); - assert_eq!(lhs.basek(), basek); - assert_eq!(rhs.n(), module.n()); - assert_eq!(self.n(), module.n()); - assert_eq!(lhs.n(), module.n()); - assert!( - scratch.available() - >= GLWECiphertext::keyswitch_from_fourier_scratch_space( - module, - self.basek(), - self.k(), - lhs.k(), - rhs.k(), - rhs.digits(), - rhs.rank_in(), - rhs.rank_out(), - ) - ); - } - - let cols_in: usize = rhs.rank_in(); - let cols_out: usize = rhs.rank_out() + 1; - - // Buffer of the result of VMP in DFT - let (mut res_dft, scratch1) = scratch.tmp_vec_znx_dft(module, cols_out, rhs.size()); // Todo optimise - - { - let digits = rhs.digits(); - - (0..digits).for_each(|di| { - // (lhs.size() + di) / digits = (a - (digit - di - 1) + digit - 1) / digits - let (mut ai_dft, scratch2) = scratch1.tmp_vec_znx_dft(module, cols_in, (lhs.size() + di) / digits); - - (0..cols_in).for_each(|col_i| { - module.vec_znx_dft_copy( - digits, - digits - 1 - di, - &mut ai_dft, - col_i, - &lhs.data, - col_i + 1, - ); - }); - - if di == 0 { - module.vmp_apply(&mut res_dft, &ai_dft, &rhs.0.data, scratch2); - } else { - module.vmp_apply_add(&mut res_dft, &ai_dft, &rhs.0.data, di, scratch2); - } - }); - } - - module.vec_znx_dft_add_inplace(&mut res_dft, 0, &lhs.data, 0); - - // Switches result of VMP outside of DFT - let res_big: VecZnxBig<&mut [u8], FFT64> = module.vec_znx_idft_consume::<&mut [u8]>(res_dft); - - (0..cols_out).for_each(|i| { - module.vec_znx_big_normalize(basek, &mut self.data, i, &res_big, i, scratch1); - }); - } - - pub fn keyswitch, DataRhs: AsRef<[u8]>>( - &mut self, - module: &Module, - lhs: &GLWECiphertext, - rhs: &GLWESwitchingKey, - scratch: &mut Scratch, - ) { - Self::keyswitch_private::<_, _, 0>(self, 0, module, lhs, rhs, scratch); - } - - pub(crate) fn keyswitch_private, DataRhs: AsRef<[u8]>, const OP: u8>( - &mut self, - apply_auto: i64, - module: &Module, - lhs: &GLWECiphertext, - rhs: &GLWESwitchingKey, - scratch: &mut Scratch, - ) { - let basek: usize = self.basek(); - - #[cfg(debug_assertions)] - { - assert_eq!(lhs.rank(), rhs.rank_in()); - assert_eq!(self.rank(), rhs.rank_out()); - assert_eq!(self.basek(), basek); - assert_eq!(lhs.basek(), basek); - assert_eq!(rhs.n(), module.n()); - assert_eq!(self.n(), module.n()); - assert_eq!(lhs.n(), module.n()); - assert!( - scratch.available() - >= GLWECiphertext::keyswitch_scratch_space( - module, - self.basek(), - self.k(), - lhs.k(), - rhs.k(), - rhs.digits(), - rhs.rank_in(), - rhs.rank_out(), - ) - ); - } - - let cols_in: usize = rhs.rank_in(); - let cols_out: usize = rhs.rank_out() + 1; - let digits: usize = rhs.digits(); - - let (mut res_dft, scratch1) = scratch.tmp_vec_znx_dft(module, cols_out, rhs.size()); // Todo optimise - let (mut ai_dft, scratch2) = scratch1.tmp_vec_znx_dft(module, cols_in, (lhs.size() + digits - 1) / digits); - ai_dft.zero(); - { - (0..digits).for_each(|di| { - ai_dft.set_size((lhs.size() + di) / digits); - - // Small optimization for digits > 2 - // VMP produce some error e, and since we aggregate vmp * 2^{di * B}, then - // we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(digits-1) * B}. - // As such we can ignore the last digits-2 limbs safely of the sum of vmp products. - // It is possible to further ignore the last digits-1 limbs, but this introduce - // ~0.5 to 1 bit of additional noise, and thus not chosen here to ensure that the same - // noise is kept with respect to the ideal functionality. - res_dft.set_size(rhs.size() - ((digits - di) as isize - 2).max(0) as usize); - - (0..cols_in).for_each(|col_i| { - module.vec_znx_dft( - digits, - digits - di - 1, - &mut ai_dft, - col_i, - &lhs.data, - col_i + 1, - ); - }); - - if di == 0 { - module.vmp_apply(&mut res_dft, &ai_dft, &rhs.0.data, scratch2); - } else { - module.vmp_apply_add(&mut res_dft, &ai_dft, &rhs.0.data, di, scratch2); - } - }); - } - - let mut res_big: VecZnxBig<&mut [u8], FFT64> = module.vec_znx_idft_consume(res_dft); - - module.vec_znx_big_add_small_inplace(&mut res_big, 0, &lhs.data, 0); - - (0..cols_out).for_each(|i| { - if apply_auto != 0 { - module.vec_znx_big_automorphism_inplace(apply_auto, &mut res_big, i); - } - - match OP { - 1 => module.vec_znx_big_add_small_inplace(&mut res_big, i, &lhs.data, i), - 2 => module.vec_znx_big_sub_small_a_inplace(&mut res_big, i, &lhs.data, i), - 3 => module.vec_znx_big_sub_small_b_inplace(&mut res_big, i, &lhs.data, i), - _ => {} - } - module.vec_znx_big_normalize(basek, &mut self.data, i, &res_big, i, scratch1); - }); - } - - pub fn keyswitch_inplace>( - &mut self, - module: &Module, - rhs: &GLWESwitchingKey, - scratch: &mut Scratch, - ) { - unsafe { - let self_ptr: *mut GLWECiphertext = self as *mut GLWECiphertext; - self.keyswitch(&module, &*self_ptr, rhs, scratch); - } - } - - pub fn external_product, DataRhs: AsRef<[u8]>>( - &mut self, - module: &Module, - lhs: &GLWECiphertext, - rhs: &GGSWCiphertext, - scratch: &mut Scratch, - ) { - let basek: usize = self.basek(); - - #[cfg(debug_assertions)] - { - assert_eq!(rhs.rank(), lhs.rank()); - assert_eq!(rhs.rank(), self.rank()); - assert_eq!(self.basek(), basek); - assert_eq!(lhs.basek(), basek); - assert_eq!(rhs.n(), module.n()); - assert_eq!(self.n(), module.n()); - assert_eq!(lhs.n(), module.n()); - assert!( - scratch.available() - >= GLWECiphertext::external_product_scratch_space( - module, - self.basek(), - self.k(), - lhs.k(), - rhs.k(), - rhs.digits(), - rhs.rank(), - ) - ); - } - - let cols: usize = rhs.rank() + 1; - let digits: usize = rhs.digits(); - - let (mut res_dft, scratch1) = scratch.tmp_vec_znx_dft(module, cols, rhs.size()); // Todo optimise - let (mut a_dft, scratch2) = scratch1.tmp_vec_znx_dft(module, cols, (lhs.size() + digits - 1) / digits); - - { - (0..digits).for_each(|di| { - // (lhs.size() + di) / digits = (a - (digit - di - 1) + digit - 1) / digits - a_dft.set_size((lhs.size() + di) / digits); - - // Small optimization for digits > 2 - // VMP produce some error e, and since we aggregate vmp * 2^{di * B}, then - // we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(digits-1) * B}. - // As such we can ignore the last digits-2 limbs safely of the sum of vmp products. - // It is possible to further ignore the last digits-1 limbs, but this introduce - // ~0.5 to 1 bit of additional noise, and thus not chosen here to ensure that the same - // noise is kept with respect to the ideal functionality. - res_dft.set_size(rhs.size() - ((digits - di) as isize - 2).max(0) as usize); - - (0..cols).for_each(|col_i| { - module.vec_znx_dft(digits, digits - 1 - di, &mut a_dft, col_i, &lhs.data, col_i); - }); - - if di == 0 { - module.vmp_apply(&mut res_dft, &a_dft, &rhs.data, scratch2); - } else { - module.vmp_apply_add(&mut res_dft, &a_dft, &rhs.data, di, scratch2); - } - }); - } - - let res_big: VecZnxBig<&mut [u8], FFT64> = module.vec_znx_idft_consume(res_dft); - - (0..cols).for_each(|i| { - module.vec_znx_big_normalize(basek, &mut self.data, i, &res_big, i, scratch1); - }); - } - - pub fn external_product_inplace>( - &mut self, - module: &Module, - rhs: &GGSWCiphertext, - scratch: &mut Scratch, - ) { - unsafe { - let self_ptr: *mut GLWECiphertext = self as *mut GLWECiphertext; - self.external_product(&module, &*self_ptr, rhs, scratch); - } - } - - pub(crate) fn encrypt_sk_private, DataSk: AsRef<[u8]>>( - &mut self, - module: &Module, - pt: Option<(&GLWEPlaintext, usize)>, - sk: &GLWESecret, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) { - #[cfg(debug_assertions)] - { - assert_eq!(self.rank(), sk.rank()); - assert_eq!(sk.n(), module.n()); - assert_eq!(self.n(), module.n()); - if let Some((pt, col)) = pt { - assert_eq!(pt.n(), module.n()); - assert!(col < self.rank() + 1); - } - assert!( - scratch.available() >= GLWECiphertext::encrypt_sk_scratch_space(module, self.basek(), self.k()), - "scratch.available(): {} < GLWECiphertext::encrypt_sk_scratch_space: {}", - scratch.available(), - GLWECiphertext::encrypt_sk_scratch_space(module, self.basek(), self.k()) - ) - } - - let basek: usize = self.basek(); - let k: usize = self.k(); - let size: usize = self.size(); - let cols: usize = self.rank() + 1; - - let (mut c0_big, scratch_1) = scratch.tmp_vec_znx(module, 1, size); - c0_big.zero(); - - { - // c[i] = uniform - // c[0] -= c[i] * s[i], - (1..cols).for_each(|i| { - let (mut ci_dft, scratch_2) = scratch_1.tmp_vec_znx_dft(module, 1, size); - - // c[i] = uniform - self.data.fill_uniform(basek, i, size, source_xa); - - // c[i] = norm(IDFT(DFT(c[i]) * DFT(s[i]))) - module.vec_znx_dft(1, 0, &mut ci_dft, 0, &self.data, i); - module.svp_apply_inplace(&mut ci_dft, 0, &sk.data_fourier, i - 1); - let ci_big: VecZnxBig<&mut [u8], FFT64> = module.vec_znx_idft_consume(ci_dft); - - // use c[0] as buffer, which is overwritten later by the normalization step - module.vec_znx_big_normalize(basek, &mut self.data, 0, &ci_big, 0, scratch_2); - - // c0_tmp = -c[i] * s[i] (use c[0] as buffer) - module.vec_znx_sub_ab_inplace(&mut c0_big, 0, &self.data, 0); - - // c[i] += m if col = i - if let Some((pt, col)) = pt { - if i == col { - module.vec_znx_add_inplace(&mut self.data, i, &pt.data, 0); - module.vec_znx_normalize_inplace(basek, &mut self.data, i, scratch_2); - } - } - }); - } - - // c[0] += e - c0_big.add_normal(basek, 0, k, source_xe, sigma, sigma * SIX_SIGMA); - - // c[0] += m if col = 0 - if let Some((pt, col)) = pt { - if col == 0 { - module.vec_znx_add_inplace(&mut c0_big, 0, &pt.data, 0); - } - } - - // c[0] = norm(c[0]) - module.vec_znx_normalize(basek, &mut self.data, 0, &c0_big, 0, scratch_1); - } - - pub(crate) fn encrypt_pk_private, DataPk: AsRef<[u8]>>( - &mut self, - module: &Module, - pt: Option<(&GLWEPlaintext, usize)>, - pk: &GLWEPublicKey, - source_xu: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch, - ) { - #[cfg(debug_assertions)] - { - assert_eq!(self.basek(), pk.basek()); - assert_eq!(self.n(), module.n()); - assert_eq!(pk.n(), module.n()); - assert_eq!(self.rank(), pk.rank()); - if let Some((pt, _)) = pt { - assert_eq!(pt.basek(), pk.basek()); - assert_eq!(pt.n(), module.n()); - } - } - - let basek: usize = pk.basek(); - let size_pk: usize = pk.size(); - let cols: usize = self.rank() + 1; - - // Generates u according to the underlying secret distribution. - let (mut u_dft, scratch_1) = scratch.tmp_scalar_znx_dft(module, 1); - - { - let (mut u, _) = scratch_1.tmp_scalar_znx(module, 1); - match pk.dist { - SecretDistribution::NONE => panic!( - "invalid public key: SecretDistribution::NONE, ensure it has been correctly intialized through \ - Self::generate" - ), - SecretDistribution::TernaryFixed(hw) => u.fill_ternary_hw(0, hw, source_xu), - SecretDistribution::TernaryProb(prob) => u.fill_ternary_prob(0, prob, source_xu), - SecretDistribution::BinaryFixed(hw) => u.fill_binary_hw(0, hw, source_xu), - SecretDistribution::BinaryProb(prob) => u.fill_binary_prob(0, prob, source_xu), - SecretDistribution::BinaryBlock(block_size) => u.fill_binary_block(0, block_size, source_xu), - SecretDistribution::ZERO => {} - } - - module.svp_prepare(&mut u_dft, 0, &u, 0); - } - - // ct[i] = pk[i] * u + ei (+ m if col = i) - (0..cols).for_each(|i| { - let (mut ci_dft, scratch_2) = scratch_1.tmp_vec_znx_dft(module, 1, size_pk); - // ci_dft = DFT(u) * DFT(pk[i]) - module.svp_apply(&mut ci_dft, 0, &u_dft, 0, &pk.data.data, i); - - // ci_big = u * p[i] - let mut ci_big = module.vec_znx_idft_consume(ci_dft); - - // ci_big = u * pk[i] + e - ci_big.add_normal(basek, 0, pk.k(), source_xe, sigma, sigma * SIX_SIGMA); - - // ci_big = u * pk[i] + e + m (if col = i) - if let Some((pt, col)) = pt { - if col == i { - module.vec_znx_big_add_small_inplace(&mut ci_big, 0, &pt.data, 0); - } - } - - // ct[i] = norm(ci_big) - module.vec_znx_big_normalize(basek, &mut self.data, i, &ci_big, 0, scratch_2); - }); - } -} - -impl> GLWECiphertext { - pub fn clone(&self) -> GLWECiphertext> { - GLWECiphertext { - data: self.data.clone(), - basek: self.basek(), - k: self.k(), - } - } - - pub fn decrypt + AsRef<[u8]>, DataSk: AsRef<[u8]>>( - &self, - module: &Module, - pt: &mut GLWEPlaintext, - sk: &GLWESecret, - scratch: &mut Scratch, - ) { - #[cfg(debug_assertions)] - { - assert_eq!(self.rank(), sk.rank()); - assert_eq!(self.n(), module.n()); - assert_eq!(pt.n(), module.n()); - assert_eq!(sk.n(), module.n()); - } - - let cols: usize = self.rank() + 1; - - let (mut c0_big, scratch_1) = scratch.tmp_vec_znx_big(module, 1, self.size()); // TODO optimize size when pt << ct - c0_big.zero(); - - { - (1..cols).for_each(|i| { - // ci_dft = DFT(a[i]) * DFT(s[i]) - let (mut ci_dft, _) = scratch_1.tmp_vec_znx_dft(module, 1, self.size()); // TODO optimize size when pt << ct - module.vec_znx_dft(1, 0, &mut ci_dft, 0, &self.data, i); - module.svp_apply_inplace(&mut ci_dft, 0, &sk.data_fourier, i - 1); - let ci_big = module.vec_znx_idft_consume(ci_dft); - - // c0_big += a[i] * s[i] - module.vec_znx_big_add_inplace(&mut c0_big, 0, &ci_big, 0); - }); - } - - // c0_big = (a * s) + (-a * s + m + e) = BIG(m + e) - module.vec_znx_big_add_small_inplace(&mut c0_big, 0, &self.data, 0); - - // pt = norm(BIG(m + e)) - module.vec_znx_big_normalize(self.basek(), &mut pt.data, 0, &mut c0_big, 0, scratch_1); - - pt.basek = self.basek(); - pt.k = pt.k().min(self.k()); - } -} - -pub trait GLWECiphertextToRef { - 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 { - fn to_mut(&mut self) -> GLWECiphertext<&mut [u8]>; -} - -impl + AsRef<[u8]>> 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 - D: AsRef<[u8]> + AsMut<[u8]>, - GLWECiphertext: GLWECiphertextToMut + Infos + SetMetaData, -{ -} diff --git a/core/src/keys.rs b/core/src/keys.rs index 9549f15..45bdc61 100644 --- a/core/src/keys.rs +++ b/core/src/keys.rs @@ -1,11 +1,3 @@ -use backend::{ - Backend, FFT64, Module, ScalarZnx, ScalarZnxAlloc, ScalarZnxDft, ScalarZnxDftAlloc, ScalarZnxDftOps, ScratchOwned, VecZnxDft, - ZnxInfos, ZnxZero, -}; -use sampling::source::Source; - -use crate::{GLWECiphertextFourier, Infos}; - #[derive(Clone, Copy, Debug)] pub(crate) enum SecretDistribution { TernaryFixed(usize), // Ternary with fixed Hamming weight @@ -16,221 +8,3 @@ pub(crate) enum SecretDistribution { ZERO, // Debug mod NONE, // Unitialized } - -pub struct LWESecret { - pub(crate) data: ScalarZnx, - pub(crate) dist: SecretDistribution, -} - -impl LWESecret> { - pub fn alloc(n: usize) -> Self { - Self { - data: ScalarZnx::new(n, 1), - dist: SecretDistribution::NONE, - } - } -} - -impl LWESecret { - 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 + AsMut<[u8]>> LWESecret { - pub fn fill_ternary_prob(&mut self, prob: f64, source: &mut Source) { - self.data.fill_ternary_prob(0, prob, source); - self.dist = SecretDistribution::TernaryProb(prob); - } - - pub fn fill_ternary_hw(&mut self, hw: usize, source: &mut Source) { - self.data.fill_ternary_hw(0, hw, source); - self.dist = SecretDistribution::TernaryFixed(hw); - } - - pub fn fill_binary_prob(&mut self, prob: f64, source: &mut Source) { - self.data.fill_binary_prob(0, prob, source); - self.dist = SecretDistribution::BinaryProb(prob); - } - - pub fn fill_binary_hw(&mut self, hw: usize, source: &mut Source) { - self.data.fill_binary_hw(0, hw, source); - self.dist = SecretDistribution::BinaryFixed(hw); - } - - pub fn fill_binary_block(&mut self, block_size: usize, source: &mut Source) { - self.data.fill_binary_block(0, block_size, source); - self.dist = SecretDistribution::BinaryBlock(block_size); - } - - pub fn fill_zero(&mut self) { - self.data.zero(); - self.dist = SecretDistribution::ZERO; - } -} - -pub struct GLWESecret { - pub(crate) data: ScalarZnx, - pub(crate) data_fourier: ScalarZnxDft, - pub(crate) dist: SecretDistribution, -} - -impl GLWESecret, B> { - pub fn alloc(module: &Module, rank: usize) -> Self { - Self { - data: module.new_scalar_znx(rank), - data_fourier: module.new_scalar_znx_dft(rank), - dist: SecretDistribution::NONE, - } - } - - pub fn bytes_of(module: &Module, rank: usize) -> usize { - module.bytes_of_scalar_znx(rank) + module.bytes_of_scalar_znx_dft(rank) - } -} - -impl GLWESecret { - 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 + AsRef<[u8]>> GLWESecret { - pub fn fill_ternary_prob(&mut self, module: &Module, prob: f64, source: &mut Source) { - (0..self.rank()).for_each(|i| { - self.data.fill_ternary_prob(i, prob, source); - }); - self.prep_fourier(module); - self.dist = SecretDistribution::TernaryProb(prob); - } - - pub fn fill_ternary_hw(&mut self, module: &Module, hw: usize, source: &mut Source) { - (0..self.rank()).for_each(|i| { - self.data.fill_ternary_hw(i, hw, source); - }); - self.prep_fourier(module); - self.dist = SecretDistribution::TernaryFixed(hw); - } - - pub fn fill_binary_prob(&mut self, module: &Module, prob: f64, source: &mut Source) { - (0..self.rank()).for_each(|i| { - self.data.fill_binary_prob(i, prob, source); - }); - self.prep_fourier(module); - self.dist = SecretDistribution::BinaryProb(prob); - } - - pub fn fill_binary_hw(&mut self, module: &Module, hw: usize, source: &mut Source) { - (0..self.rank()).for_each(|i| { - self.data.fill_binary_hw(i, hw, source); - }); - self.prep_fourier(module); - self.dist = SecretDistribution::BinaryFixed(hw); - } - - pub fn fill_binary_block(&mut self, module: &Module, block_size: usize, source: &mut Source) { - (0..self.rank()).for_each(|i| { - self.data.fill_binary_block(i, block_size, source); - }); - self.prep_fourier(module); - self.dist = SecretDistribution::BinaryBlock(block_size); - } - - pub fn fill_zero(&mut self) { - self.data.zero(); - self.dist = SecretDistribution::ZERO; - } - - pub(crate) fn prep_fourier(&mut self, module: &Module) { - (0..self.rank()).for_each(|i| { - module.svp_prepare(&mut self.data_fourier, i, &self.data, i); - }); - } -} - -pub struct GLWEPublicKey { - pub(crate) data: GLWECiphertextFourier, - pub(crate) dist: SecretDistribution, -} - -impl GLWEPublicKey, B> { - pub fn alloc(module: &Module, basek: usize, k: usize, rank: usize) -> Self { - Self { - data: GLWECiphertextFourier::alloc(module, basek, k, rank), - dist: SecretDistribution::NONE, - } - } - - pub fn bytes_of(module: &Module, basek: usize, k: usize, rank: usize) -> usize { - GLWECiphertextFourier::, B>::bytes_of(module, basek, k, rank) - } -} - -impl Infos for GLWEPublicKey { - type Inner = VecZnxDft; - - fn inner(&self) -> &Self::Inner { - &self.data.data - } - - fn basek(&self) -> usize { - self.data.basek - } - - fn k(&self) -> usize { - self.data.k - } -} - -impl GLWEPublicKey { - pub fn rank(&self) -> usize { - self.cols() - 1 - } -} - -impl + AsMut<[u8]>> GLWEPublicKey { - pub fn generate_from_sk>( - &mut self, - module: &Module, - sk: &GLWESecret, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - ) { - #[cfg(debug_assertions)] - { - match sk.dist { - SecretDistribution::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::new(GLWECiphertextFourier::encrypt_sk_scratch_space( - module, - self.basek(), - self.k(), - self.rank(), - )); - - self.data - .encrypt_zero_sk(module, sk, source_xa, source_xe, sigma, scratch.borrow()); - self.dist = sk.dist; - } -} diff --git a/core/src/keyswitch_key.rs b/core/src/keyswitch_key.rs index fd4da76..201ae22 100644 --- a/core/src/keyswitch_key.rs +++ b/core/src/keyswitch_key.rs @@ -1,7 +1,7 @@ use backend::{Backend, FFT64, MatZnxDft, MatZnxDftOps, Module, Scratch, ZnxZero}; use sampling::source::Source; -use crate::{GGLWECiphertext, GGSWCiphertext, GLWECiphertextFourier, GLWESecret, GetRow, Infos, ScratchCore, SetRow}; +use crate::{FourierGLWECiphertext, GGLWECiphertext, GGSWCiphertext, GLWESecret, GetRow, Infos, ScratchCore, SetRow}; pub struct GLWESwitchingKey(pub(crate) GGLWECiphertext); @@ -73,7 +73,7 @@ impl> GetRow for GLWESwitchingKey { module: &Module, row_i: usize, col_j: usize, - res: &mut GLWECiphertextFourier, + res: &mut FourierGLWECiphertext, ) { module.mat_znx_dft_get_row(&mut res.data, &self.0.data, row_i, col_j); } @@ -85,7 +85,7 @@ impl + AsRef<[u8]>> SetRow for GLWESwitchingKey module: &Module, row_i: usize, col_j: usize, - a: &GLWECiphertextFourier, + a: &FourierGLWECiphertext, ) { module.mat_znx_dft_set_row(&mut self.0.data, row_i, col_j, &a.data); } @@ -110,10 +110,10 @@ impl GLWESwitchingKey, FFT64> { rank_in: usize, rank_out: usize, ) -> usize { - let tmp_in: usize = GLWECiphertextFourier::bytes_of(module, basek, k_in, rank_in); - let tmp_out: usize = GLWECiphertextFourier::bytes_of(module, basek, k_out, rank_out); + let tmp_in: usize = FourierGLWECiphertext::bytes_of(module, basek, k_in, rank_in); + let tmp_out: usize = FourierGLWECiphertext::bytes_of(module, basek, k_out, rank_out); let ksk: usize = - GLWECiphertextFourier::keyswitch_scratch_space(module, basek, k_out, k_in, k_ksk, digits, rank_in, rank_out); + FourierGLWECiphertext::keyswitch_scratch_space(module, basek, k_out, k_in, k_ksk, digits, rank_in, rank_out); tmp_in + tmp_out + ksk } @@ -125,8 +125,8 @@ impl GLWESwitchingKey, FFT64> { digits: usize, rank: usize, ) -> usize { - let tmp: usize = GLWECiphertextFourier::bytes_of(module, basek, k_out, rank); - let ksk: usize = GLWECiphertextFourier::keyswitch_inplace_scratch_space(module, basek, k_out, k_ksk, digits, rank); + let tmp: usize = FourierGLWECiphertext::bytes_of(module, basek, k_out, rank); + let ksk: usize = FourierGLWECiphertext::keyswitch_inplace_scratch_space(module, basek, k_out, k_ksk, digits, rank); tmp + ksk } @@ -139,9 +139,9 @@ impl GLWESwitchingKey, FFT64> { digits: usize, rank: usize, ) -> usize { - let tmp_in: usize = GLWECiphertextFourier::bytes_of(module, basek, k_in, rank); - let tmp_out: usize = GLWECiphertextFourier::bytes_of(module, basek, k_out, rank); - let ggsw: usize = GLWECiphertextFourier::external_product_scratch_space(module, basek, k_out, k_in, k_ggsw, digits, rank); + let tmp_in: usize = FourierGLWECiphertext::bytes_of(module, basek, k_in, rank); + let tmp_out: usize = FourierGLWECiphertext::bytes_of(module, basek, k_out, rank); + let ggsw: usize = FourierGLWECiphertext::external_product_scratch_space(module, basek, k_out, k_in, k_ggsw, digits, rank); tmp_in + tmp_out + ggsw } @@ -153,9 +153,9 @@ impl GLWESwitchingKey, FFT64> { digits: usize, rank: usize, ) -> usize { - let tmp: usize = GLWECiphertextFourier::bytes_of(module, basek, k_out, rank); + let tmp: usize = FourierGLWECiphertext::bytes_of(module, basek, k_out, rank); let ggsw: usize = - GLWECiphertextFourier::external_product_inplace_scratch_space(module, basek, k_out, k_ggsw, digits, rank); + FourierGLWECiphertext::external_product_inplace_scratch_space(module, basek, k_out, k_ggsw, digits, rank); tmp + ggsw } } diff --git a/core/src/lib.rs b/core/src/lib.rs index 1bffc5a..ef181a1 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,39 +1,36 @@ pub mod automorphism; pub mod blind_rotation; pub mod elem; -pub mod gglwe_ciphertext; -pub mod ggsw_ciphertext; -pub mod glwe_ciphertext; -pub mod glwe_ciphertext_fourier; -pub mod glwe_ops; -pub mod glwe_packing; -pub mod glwe_plaintext; +pub mod fourier_glwe; +pub mod gglwe; +pub mod ggsw; +pub mod glwe; pub mod keys; pub mod keyswitch_key; +pub mod lwe; pub mod tensor_key; #[cfg(test)] mod test_fft64; -pub mod trace; +mod utils; pub use automorphism::*; use backend::Backend; use backend::FFT64; use backend::Module; pub use elem::*; -pub use gglwe_ciphertext::*; -pub use ggsw_ciphertext::*; -pub use glwe_ciphertext::*; -pub use glwe_ciphertext_fourier::*; -pub use glwe_ops::*; -pub use glwe_packing::*; -pub use glwe_plaintext::*; -pub use keys::*; +pub use fourier_glwe::*; +pub use gglwe::*; +pub use ggsw::*; +pub use glwe::*; pub use keyswitch_key::*; +pub use lwe::*; pub use tensor_key::*; pub use backend::Scratch; pub use backend::ScratchOwned; +use crate::keys::SecretDistribution; + pub(crate) const SIX_SIGMA: f64 = 6.0; pub trait ScratchCore { @@ -64,7 +61,7 @@ pub trait ScratchCore { basek: usize, k: usize, rank: usize, - ) -> (GLWECiphertextFourier<&mut [u8], B>, &mut Self); + ) -> (FourierGLWECiphertext<&mut [u8], B>, &mut Self); fn tmp_sk(&mut self, module: &Module, rank: usize) -> (GLWESecret<&mut [u8], B>, &mut Self); fn tmp_glwe_pk( &mut self, @@ -181,9 +178,9 @@ impl ScratchCore for Scratch { basek: usize, k: usize, rank: usize, - ) -> (GLWECiphertextFourier<&mut [u8], FFT64>, &mut Self) { - let (data, scratch) = self.tmp_vec_znx_dft(module, rank + 1, k.div_ceil(basek)); - (GLWECiphertextFourier { data, basek, k }, scratch) + ) -> (FourierGLWECiphertext<&mut [u8], FFT64>, &mut Self) { + let (data, scratch) = self.tmp_vec_znx_dft(module, rank + 1, div_ceil(k, basek)); + (FourierGLWECiphertext { data, basek, k }, scratch) } fn tmp_glwe_pk( diff --git a/core/src/lwe.rs b/core/src/lwe.rs new file mode 100644 index 0000000..3f0d749 --- /dev/null +++ b/core/src/lwe.rs @@ -0,0 +1,64 @@ +use backend::{ScalarZnx, ZnxInfos, ZnxZero}; +use sampling::source::Source; + +use crate::SecretDistribution; + +pub struct LWESecret { + pub(crate) data: ScalarZnx, + pub(crate) dist: SecretDistribution, +} + +impl LWESecret> { + pub fn alloc(n: usize) -> Self { + Self { + data: ScalarZnx::new(n, 1), + dist: SecretDistribution::NONE, + } + } +} + +impl LWESecret { + 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 + AsMut<[u8]>> LWESecret { + pub fn fill_ternary_prob(&mut self, prob: f64, source: &mut Source) { + self.data.fill_ternary_prob(0, prob, source); + self.dist = SecretDistribution::TernaryProb(prob); + } + + pub fn fill_ternary_hw(&mut self, hw: usize, source: &mut Source) { + self.data.fill_ternary_hw(0, hw, source); + self.dist = SecretDistribution::TernaryFixed(hw); + } + + pub fn fill_binary_prob(&mut self, prob: f64, source: &mut Source) { + self.data.fill_binary_prob(0, prob, source); + self.dist = SecretDistribution::BinaryProb(prob); + } + + pub fn fill_binary_hw(&mut self, hw: usize, source: &mut Source) { + self.data.fill_binary_hw(0, hw, source); + self.dist = SecretDistribution::BinaryFixed(hw); + } + + pub fn fill_binary_block(&mut self, block_size: usize, source: &mut Source) { + self.data.fill_binary_block(0, block_size, source); + self.dist = SecretDistribution::BinaryBlock(block_size); + } + + pub fn fill_zero(&mut self) { + self.data.zero(); + self.dist = SecretDistribution::ZERO; + } +} diff --git a/core/src/test_fft64/automorphism_key.rs b/core/src/test_fft64/automorphism_key.rs index f23b619..93cd5d6 100644 --- a/core/src/test_fft64/automorphism_key.rs +++ b/core/src/test_fft64/automorphism_key.rs @@ -2,7 +2,8 @@ use backend::{FFT64, Module, ScalarZnxOps, ScratchOwned, Stats, VecZnxOps}; use sampling::source::Source; use crate::{ - AutomorphismKey, GLWECiphertextFourier, GLWEPlaintext, GLWESecret, GetRow, Infos, test_fft64::log2_std_noise_gglwe_product, + AutomorphismKey, FourierGLWECiphertext, GLWEPlaintext, GLWESecret, GetRow, Infos, div_ceil, + test_fft64::log2_std_noise_gglwe_product, }; #[test] @@ -69,7 +70,7 @@ fn test_automorphism( let mut scratch: ScratchOwned = ScratchOwned::new( AutomorphismKey::generate_from_sk_scratch_space(&module, basek, k_apply, rank) - | GLWECiphertextFourier::decrypt_scratch_space(&module, basek, k_out) + | FourierGLWECiphertext::decrypt_scratch_space(&module, basek, k_out) | AutomorphismKey::automorphism_scratch_space(&module, basek, k_out, k_in, k_apply, digits, rank), ); @@ -101,7 +102,7 @@ fn test_automorphism( // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0) auto_key_out.automorphism(&module, &auto_key_in, &auto_key_apply, scratch.borrow()); - let mut ct_glwe_dft: GLWECiphertextFourier, FFT64> = GLWECiphertextFourier::alloc(&module, basek, k_out, rank); + let mut ct_glwe_dft: FourierGLWECiphertext, FFT64> = FourierGLWECiphertext::alloc(&module, basek, k_out, rank); let mut pt: GLWEPlaintext> = GLWEPlaintext::alloc(&module, basek, k_out); let mut sk_auto: GLWESecret, FFT64> = GLWESecret::alloc(&module, rank); @@ -183,7 +184,7 @@ fn test_automorphism_inplace( let mut scratch: ScratchOwned = ScratchOwned::new( AutomorphismKey::generate_from_sk_scratch_space(&module, basek, k_apply, rank) - | GLWECiphertextFourier::decrypt_scratch_space(&module, basek, k_in) + | FourierGLWECiphertext::decrypt_scratch_space(&module, basek, k_in) | AutomorphismKey::automorphism_inplace_scratch_space(&module, basek, k_in, k_apply, digits, rank), ); @@ -215,7 +216,7 @@ fn test_automorphism_inplace( // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0) auto_key.automorphism_inplace(&module, &auto_key_apply, scratch.borrow()); - let mut ct_glwe_dft: GLWECiphertextFourier, FFT64> = GLWECiphertextFourier::alloc(&module, basek, k_in, rank); + let mut ct_glwe_dft: FourierGLWECiphertext, FFT64> = FourierGLWECiphertext::alloc(&module, basek, k_in, rank); let mut pt: GLWEPlaintext> = GLWEPlaintext::alloc(&module, basek, k_in); let mut sk_auto: GLWESecret, FFT64> = GLWESecret::alloc(&module, rank); diff --git a/core/src/test_fft64/gglwe.rs b/core/src/test_fft64/gglwe.rs index 91798d2..bde6308 100644 --- a/core/src/test_fft64/gglwe.rs +++ b/core/src/test_fft64/gglwe.rs @@ -2,7 +2,7 @@ use backend::{FFT64, Module, ScalarZnx, ScalarZnxAlloc, ScalarZnxToMut, ScratchO use sampling::source::Source; use crate::{ - GGSWCiphertext, GLWECiphertextFourier, GLWEPlaintext, GLWESecret, GLWESwitchingKey, GetRow, Infos, + FourierGLWECiphertext, GGSWCiphertext, GLWEPlaintext, GLWESecret, GLWESwitchingKey, GetRow, Infos, div_ceil, test_fft64::{log2_std_noise_gglwe_product, noise_ggsw_product}, }; @@ -145,7 +145,7 @@ fn test_encrypt_sk(log_n: usize, basek: usize, k_ksk: usize, digits: usize, rank let mut scratch: ScratchOwned = ScratchOwned::new( GLWESwitchingKey::encrypt_sk_scratch_space(&module, basek, k_ksk, rank_out) - | GLWECiphertextFourier::decrypt_scratch_space(&module, basek, k_ksk), + | FourierGLWECiphertext::decrypt_scratch_space(&module, basek, k_ksk), ); let mut sk_in: GLWESecret, FFT64> = GLWESecret::alloc(&module, rank_in); @@ -164,8 +164,8 @@ fn test_encrypt_sk(log_n: usize, basek: usize, k_ksk: usize, digits: usize, rank scratch.borrow(), ); - let mut ct_glwe_fourier: GLWECiphertextFourier, FFT64> = - GLWECiphertextFourier::alloc(&module, basek, k_ksk, rank_out); + let mut ct_glwe_fourier: FourierGLWECiphertext, FFT64> = + FourierGLWECiphertext::alloc(&module, basek, k_ksk, rank_out); (0..ksk.rank_in()).for_each(|col_i| { (0..ksk.rows()).for_each(|row_i| { @@ -234,7 +234,7 @@ fn test_key_switch( let mut scratch: ScratchOwned = ScratchOwned::new( GLWESwitchingKey::encrypt_sk_scratch_space(&module, basek, k_ksk, rank_in_s0s1 | rank_out_s0s1) - | GLWECiphertextFourier::decrypt_scratch_space(&module, basek, k_out) + | FourierGLWECiphertext::decrypt_scratch_space(&module, basek, k_out) | GLWESwitchingKey::keyswitch_scratch_space( &module, basek, @@ -281,8 +281,8 @@ fn test_key_switch( // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0) ct_gglwe_s0s2.keyswitch(&module, &ct_gglwe_s0s1, &ct_gglwe_s1s2, scratch.borrow()); - let mut ct_glwe_dft: GLWECiphertextFourier, FFT64> = - GLWECiphertextFourier::alloc(&module, basek, k_out, rank_out_s1s2); + let mut ct_glwe_dft: FourierGLWECiphertext, FFT64> = + FourierGLWECiphertext::alloc(&module, basek, k_out, rank_out_s1s2); let mut pt: GLWEPlaintext> = GLWEPlaintext::alloc(&module, basek, k_out); (0..ct_gglwe_s0s2.rank_in()).for_each(|col_i| { @@ -346,7 +346,7 @@ fn test_key_switch_inplace( let mut scratch: ScratchOwned = ScratchOwned::new( GLWESwitchingKey::encrypt_sk_scratch_space(&module, basek, k_ksk, rank_out) - | GLWECiphertextFourier::decrypt_scratch_space(&module, basek, k_ksk) + | FourierGLWECiphertext::decrypt_scratch_space(&module, basek, k_ksk) | GLWESwitchingKey::keyswitch_inplace_scratch_space(&module, basek, k_ct, k_ksk, digits, rank_out), ); @@ -386,7 +386,7 @@ fn test_key_switch_inplace( let ct_gglwe_s0s2: GLWESwitchingKey, FFT64> = ct_gglwe_s0s1; - let mut ct_glwe_dft: GLWECiphertextFourier, FFT64> = GLWECiphertextFourier::alloc(&module, basek, k_ct, rank_out); + let mut ct_glwe_dft: FourierGLWECiphertext, FFT64> = FourierGLWECiphertext::alloc(&module, basek, k_ct, rank_out); let mut pt: GLWEPlaintext> = GLWEPlaintext::alloc(&module, basek, k_ct); (0..ct_gglwe_s0s2.rank_in()).for_each(|col_i| { @@ -455,7 +455,7 @@ fn test_external_product( let mut scratch: ScratchOwned = ScratchOwned::new( GLWESwitchingKey::encrypt_sk_scratch_space(&module, basek, k_in, rank_out) - | GLWECiphertextFourier::decrypt_scratch_space(&module, basek, k_out) + | FourierGLWECiphertext::decrypt_scratch_space(&module, basek, k_out) | GLWESwitchingKey::external_product_scratch_space(&module, basek, k_out, k_in, k_ggsw, digits, rank_out) | GGSWCiphertext::encrypt_sk_scratch_space(&module, basek, k_ggsw, rank_out), ); @@ -494,7 +494,7 @@ fn test_external_product( // gglwe_(m) (x) RGSW_(X^k) = gglwe_(m * X^k) ct_gglwe_out.external_product(&module, &ct_gglwe_in, &ct_rgsw, scratch.borrow()); - let mut ct_glwe_dft: GLWECiphertextFourier, FFT64> = GLWECiphertextFourier::alloc(&module, basek, k_out, rank_out); + let mut ct_glwe_dft: FourierGLWECiphertext, FFT64> = FourierGLWECiphertext::alloc(&module, basek, k_out, rank_out); let mut pt: GLWEPlaintext> = GLWEPlaintext::alloc(&module, basek, k_out); (0..rank_in).for_each(|i| { @@ -575,7 +575,7 @@ fn test_external_product_inplace( let mut scratch: ScratchOwned = ScratchOwned::new( GLWESwitchingKey::encrypt_sk_scratch_space(&module, basek, k_ct, rank_out) - | GLWECiphertextFourier::decrypt_scratch_space(&module, basek, k_ct) + | FourierGLWECiphertext::decrypt_scratch_space(&module, basek, k_ct) | GLWESwitchingKey::external_product_inplace_scratch_space(&module, basek, k_ct, k_ggsw, digits, rank_out) | GGSWCiphertext::encrypt_sk_scratch_space(&module, basek, k_ggsw, rank_out), ); @@ -614,7 +614,7 @@ fn test_external_product_inplace( // gglwe_(m) (x) RGSW_(X^k) = gglwe_(m * X^k) ct_gglwe.external_product_inplace(&module, &ct_rgsw, scratch.borrow()); - let mut ct_glwe_dft: GLWECiphertextFourier, FFT64> = GLWECiphertextFourier::alloc(&module, basek, k_ct, rank_out); + let mut ct_glwe_dft: FourierGLWECiphertext, FFT64> = FourierGLWECiphertext::alloc(&module, basek, k_ct, rank_out); let mut pt: GLWEPlaintext> = GLWEPlaintext::alloc(&module, basek, k_ct); (0..rank_in).for_each(|i| { diff --git a/core/src/test_fft64/ggsw.rs b/core/src/test_fft64/ggsw.rs index 3e6ee8b..bcfb950 100644 --- a/core/src/test_fft64/ggsw.rs +++ b/core/src/test_fft64/ggsw.rs @@ -5,7 +5,7 @@ use backend::{ use sampling::source::Source; use crate::{ - GGSWCiphertext, GLWECiphertextFourier, GLWEPlaintext, GLWESecret, GLWESwitchingKey, GetRow, Infos, TensorKey, + FourierGLWECiphertext, GGSWCiphertext, GLWEPlaintext, GLWESecret, GLWESwitchingKey, GetRow, Infos, TensorKey, automorphism::AutomorphismKey, test_fft64::{noise_ggsw_keyswitch, noise_ggsw_product}, }; @@ -139,7 +139,7 @@ fn test_encrypt_sk(log_n: usize, basek: usize, k: usize, digits: usize, rank: us let mut scratch: ScratchOwned = ScratchOwned::new( GGSWCiphertext::encrypt_sk_scratch_space(&module, basek, k, rank) - | GLWECiphertextFourier::decrypt_scratch_space(&module, basek, k), + | FourierGLWECiphertext::decrypt_scratch_space(&module, basek, k), ); let mut sk: GLWESecret, FFT64> = GLWESecret::alloc(&module, rank); @@ -155,7 +155,7 @@ fn test_encrypt_sk(log_n: usize, basek: usize, k: usize, digits: usize, rank: us scratch.borrow(), ); - let mut ct_glwe_fourier: GLWECiphertextFourier, FFT64> = GLWECiphertextFourier::alloc(&module, basek, k, rank); + let mut ct_glwe_fourier: FourierGLWECiphertext, FFT64> = FourierGLWECiphertext::alloc(&module, basek, k, rank); let mut pt_dft: VecZnxDft, FFT64> = module.new_vec_znx_dft(1, ct.size()); let mut pt_big: VecZnxBig, FFT64> = module.new_vec_znx_big(1, ct.size()); @@ -221,7 +221,7 @@ fn test_keyswitch( let mut scratch: ScratchOwned = ScratchOwned::new( GGSWCiphertext::encrypt_sk_scratch_space(&module, basek, k_in, rank) - | GLWECiphertextFourier::decrypt_scratch_space(&module, basek, k_out) + | FourierGLWECiphertext::decrypt_scratch_space(&module, basek, k_out) | GLWESwitchingKey::encrypt_sk_scratch_space(&module, basek, k_ksk, rank) | TensorKey::generate_from_sk_scratch_space(&module, basek, k_tsk, rank) | GGSWCiphertext::keyswitch_scratch_space( @@ -269,7 +269,7 @@ fn test_keyswitch( ct_out.keyswitch(&module, &ct_in, &ksk, &tsk, scratch.borrow()); - let mut ct_glwe_fourier: GLWECiphertextFourier, FFT64> = GLWECiphertextFourier::alloc(&module, basek, k_out, rank); + let mut ct_glwe_fourier: FourierGLWECiphertext, FFT64> = FourierGLWECiphertext::alloc(&module, basek, k_out, rank); let mut pt_dft: VecZnxDft, FFT64> = module.new_vec_znx_dft(1, ct_out.size()); let mut pt_big: VecZnxBig, FFT64> = module.new_vec_znx_big(1, ct_out.size()); @@ -348,7 +348,7 @@ fn test_keyswitch_inplace( let mut scratch: ScratchOwned = ScratchOwned::new( GGSWCiphertext::encrypt_sk_scratch_space(&module, basek, k_ct, rank) - | GLWECiphertextFourier::decrypt_scratch_space(&module, basek, k_ct) + | FourierGLWECiphertext::decrypt_scratch_space(&module, basek, k_ct) | GLWESwitchingKey::encrypt_sk_scratch_space(&module, basek, k_ksk, rank) | TensorKey::generate_from_sk_scratch_space(&module, basek, k_tsk, rank) | GGSWCiphertext::keyswitch_inplace_scratch_space(&module, basek, k_ct, k_ksk, digits, k_tsk, digits, rank), @@ -394,7 +394,7 @@ fn test_keyswitch_inplace( ct.keyswitch_inplace(&module, &ksk, &tsk, scratch.borrow()); - let mut ct_glwe_fourier: GLWECiphertextFourier, FFT64> = GLWECiphertextFourier::alloc(&module, basek, k_ct, rank); + let mut ct_glwe_fourier: FourierGLWECiphertext, FFT64> = FourierGLWECiphertext::alloc(&module, basek, k_ct, rank); let mut pt_dft: VecZnxDft, FFT64> = module.new_vec_znx_dft(1, ct.size()); let mut pt_big: VecZnxBig, FFT64> = module.new_vec_znx_big(1, ct.size()); @@ -483,7 +483,7 @@ fn test_automorphism( let mut scratch: ScratchOwned = ScratchOwned::new( GGSWCiphertext::encrypt_sk_scratch_space(&module, basek, k_in, rank) - | GLWECiphertextFourier::decrypt_scratch_space(&module, basek, k_out) + | FourierGLWECiphertext::decrypt_scratch_space(&module, basek, k_out) | AutomorphismKey::generate_from_sk_scratch_space(&module, basek, k_ksk, rank) | TensorKey::generate_from_sk_scratch_space(&module, basek, k_tsk, rank) | GGSWCiphertext::automorphism_scratch_space( @@ -530,7 +530,7 @@ fn test_automorphism( module.scalar_znx_automorphism_inplace(p, &mut pt_scalar, 0); - let mut ct_glwe_fourier: GLWECiphertextFourier, FFT64> = GLWECiphertextFourier::alloc(&module, basek, k_out, rank); + let mut ct_glwe_fourier: FourierGLWECiphertext, FFT64> = FourierGLWECiphertext::alloc(&module, basek, k_out, rank); let mut pt_dft: VecZnxDft, FFT64> = module.new_vec_znx_dft(1, ct_out.size()); let mut pt_big: VecZnxBig, FFT64> = module.new_vec_znx_big(1, ct_out.size()); @@ -608,7 +608,7 @@ fn test_automorphism_inplace( let mut scratch: ScratchOwned = ScratchOwned::new( GGSWCiphertext::encrypt_sk_scratch_space(&module, basek, k_ct, rank) - | GLWECiphertextFourier::decrypt_scratch_space(&module, basek, k_ct) + | FourierGLWECiphertext::decrypt_scratch_space(&module, basek, k_ct) | AutomorphismKey::generate_from_sk_scratch_space(&module, basek, k_ksk, rank) | TensorKey::generate_from_sk_scratch_space(&module, basek, k_tsk, rank) | GGSWCiphertext::automorphism_inplace_scratch_space(&module, basek, k_ct, k_ksk, digits, k_tsk, digits, rank), @@ -653,7 +653,7 @@ fn test_automorphism_inplace( module.scalar_znx_automorphism_inplace(p, &mut pt_scalar, 0); - let mut ct_glwe_fourier: GLWECiphertextFourier, FFT64> = GLWECiphertextFourier::alloc(&module, basek, k_ct, rank); + let mut ct_glwe_fourier: FourierGLWECiphertext, FFT64> = FourierGLWECiphertext::alloc(&module, basek, k_ct, rank); let mut pt_dft: VecZnxDft, FFT64> = module.new_vec_znx_dft(1, ct.size()); let mut pt_big: VecZnxBig, FFT64> = module.new_vec_znx_big(1, ct.size()); @@ -737,7 +737,7 @@ fn test_external_product( pt_ggsw_rhs.to_mut().raw_mut()[k] = 1; //X^{k} let mut scratch: ScratchOwned = ScratchOwned::new( - GLWECiphertextFourier::decrypt_scratch_space(&module, basek, k_out) + FourierGLWECiphertext::decrypt_scratch_space(&module, basek, k_out) | GGSWCiphertext::encrypt_sk_scratch_space(&module, basek, k_ggsw, rank) | GGSWCiphertext::external_product_scratch_space(&module, basek, k_out, k_in, k_ggsw, digits, rank), ); @@ -767,7 +767,7 @@ fn test_external_product( ct_ggsw_lhs_out.external_product(&module, &ct_ggsw_lhs_in, &ct_ggsw_rhs, scratch.borrow()); - let mut ct_glwe_fourier: GLWECiphertextFourier, FFT64> = GLWECiphertextFourier::alloc(&module, basek, k_out, rank); + let mut ct_glwe_fourier: FourierGLWECiphertext, FFT64> = FourierGLWECiphertext::alloc(&module, basek, k_out, rank); let mut pt: GLWEPlaintext> = GLWEPlaintext::alloc(&module, basek, k_out); let mut pt_dft: VecZnxDft, FFT64> = module.new_vec_znx_dft(1, ct_ggsw_lhs_out.size()); let mut pt_big: VecZnxBig, FFT64> = module.new_vec_znx_big(1, ct_ggsw_lhs_out.size()); @@ -857,7 +857,7 @@ fn test_external_product_inplace(log_n: usize, basek: usize, k_ct: usize, k_ggsw pt_ggsw_rhs.to_mut().raw_mut()[k] = 1; //X^{k} let mut scratch: ScratchOwned = ScratchOwned::new( - GLWECiphertextFourier::decrypt_scratch_space(&module, basek, k_ct) + FourierGLWECiphertext::decrypt_scratch_space(&module, basek, k_ct) | GGSWCiphertext::encrypt_sk_scratch_space(&module, basek, k_ggsw, rank) | GGSWCiphertext::external_product_inplace_scratch_space(&module, basek, k_ct, k_ggsw, digits, rank), ); @@ -887,7 +887,7 @@ fn test_external_product_inplace(log_n: usize, basek: usize, k_ct: usize, k_ggsw ct_ggsw_lhs.external_product_inplace(&module, &ct_ggsw_rhs, scratch.borrow()); - let mut ct_glwe_fourier: GLWECiphertextFourier, FFT64> = GLWECiphertextFourier::alloc(&module, basek, k_ct, rank); + let mut ct_glwe_fourier: FourierGLWECiphertext, FFT64> = FourierGLWECiphertext::alloc(&module, basek, k_ct, rank); let mut pt: GLWEPlaintext> = GLWEPlaintext::alloc(&module, basek, k_ct); let mut pt_dft: VecZnxDft, FFT64> = module.new_vec_znx_dft(1, ct_ggsw_lhs.size()); let mut pt_big: VecZnxBig, FFT64> = module.new_vec_znx_big(1, ct_ggsw_lhs.size()); diff --git a/core/src/test_fft64/glwe.rs b/core/src/test_fft64/glwe.rs index 4859ad1..7a32343 100644 --- a/core/src/test_fft64/glwe.rs +++ b/core/src/test_fft64/glwe.rs @@ -6,7 +6,7 @@ use itertools::izip; use sampling::source::Source; use crate::{ - GGSWCiphertext, GLWECiphertext, GLWECiphertextFourier, GLWEPlaintext, GLWEPublicKey, GLWESecret, Infos, + FourierGLWECiphertext, GGSWCiphertext, GLWECiphertext, GLWEPlaintext, GLWEPublicKey, GLWESecret, Infos, automorphism::AutomorphismKey, keyswitch_key::GLWESwitchingKey, test_fft64::{log2_std_noise_gglwe_product, noise_ggsw_product}, @@ -207,11 +207,11 @@ fn test_encrypt_zero_sk(log_n: usize, basek: usize, k_ct: usize, sigma: f64, ran let mut sk: GLWESecret, FFT64> = GLWESecret::alloc(&module, rank); sk.fill_ternary_prob(&module, 0.5, &mut source_xs); - let mut ct_dft: GLWECiphertextFourier, FFT64> = GLWECiphertextFourier::alloc(&module, basek, k_ct, rank); + let mut ct_dft: FourierGLWECiphertext, FFT64> = FourierGLWECiphertext::alloc(&module, basek, k_ct, rank); let mut scratch: ScratchOwned = ScratchOwned::new( - GLWECiphertextFourier::decrypt_scratch_space(&module, basek, k_ct) - | GLWECiphertextFourier::encrypt_sk_scratch_space(&module, basek, k_ct, rank), + FourierGLWECiphertext::decrypt_scratch_space(&module, basek, k_ct) + | FourierGLWECiphertext::encrypt_sk_scratch_space(&module, basek, k_ct, rank), ); ct_dft.encrypt_zero_sk( diff --git a/core/src/test_fft64/glwe_fourier.rs b/core/src/test_fft64/glwe_fourier.rs index 48a0f0d..fd54f57 100644 --- a/core/src/test_fft64/glwe_fourier.rs +++ b/core/src/test_fft64/glwe_fourier.rs @@ -1,5 +1,5 @@ use crate::{ - GGSWCiphertext, GLWECiphertext, GLWECiphertextFourier, GLWEOps, GLWEPlaintext, GLWESecret, GLWESwitchingKey, Infos, + FourierGLWECiphertext, GGSWCiphertext, GLWECiphertext, GLWEOps, GLWEPlaintext, GLWESecret, GLWESwitchingKey, Infos, div_ceil, test_fft64::{log2_std_noise_gglwe_product, noise_ggsw_product}, }; use backend::{FFT64, FillUniform, Module, ScalarZnx, ScalarZnxAlloc, ScratchOwned, Stats, VecZnxOps, ZnxViewMut}; @@ -90,10 +90,10 @@ fn test_keyswitch( let mut ksk: GLWESwitchingKey, FFT64> = GLWESwitchingKey::alloc(&module, basek, k_ksk, rows, digits, rank_in, rank_out); let mut ct_glwe_in: GLWECiphertext> = GLWECiphertext::alloc(&module, basek, k_in, rank_in); - let mut ct_glwe_dft_in: GLWECiphertextFourier, FFT64> = GLWECiphertextFourier::alloc(&module, basek, k_in, rank_in); + let mut ct_glwe_dft_in: FourierGLWECiphertext, FFT64> = FourierGLWECiphertext::alloc(&module, basek, k_in, rank_in); let mut ct_glwe_out: GLWECiphertext> = GLWECiphertext::alloc(&module, basek, k_out, rank_out); - let mut ct_glwe_dft_out: GLWECiphertextFourier, FFT64> = - GLWECiphertextFourier::alloc(&module, basek, k_out, rank_out); + let mut ct_glwe_dft_out: FourierGLWECiphertext, FFT64> = + FourierGLWECiphertext::alloc(&module, basek, k_out, rank_out); let mut pt_want: GLWEPlaintext> = GLWEPlaintext::alloc(&module, basek, k_in); let mut pt_have: GLWEPlaintext> = GLWEPlaintext::alloc(&module, basek, k_out); @@ -110,7 +110,7 @@ fn test_keyswitch( GLWESwitchingKey::encrypt_sk_scratch_space(&module, basek, k_ksk, rank_out) | GLWECiphertext::decrypt_scratch_space(&module, basek, k_out) | GLWECiphertext::encrypt_sk_scratch_space(&module, basek, k_in) - | GLWECiphertextFourier::keyswitch_scratch_space( + | FourierGLWECiphertext::keyswitch_scratch_space( &module, basek, ct_glwe_out.k(), @@ -185,7 +185,7 @@ fn test_keyswitch_inplace(log_n: usize, basek: usize, k_ct: usize, k_ksk: usize, let mut ksk: GLWESwitchingKey, FFT64> = GLWESwitchingKey::alloc(&module, basek, k_ksk, rows, digits, rank, rank); let mut ct_glwe: GLWECiphertext> = GLWECiphertext::alloc(&module, basek, k_ct, rank); - let mut ct_rlwe_dft: GLWECiphertextFourier, FFT64> = GLWECiphertextFourier::alloc(&module, basek, k_ct, rank); + let mut ct_rlwe_dft: FourierGLWECiphertext, FFT64> = FourierGLWECiphertext::alloc(&module, basek, k_ct, rank); let mut pt_want: GLWEPlaintext> = GLWEPlaintext::alloc(&module, basek, k_ct); let mut pt_have: GLWEPlaintext> = GLWEPlaintext::alloc(&module, basek, k_ct); @@ -202,7 +202,7 @@ fn test_keyswitch_inplace(log_n: usize, basek: usize, k_ct: usize, k_ksk: usize, GLWESwitchingKey::encrypt_sk_scratch_space(&module, basek, ksk.k(), rank) | GLWECiphertext::decrypt_scratch_space(&module, basek, ct_glwe.k()) | GLWECiphertext::encrypt_sk_scratch_space(&module, basek, ct_glwe.k()) - | GLWECiphertextFourier::keyswitch_inplace_scratch_space(&module, basek, ct_rlwe_dft.k(), ksk.k(), digits, rank), + | FourierGLWECiphertext::keyswitch_inplace_scratch_space(&module, basek, ct_rlwe_dft.k(), ksk.k(), digits, rank), ); let mut sk_in: GLWESecret, FFT64> = GLWESecret::alloc(&module, rank); @@ -278,8 +278,8 @@ fn test_external_product( let mut ct_ggsw: GGSWCiphertext, FFT64> = GGSWCiphertext::alloc(&module, basek, k_ggsw, rows, digits, rank); let mut ct_in: GLWECiphertext> = GLWECiphertext::alloc(&module, basek, k_in, rank); let mut ct_out: GLWECiphertext> = GLWECiphertext::alloc(&module, basek, k_out, rank); - let mut ct_in_dft: GLWECiphertextFourier, FFT64> = GLWECiphertextFourier::alloc(&module, basek, k_in, rank); - let mut ct_out_dft: GLWECiphertextFourier, FFT64> = GLWECiphertextFourier::alloc(&module, basek, k_out, rank); + let mut ct_in_dft: FourierGLWECiphertext, FFT64> = FourierGLWECiphertext::alloc(&module, basek, k_in, rank); + let mut ct_out_dft: FourierGLWECiphertext, FFT64> = FourierGLWECiphertext::alloc(&module, basek, k_out, rank); let mut pt_rgsw: ScalarZnx> = module.new_scalar_znx(1); let mut pt_want: GLWEPlaintext> = GLWEPlaintext::alloc(&module, basek, k_in); let mut pt_have: GLWEPlaintext> = GLWEPlaintext::alloc(&module, basek, k_out); @@ -304,7 +304,7 @@ fn test_external_product( GGSWCiphertext::encrypt_sk_scratch_space(&module, basek, ct_ggsw.k(), rank) | GLWECiphertext::decrypt_scratch_space(&module, basek, ct_out.k()) | GLWECiphertext::encrypt_sk_scratch_space(&module, basek, ct_in.k()) - | GLWECiphertextFourier::external_product_scratch_space( + | FourierGLWECiphertext::external_product_scratch_space( &module, basek, ct_out.k(), @@ -384,7 +384,7 @@ fn test_external_product_inplace(log_n: usize, basek: usize, k_ct: usize, k_ggsw let mut ct_ggsw: GGSWCiphertext, FFT64> = GGSWCiphertext::alloc(&module, basek, k_ggsw, rows, digits, rank); let mut ct: GLWECiphertext> = GLWECiphertext::alloc(&module, basek, k_ct, rank); - let mut ct_rlwe_dft: GLWECiphertextFourier, FFT64> = GLWECiphertextFourier::alloc(&module, basek, k_ct, rank); + let mut ct_rlwe_dft: FourierGLWECiphertext, FFT64> = FourierGLWECiphertext::alloc(&module, basek, k_ct, rank); let mut pt_rgsw: ScalarZnx> = module.new_scalar_znx(1); let mut pt_want: GLWEPlaintext> = GLWEPlaintext::alloc(&module, basek, k_ct); let mut pt_have: GLWEPlaintext> = GLWEPlaintext::alloc(&module, basek, k_ct); @@ -409,7 +409,7 @@ fn test_external_product_inplace(log_n: usize, basek: usize, k_ct: usize, k_ggsw GGSWCiphertext::encrypt_sk_scratch_space(&module, basek, ct_ggsw.k(), rank) | GLWECiphertext::decrypt_scratch_space(&module, basek, ct.k()) | GLWECiphertext::encrypt_sk_scratch_space(&module, basek, ct.k()) - | GLWECiphertextFourier::external_product_inplace_scratch_space(&module, basek, ct.k(), ct_ggsw.k(), digits, rank), + | FourierGLWECiphertext::external_product_inplace_scratch_space(&module, basek, ct.k(), ct_ggsw.k(), digits, rank), ); let mut sk: GLWESecret, FFT64> = GLWESecret::alloc(&module, rank); diff --git a/core/src/test_fft64/tensor_key.rs b/core/src/test_fft64/tensor_key.rs index 579fec4..e9827cb 100644 --- a/core/src/test_fft64/tensor_key.rs +++ b/core/src/test_fft64/tensor_key.rs @@ -1,7 +1,7 @@ use backend::{FFT64, Module, ScalarZnxDftOps, ScratchOwned, Stats, VecZnxOps}; use sampling::source::Source; -use crate::{GLWECiphertextFourier, GLWEPlaintext, GLWESecret, GetRow, Infos, TensorKey}; +use crate::{FourierGLWECiphertext, GLWEPlaintext, GLWESecret, GetRow, Infos, TensorKey}; #[test] fn encrypt_sk() { @@ -42,7 +42,7 @@ fn test_encrypt_sk(log_n: usize, basek: usize, k: usize, sigma: f64, rank: usize scratch.borrow(), ); - let mut ct_glwe_fourier: GLWECiphertextFourier, FFT64> = GLWECiphertextFourier::alloc(&module, basek, k, rank); + let mut ct_glwe_fourier: FourierGLWECiphertext, FFT64> = FourierGLWECiphertext::alloc(&module, basek, k, rank); let mut pt: GLWEPlaintext> = GLWEPlaintext::alloc(&module, basek, k); let mut sk_ij = GLWESecret::alloc(&module, 1);